|
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