OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <fcntl.h> | 5 #include <fcntl.h> |
| 6 #include <stdlib.h> |
| 7 #include <sys/time.h> |
6 | 8 |
7 #include "library.h" | 9 #include "library.h" |
8 #include "sandbox.h" | 10 #include "sandbox.h" |
9 #include "test_runner.h" | 11 #include "test_runner.h" |
10 | 12 |
11 | 13 |
12 extern "C" int my_getpid(void); | 14 extern "C" int my_getpid(void); |
13 extern char my_getpid_end[]; | 15 extern char my_getpid_end[]; |
14 | 16 |
15 void patch_range(char *start, char *end) { | 17 void patch_range(char *start, char *end) { |
(...skipping 26 matching lines...) Expand all Loading... |
42 CHECK(func[0] == '\x68'); // 68 XX XX XX XX push $X | 44 CHECK(func[0] == '\x68'); // 68 XX XX XX XX push $X |
43 CHECK(func[5] == '\xc3'); // c3 ret | 45 CHECK(func[5] == '\xc3'); // c3 ret |
44 CHECK(func[6] == '\x90'); // 90 nop | 46 CHECK(func[6] == '\x90'); // 90 nop |
45 CHECK(func[7] == '\xc3'); // c3 ret (unmodified) | 47 CHECK(func[7] == '\xc3'); // c3 ret (unmodified) |
46 #else | 48 #else |
47 # error Unsupported target platform | 49 # error Unsupported target platform |
48 #endif | 50 #endif |
49 StartSeccompSandbox(); | 51 StartSeccompSandbox(); |
50 CHECK(my_getpid() == pid); | 52 CHECK(my_getpid() == pid); |
51 } | 53 } |
| 54 |
| 55 #if defined(__x86_64__) |
| 56 |
| 57 // These test cases test patching calls to the vsyscall page, which is |
| 58 // present on x86-64 only. |
| 59 |
| 60 // The timer tests below could fail on a heavily loaded machine, but |
| 61 // we make a generous allowance for this. They could also fail if the |
| 62 // clock is changed while the test is running. |
| 63 const int kMaxTime = 30; // Time in seconds |
| 64 |
| 65 extern "C" int my_vgettimeofday(struct timeval *tv, struct timezone *tz); |
| 66 extern char my_vgettimeofday_end[]; |
| 67 |
| 68 extern "C" int my_vtime(time_t *time); |
| 69 extern char my_vtime_end[]; |
| 70 |
| 71 extern "C" int my_vgetcpu(unsigned *cpu, unsigned *node, void *tcache); |
| 72 extern char my_vgetcpu_end[]; |
| 73 |
| 74 void check_patching_vsyscall(char *func, char *func_end) { |
| 75 patch_range(func, func_end); |
| 76 CHECK(func[0] == '\x48'); // 48 83 ec 08 sub $8, %rsp (unmodified) |
| 77 CHECK(func[1] == '\x83'); |
| 78 CHECK(func[2] == '\xec'); |
| 79 CHECK(func[3] == '\x08'); |
| 80 CHECK(func[4] == '\xe9'); // e9 XX XX XX XX jmp X |
| 81 CHECK(func[9] == '\x90'); // 90 nop |
| 82 CHECK(func[10] == '\x90'); // 90 nop |
| 83 CHECK(func[11] == '\x90'); // 90 nop |
| 84 CHECK(func[12] == '\x90'); // 90 nop |
| 85 CHECK(func[13] == '\x48'); // 48 83 c4 08 add $8, %rsp (unmodified) |
| 86 CHECK(func[14] == '\x83'); |
| 87 CHECK(func[15] == '\xc4'); |
| 88 CHECK(func[16] == '\x08'); |
| 89 CHECK(func[17] == '\xc3'); // c3 ret (unmodified) |
| 90 } |
| 91 |
| 92 TEST(test_patching_vsyscall_gettimeofday) { |
| 93 struct timeval time1; |
| 94 struct timeval time2; |
| 95 CHECK_SUCCEEDS(gettimeofday(&time1, NULL) == 0); |
| 96 CHECK(my_vgettimeofday(&time2, NULL) == 0); |
| 97 CHECK(time1.tv_sec <= time2.tv_sec && time2.tv_sec < time1.tv_sec + kMaxTime); |
| 98 |
| 99 check_patching_vsyscall((char *) my_vgettimeofday, my_vgettimeofday_end); |
| 100 |
| 101 StartSeccompSandbox(); |
| 102 CHECK(my_vgettimeofday(&time2, NULL) == 0); |
| 103 CHECK(time1.tv_sec <= time2.tv_sec && time2.tv_sec < time1.tv_sec + kMaxTime); |
| 104 } |
| 105 |
| 106 TEST(test_patching_vsyscall_time) { |
| 107 time_t time1; |
| 108 time_t time2; |
| 109 CHECK_SUCCEEDS((time1 = time(NULL)) != -1); |
| 110 time2 = time(NULL); |
| 111 CHECK(time1 <= time2 && time2 < time1 + kMaxTime); |
| 112 |
| 113 check_patching_vsyscall((char *) my_vtime, my_vtime_end); |
| 114 |
| 115 StartSeccompSandbox(); |
| 116 time2 = time(NULL); |
| 117 CHECK(time1 <= time2 && time2 < time1 + kMaxTime); |
| 118 } |
| 119 |
| 120 TEST(test_patching_vsyscall_getcpu) { |
| 121 CHECK(my_vgetcpu(NULL, NULL, NULL) == 0); |
| 122 |
| 123 check_patching_vsyscall((char *) my_vgetcpu, my_vgetcpu_end); |
| 124 |
| 125 StartSeccompSandbox(); |
| 126 // glibc's sched_getcpu() could still succeed if it goes via the |
| 127 // vdso and just reads memory, but my_vgetcpu() is always redirected |
| 128 // through the sandbox's handler and is rejected. |
| 129 CHECK(my_vgetcpu(NULL, NULL, NULL) == -ENOSYS); |
| 130 } |
| 131 |
| 132 #endif |
OLD | NEW |