tools/testing/selftests/namespaces/cred_change_test.c

Source file repositories/reference/linux-study-clean/tools/testing/selftests/namespaces/cred_change_test.c

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/namespaces/cred_change_test.c
Extension
.c
Size
16953 bytes
Lines
815
Domain
Support Tooling And Documentation
Bucket
tools
Inferred role
Support Tooling And Documentation: implementation source
Status
source implementation candidate

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

if (userns_fd < 0) {
			close(pipefd[1]);
			exit(1);
		}

		if (setns(userns_fd, CLONE_NEWUSER) < 0) {
			close(userns_fd);
			close(pipefd[1]);
			exit(1);
		}
		close(userns_fd);

		/* Get user namespace ID */
		fd = open("/proc/self/ns/user", O_RDONLY);
		if (fd < 0) {
			close(pipefd[1]);
			exit(1);
		}

		if (ioctl(fd, NS_GET_ID, &child_userns_id) < 0) {
			close(fd);
			close(pipefd[1]);
			exit(1);
		}
		close(fd);

		/* Send namespace ID to parent */
		write(pipefd[1], &child_userns_id, sizeof(child_userns_id));

		/*
		 * Perform multiple setuid() calls.
		 * Each setuid() triggers commit_creds() which should properly
		 * swap active references via switch_cred_namespaces().
		 */
		for (setuid_count = 0; setuid_count < 50; setuid_count++) {
			uid_t target_uid = (setuid_count % 10);
			if (setuid(target_uid) < 0) {
				if (errno != EPERM) {
					close(pipefd[1]);
					exit(1);
				}
			}
		}

		close(pipefd[1]);
		exit(0);
	}

	/* Parent process */
	close(pipefd[1]);

	if (read(pipefd[0], &userns_id, sizeof(userns_id)) != sizeof(userns_id)) {
		close(pipefd[0]);
		kill(pid, SIGKILL);
		waitpid(pid, NULL, 0);
		SKIP(return, "Failed to get namespace ID from child");
	}
	close(pipefd[0]);

	TH_LOG("Child user namespace ID: %llu", (unsigned long long)userns_id);

	/* Verify namespace is active while child is running */
	ret = sys_listns(&req, ns_ids, ARRAY_SIZE(ns_ids), 0);
	if (ret < 0) {
		kill(pid, SIGKILL);
		waitpid(pid, NULL, 0);
		if (errno == ENOSYS)
			SKIP(return, "listns() not supported");
		ASSERT_GE(ret, 0);
	}

	for (i = 0; i < ret; i++) {
		if (ns_ids[i] == userns_id) {
			found = true;
			break;
		}
	}
	ASSERT_TRUE(found);

	waitpid(pid, &status, 0);
	ASSERT_TRUE(WIFEXITED(status));
	ASSERT_EQ(WEXITSTATUS(status), 0);

	/* Verify namespace becomes inactive after child exits */
	ret = sys_listns(&req, ns_ids, ARRAY_SIZE(ns_ids), 0);
	ASSERT_GE(ret, 0);

	found = false;
	for (i = 0; i < ret; i++) {
		if (ns_ids[i] == userns_id) {

Annotation

Implementation Notes