tools/testing/selftests/arm64/gcs/libc-gcs.c

Source file repositories/reference/linux-study-clean/tools/testing/selftests/arm64/gcs/libc-gcs.c

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/arm64/gcs/libc-gcs.c
Extension
.c
Size
17480 bytes
Lines
730
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 (pid == -1) {
			ksft_print_msg("wait() failed: %s",
				       strerror(errno));
			goto error;
		}

		/*
		 * This should never happen but it's hard to flag in
		 * the framework.
		 */
		if (pid != child)
			continue;

		if (WIFEXITED(status) || WIFSIGNALED(status))
			ksft_exit_fail_msg("Child died unexpectedly\n");

		if (!WIFSTOPPED(status))
			goto error;

		sig = WSTOPSIG(status);

		if (ptrace(PTRACE_GETSIGINFO, pid, NULL, &si)) {
			if (errno == ESRCH) {
				ASSERT_NE(errno, ESRCH);
				return;
			}

			if (errno == EINVAL) {
				sig = 0; /* bust group-stop */
				goto cont;
			}

			ksft_print_msg("PTRACE_GETSIGINFO: %s\n",
				       strerror(errno));
			goto error;
		}

		if (sig == SIGSTOP && si.si_code == SI_TKILL &&
		    si.si_pid == pid)
			break;

	cont:
		if (ptrace(PTRACE_CONT, pid, NULL, sig)) {
			if (errno == ESRCH) {
				ASSERT_NE(errno, ESRCH);
				return;
			}

			ksft_print_msg("PTRACE_CONT: %s\n", strerror(errno));
			goto error;
		}
	}

	/* Where is the child GCS? */
	iov.iov_base = &child_gcs;
	iov.iov_len = sizeof(child_gcs);
	ret = ptrace(PTRACE_GETREGSET, child, NT_ARM_GCS, &iov);
	if (ret != 0) {
		ksft_print_msg("Failed to read child GCS state: %s (%d)\n",
			       strerror(errno), errno);
		goto error;
	}

	/* We should have inherited GCS over fork(), confirm */
	if (!(child_gcs.features_enabled & PR_SHADOW_STACK_ENABLE)) {
		ASSERT_TRUE(child_gcs.features_enabled &
			    PR_SHADOW_STACK_ENABLE);
		goto error;
	}

	gcspr = child_gcs.gcspr_el0;
	ksft_print_msg("Child GCSPR 0x%lx, flags %llx, locked %llx\n",
		       gcspr, child_gcs.features_enabled,
		       child_gcs.features_locked);

	/* Ideally we'd cross check with the child memory map */

	errno = 0;
	val = ptrace(PTRACE_PEEKDATA, child, (void *)gcspr, NULL);
	ret = errno;
	if (ret != 0)
		ksft_print_msg("PTRACE_PEEKDATA failed: %s (%d)\n",
			       strerror(ret), ret);
	EXPECT_EQ(ret, 0);

	/* The child should be in a function, the GCSPR shouldn't be 0 */
	EXPECT_NE(val, 0);

	/* Same thing via process_vm_readv() */
	local_iov.iov_base = &rval;

Annotation

Implementation Notes