tools/testing/selftests/powerpc/mm/pkey_siginfo.c

Source file repositories/reference/linux-study-clean/tools/testing/selftests/powerpc/mm/pkey_siginfo.c

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/powerpc/mm/pkey_siginfo.c
Extension
.c
Size
9212 bytes
Lines
334
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

struct region {
	unsigned long rights;
	unsigned int *base;
	size_t size;
};

static void *protect(void *p)
{
	unsigned long rights;
	unsigned int *base;
	size_t size;
	int tid, i;

	tid = gettid();
	base = ((struct region *) p)->base;
	size = ((struct region *) p)->size;
	FAIL_IF_EXIT(!base);

	/* No read, write and execute restrictions */
	rights = 0;

	printf("tid %d, pkey permissions are %s\n", tid, pkey_rights(rights));

	/* Allocate the permissive pkey */
	perm_pkey = sys_pkey_alloc(0, rights);
	FAIL_IF_EXIT(perm_pkey < 0);

	/*
	 * Repeatedly try to protect the common region with a permissive
	 * pkey
	 */
	for (i = 0; i < NUM_ITERATIONS; i++) {
		/*
		 * Wait until the other thread has finished allocating the
		 * restrictive pkey or until the next iteration has begun
		 */
		pthread_barrier_wait(&iteration_barrier);

		/* Try to associate the permissive pkey with the region */
		FAIL_IF_EXIT(sys_pkey_mprotect(base, size, PROT_RWX,
					       perm_pkey));
	}

	/* Free the permissive pkey */
	sys_pkey_free(perm_pkey);

	return NULL;
}

static void *protect_access(void *p)
{
	size_t size, numinsns;
	unsigned int *base;
	int tid, i;

	tid = gettid();
	base = ((struct region *) p)->base;
	size = ((struct region *) p)->size;
	rights = ((struct region *) p)->rights;
	numinsns = size / sizeof(base[0]);
	FAIL_IF_EXIT(!base);

	/* Allocate the restrictive pkey */
	rest_pkey = sys_pkey_alloc(0, rights);
	FAIL_IF_EXIT(rest_pkey < 0);

	printf("tid %d, pkey permissions are %s\n", tid, pkey_rights(rights));
	printf("tid %d, %s randomly in range [%p, %p]\n", tid,
	       (rights == PKEY_DISABLE_EXECUTE) ? "execute" :
	       (rights == PKEY_DISABLE_WRITE)  ? "write" : "read",
	       base, base + numinsns);

	/*
	 * Repeatedly try to protect the common region with a restrictive
	 * pkey and read, write or execute from it
	 */
	for (i = 0; i < NUM_ITERATIONS; i++) {
		/*
		 * Wait until the other thread has finished allocating the
		 * permissive pkey or until the next iteration has begun
		 */
		pthread_barrier_wait(&iteration_barrier);

		/* Try to associate the restrictive pkey with the region */
		FAIL_IF_EXIT(sys_pkey_mprotect(base, size, PROT_RWX,
					       rest_pkey));

		/* Choose a random instruction word address from the region */
		fault_addr = base + (rand() % numinsns);
		fault_count = 0;

Annotation

Implementation Notes