|
23 | 23 | * /proc/${pid}/smaps
|
24 | 24 | * /proc/${pid}/smaps_rollup
|
25 | 25 | */
|
| 26 | +#undef _GNU_SOURCE |
| 27 | +#define _GNU_SOURCE |
| 28 | + |
26 | 29 | #undef NDEBUG
|
27 | 30 | #include <assert.h>
|
28 | 31 | #include <errno.h>
|
|
34 | 37 | #include <sys/mman.h>
|
35 | 38 | #include <sys/ptrace.h>
|
36 | 39 | #include <sys/resource.h>
|
| 40 | +#include <sys/syscall.h> |
37 | 41 | #include <sys/types.h>
|
38 | 42 | #include <sys/wait.h>
|
39 | 43 | #include <unistd.h>
|
|
42 | 46 | #define TEST_VSYSCALL
|
43 | 47 | #endif
|
44 | 48 |
|
| 49 | +#if defined __amd64__ |
| 50 | + #ifndef SYS_pkey_alloc |
| 51 | + #define SYS_pkey_alloc 330 |
| 52 | + #endif |
| 53 | + #ifndef SYS_pkey_free |
| 54 | + #define SYS_pkey_free 331 |
| 55 | + #endif |
| 56 | +#elif defined __i386__ |
| 57 | + #ifndef SYS_pkey_alloc |
| 58 | + #define SYS_pkey_alloc 381 |
| 59 | + #endif |
| 60 | + #ifndef SYS_pkey_free |
| 61 | + #define SYS_pkey_free 382 |
| 62 | + #endif |
| 63 | +#else |
| 64 | + #error "SYS_pkey_alloc" |
| 65 | +#endif |
| 66 | + |
| 67 | +static int g_protection_key_support; |
| 68 | + |
| 69 | +static int protection_key_support(void) |
| 70 | +{ |
| 71 | + long rv = syscall(SYS_pkey_alloc, 0, 0); |
| 72 | + if (rv > 0) { |
| 73 | + syscall(SYS_pkey_free, (int)rv); |
| 74 | + return 1; |
| 75 | + } else if (rv == -1 && errno == ENOSYS) { |
| 76 | + return 0; |
| 77 | + } else if (rv == -1 && errno == EINVAL) { |
| 78 | + // ospke=n |
| 79 | + return 0; |
| 80 | + } else { |
| 81 | + fprintf(stderr, "%s: error: rv %ld, errno %d\n", __func__, rv, errno); |
| 82 | + exit(EXIT_FAILURE); |
| 83 | + } |
| 84 | +} |
| 85 | + |
45 | 86 | /*
|
46 | 87 | * 0: vsyscall VMA doesn't exist vsyscall=none
|
47 | 88 | * 1: vsyscall VMA is --xp vsyscall=xonly
|
@@ -84,10 +125,6 @@ static const char proc_pid_smaps_vsyscall_1[] =
|
84 | 125 | "SwapPss: 0 kB\n"
|
85 | 126 | "Locked: 0 kB\n"
|
86 | 127 | "THPeligible: 0\n"
|
87 |
| -/* |
88 |
| - * "ProtectionKey:" field is conditional. It is possible to check it as well, |
89 |
| - * but I don't have such machine. |
90 |
| - */ |
91 | 128 | ;
|
92 | 129 |
|
93 | 130 | static const char proc_pid_smaps_vsyscall_2[] =
|
@@ -115,10 +152,6 @@ static const char proc_pid_smaps_vsyscall_2[] =
|
115 | 152 | "SwapPss: 0 kB\n"
|
116 | 153 | "Locked: 0 kB\n"
|
117 | 154 | "THPeligible: 0\n"
|
118 |
| -/* |
119 |
| - * "ProtectionKey:" field is conditional. It is possible to check it as well, |
120 |
| - * but I'm too tired. |
121 |
| - */ |
122 | 155 | ;
|
123 | 156 |
|
124 | 157 | static void sigaction_SIGSEGV(int _, siginfo_t *__, void *___)
|
@@ -240,19 +273,27 @@ static int test_proc_pid_smaps(pid_t pid)
|
240 | 273 | }
|
241 | 274 | perror("open /proc/${pid}/smaps");
|
242 | 275 | return EXIT_FAILURE;
|
| 276 | + } |
| 277 | + ssize_t rv = read(fd, buf, sizeof(buf)); |
| 278 | + close(fd); |
| 279 | + |
| 280 | + assert(0 <= rv); |
| 281 | + assert(rv <= sizeof(buf)); |
| 282 | + |
| 283 | + if (g_vsyscall == 0) { |
| 284 | + assert(rv == 0); |
243 | 285 | } else {
|
244 |
| - ssize_t rv = read(fd, buf, sizeof(buf)); |
245 |
| - close(fd); |
246 |
| - if (g_vsyscall == 0) { |
247 |
| - assert(rv == 0); |
248 |
| - } else { |
249 |
| - size_t len = strlen(g_proc_pid_smaps_vsyscall); |
250 |
| - /* TODO "ProtectionKey:" */ |
251 |
| - assert(rv > len); |
252 |
| - assert(memcmp(buf, g_proc_pid_smaps_vsyscall, len) == 0); |
| 286 | + size_t len = strlen(g_proc_pid_smaps_vsyscall); |
| 287 | + assert(rv > len); |
| 288 | + assert(memcmp(buf, g_proc_pid_smaps_vsyscall, len) == 0); |
| 289 | + |
| 290 | + if (g_protection_key_support) { |
| 291 | +#define PROTECTION_KEY "ProtectionKey: 0\n" |
| 292 | + assert(memmem(buf, rv, PROTECTION_KEY, strlen(PROTECTION_KEY))); |
253 | 293 | }
|
254 |
| - return EXIT_SUCCESS; |
255 | 294 | }
|
| 295 | + |
| 296 | + return EXIT_SUCCESS; |
256 | 297 | }
|
257 | 298 |
|
258 | 299 | static const char g_smaps_rollup[] =
|
@@ -419,6 +460,8 @@ int main(void)
|
419 | 460 | abort();
|
420 | 461 | }
|
421 | 462 |
|
| 463 | + g_protection_key_support = protection_key_support(); |
| 464 | + |
422 | 465 | pid_t pid = fork();
|
423 | 466 | if (pid == -1) {
|
424 | 467 | perror("fork");
|
|
0 commit comments