Repository: opencontainers/runc
File: libcontainer/nsenter/nsexec.c (C)

Code before:
		ns->path[PATH_MAX - 1] = '\0';

		ns_to_join |= nstype(ns->type);
	} while ((namespace = strtok_r(NULL, ",", &saveptr)) != NULL);

	*ns_list = namespaces;
	*ns_len = len;
	return ns_to_join;
}

/*
 * Try to join all namespaces that are in the "allow" nsset, and return the
 * set we were able to successfully join. If a permission error is returned
 * from nsset(2), the namespace is skipped (non-permission errors are fatal).
 */
static nsset_t __join_namespaces(nsset_t allow, struct namespace_t *ns_list, size_t ns_len)
{
	nsset_t joined = 0;

	for (size_t i = 0; i < ns_len; i++) {
		struct namespace_t *ns = &ns_list[i];
		int type = nstype(ns->type);
		int err, saved_errno;

		if (!(type & allow)) {
			write_log(DEBUG, "skipping setns(%#x) into %s namespace (with path %s)",
				  type, ns->type, ns->path);
			continue;
		}

		err = setns(ns->fd, type);
		saved_errno = errno;
		write_log(DEBUG, "setns(%#x) into %s namespace (with path %s): %s",
			  type, ns->type, ns->path, strerror(errno));
		if (err < 0) {
			/* Skip permission errors. */
			if (saved_errno == EPERM)
				continue;
			bail("failed to setns into %s namespace", ns->type);
		}
		joined |= type;

		/*
		 * If we change user namespaces, make sure we switch to root in the
		 * namespace (this matches the logic for unshare(CLONE_NEWUSER)), lots
		 * of things can break if we aren't the right user. See
		 * <https://github.com/opencontainers/runc/issues/4466> for one example.
		 */
		if (type == CLONE_NEWUSER) {
			if (setresuid(0, 0, 0) < 0)
				bail("failed to become root in user namespace");

Review comment (suggestion):
Maybe we should check whether is this type ns has been joined before, or else it will make user confused for this log.

Code after:
		ns->path[PATH_MAX - 1] = '\0';

		ns_to_join |= nstype(ns->type);
	} while ((namespace = strtok_r(NULL, ",", &saveptr)) != NULL);

	*ns_list = namespaces;
	*ns_len = len;
	return ns_to_join;
}

/*
 * Try to join all namespaces that are in the "allow" nsset, and return the
 * set we were able to successfully join. If a permission error is returned
 * from nsset(2), the namespace is skipped (non-permission errors are fatal).
 */
static nsset_t __join_namespaces(nsset_t allow, struct namespace_t *ns_list, size_t ns_len)
{
	nsset_t joined = 0;

	for (size_t i = 0; i < ns_len; i++) {
		struct namespace_t *ns = &ns_list[i];
		int type = nstype(ns->type);
		int err, saved_errno;

		if (!(type & allow))
			continue;

		err = setns(ns->fd, type);
		saved_errno = errno;
		write_log(DEBUG, "setns(%#x) into %s namespace (with path %s): %s",
			  type, ns->type, ns->path, strerror(errno));
		if (err < 0) {
			/* Skip permission errors. */
			if (saved_errno == EPERM)
				continue;
			bail("failed to setns into %s namespace", ns->type);
		}
		joined |= type;

		/*
		 * If we change user namespaces, make sure we switch to root in the
		 * namespace (this matches the logic for unshare(CLONE_NEWUSER)), lots
		 * of things can break if we aren't the right user. See
		 * <https://github.com/opencontainers/runc/issues/4466> for one example.
		 */
		if (type == CLONE_NEWUSER) {
			if (setresuid(0, 0, 0) < 0)
				bail("failed to become root in user namespace");
		}

		close(ns->fd);