proc: test ProtectionKey in proc-empty-vm test

Check ProtectionKey field in /proc/*/smaps output, if system supports
protection keys feature.

[adobriyan@gmail.com: test support in the beginning of the program, use syscall, not glibc pkey_alloc(3) which may not compile]

Link: https://lkml.kernel.org/r/ac05efa7-d2a0-48ad-b704-ffdd5450582e@p183
Signed-off-by: Swarup Laxman Kotiaklapudi <swarupkotikalapudi@gmail.com>
Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
Reviewed-by: Swarup Laxman Kotikalapudi<swarupkotikalapudi@gmail.com>
Tested-by: Swarup Laxman Kotikalapudi<swarupkotikalapudi@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
Swarup Laxman Kotiaklapudi 2023-10-27 17:26:24 +03:00 committed by Andrew Morton
parent 20e34aa7e0
commit bf5add391e
1 changed files with 63 additions and 20 deletions

View File

@ -23,6 +23,9 @@
* /proc/${pid}/smaps
* /proc/${pid}/smaps_rollup
*/
#undef _GNU_SOURCE
#define _GNU_SOURCE
#undef NDEBUG
#include <assert.h>
#include <errno.h>
@ -34,6 +37,7 @@
#include <sys/mman.h>
#include <sys/ptrace.h>
#include <sys/resource.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
@ -42,6 +46,43 @@
#define TEST_VSYSCALL
#endif
#if defined __amd64__
#ifndef SYS_pkey_alloc
#define SYS_pkey_alloc 330
#endif
#ifndef SYS_pkey_free
#define SYS_pkey_free 331
#endif
#elif defined __i386__
#ifndef SYS_pkey_alloc
#define SYS_pkey_alloc 381
#endif
#ifndef SYS_pkey_free
#define SYS_pkey_free 382
#endif
#else
#error "SYS_pkey_alloc"
#endif
static int g_protection_key_support;
static int protection_key_support(void)
{
long rv = syscall(SYS_pkey_alloc, 0, 0);
if (rv > 0) {
syscall(SYS_pkey_free, (int)rv);
return 1;
} else if (rv == -1 && errno == ENOSYS) {
return 0;
} else if (rv == -1 && errno == EINVAL) {
// ospke=n
return 0;
} else {
fprintf(stderr, "%s: error: rv %ld, errno %d\n", __func__, rv, errno);
exit(EXIT_FAILURE);
}
}
/*
* 0: vsyscall VMA doesn't exist vsyscall=none
* 1: vsyscall VMA is --xp vsyscall=xonly
@ -84,10 +125,6 @@ static const char proc_pid_smaps_vsyscall_1[] =
"SwapPss: 0 kB\n"
"Locked: 0 kB\n"
"THPeligible: 0\n"
/*
* "ProtectionKey:" field is conditional. It is possible to check it as well,
* but I don't have such machine.
*/
;
static const char proc_pid_smaps_vsyscall_2[] =
@ -115,10 +152,6 @@ static const char proc_pid_smaps_vsyscall_2[] =
"SwapPss: 0 kB\n"
"Locked: 0 kB\n"
"THPeligible: 0\n"
/*
* "ProtectionKey:" field is conditional. It is possible to check it as well,
* but I'm too tired.
*/
;
static void sigaction_SIGSEGV(int _, siginfo_t *__, void *___)
@ -240,19 +273,27 @@ static int test_proc_pid_smaps(pid_t pid)
}
perror("open /proc/${pid}/smaps");
return EXIT_FAILURE;
} else {
ssize_t rv = read(fd, buf, sizeof(buf));
close(fd);
if (g_vsyscall == 0) {
assert(rv == 0);
} else {
size_t len = strlen(g_proc_pid_smaps_vsyscall);
/* TODO "ProtectionKey:" */
assert(rv > len);
assert(memcmp(buf, g_proc_pid_smaps_vsyscall, len) == 0);
}
return EXIT_SUCCESS;
}
ssize_t rv = read(fd, buf, sizeof(buf));
close(fd);
assert(0 <= rv);
assert(rv <= sizeof(buf));
if (g_vsyscall == 0) {
assert(rv == 0);
} else {
size_t len = strlen(g_proc_pid_smaps_vsyscall);
assert(rv > len);
assert(memcmp(buf, g_proc_pid_smaps_vsyscall, len) == 0);
if (g_protection_key_support) {
#define PROTECTION_KEY "ProtectionKey: 0\n"
assert(memmem(buf, rv, PROTECTION_KEY, strlen(PROTECTION_KEY)));
}
}
return EXIT_SUCCESS;
}
static const char g_smaps_rollup[] =
@ -419,6 +460,8 @@ int main(void)
abort();
}
g_protection_key_support = protection_key_support();
pid_t pid = fork();
if (pid == -1) {
perror("fork");