|
9 | 9 |
|
10 | 10 | // Dispatcher function |
11 | 11 | int pass_fptr_to_wt(uint64_t fn_ptr_uint, uint64_t cageid, uint64_t arg1, |
12 | | - uint64_t arg1cage, uint64_t arg2, uint64_t arg2cage, |
13 | | - uint64_t arg3, uint64_t arg3cage, uint64_t arg4, |
14 | | - uint64_t arg4cage, uint64_t arg5, uint64_t arg5cage, |
15 | | - uint64_t arg6, uint64_t arg6cage) { |
16 | | - if (fn_ptr_uint == 0) { |
17 | | - fprintf(stderr, "[Grate|interpose-register] Invalid function ptr=%llu\n", fn_ptr_uint); |
18 | | - assert(0); |
19 | | - } |
20 | | - |
21 | | - printf("[Grate|interpose-register] Handling function ptr: %llu from cage: %llu\n", |
22 | | - fn_ptr_uint, cageid); |
23 | | - |
24 | | - int (*fn)(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, |
25 | | - uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, |
26 | | - uint64_t, uint64_t, uint64_t) = |
27 | | - (int (*)(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, |
28 | | - uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, |
29 | | - uint64_t, uint64_t, uint64_t))(uintptr_t)fn_ptr_uint; |
30 | | - |
31 | | - |
32 | | - return fn(cageid, arg1, arg1cage, arg2, arg2cage, |
33 | | - arg3, arg3cage, arg4, arg4cage, |
34 | | - arg5, arg5cage, arg6, arg6cage); |
| 12 | + uint64_t arg1cage, uint64_t arg2, uint64_t arg2cage, |
| 13 | + uint64_t arg3, uint64_t arg3cage, uint64_t arg4, |
| 14 | + uint64_t arg4cage, uint64_t arg5, uint64_t arg5cage, |
| 15 | + uint64_t arg6, uint64_t arg6cage) { |
| 16 | + if (fn_ptr_uint == 0) { |
| 17 | + fprintf( |
| 18 | + stderr, |
| 19 | + "[Grate|interpose-register] Invalid function ptr=%llu\n", |
| 20 | + fn_ptr_uint); |
| 21 | + assert(0); |
| 22 | + } |
| 23 | + |
| 24 | + printf("[Grate|interpose-register] Handling function ptr: %llu from " |
| 25 | + "cage: %llu\n", |
| 26 | + fn_ptr_uint, cageid); |
| 27 | + |
| 28 | + int (*fn)(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, |
| 29 | + uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, |
| 30 | + uint64_t) = |
| 31 | + (int (*)(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, |
| 32 | + uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, |
| 33 | + uint64_t))(uintptr_t)fn_ptr_uint; |
| 34 | + |
| 35 | + return fn(cageid, arg1, arg1cage, arg2, arg2cage, arg3, arg3cage, arg4, |
| 36 | + arg4cage, arg5, arg5cage, arg6, arg6cage); |
35 | 37 | } |
36 | 38 |
|
37 | | -int geteuid_grate(uint64_t cageid, |
38 | | - uint64_t arg1, uint64_t arg1cage, |
39 | | - uint64_t arg2, uint64_t arg2cage, |
40 | | - uint64_t arg3, uint64_t arg3cage, |
41 | | - uint64_t arg4, uint64_t arg4cage, |
42 | | - uint64_t arg5, uint64_t arg5cage, |
43 | | - uint64_t arg6, uint64_t arg6cage) { |
44 | | - printf("[Grate|interpose-register] In register_grate %d handler for cage: %llu\n", |
45 | | - getpid(), cageid); |
46 | | - return 10; |
| 39 | +int geteuid_grate(uint64_t cageid, uint64_t arg1, uint64_t arg1cage, |
| 40 | + uint64_t arg2, uint64_t arg2cage, uint64_t arg3, |
| 41 | + uint64_t arg3cage, uint64_t arg4, uint64_t arg4cage, |
| 42 | + uint64_t arg5, uint64_t arg5cage, uint64_t arg6, |
| 43 | + uint64_t arg6cage) { |
| 44 | + printf("[Grate|interpose-register] In register_grate %d handler for " |
| 45 | + "cage: %llu\n", |
| 46 | + getpid(), cageid); |
| 47 | + return 10; |
47 | 48 | } |
48 | 49 |
|
49 | | -// We want to register a handler for geteuid (syscall num 107) in child cage, but also |
50 | | -// monitor the register_handler behaviors, and the blow handler function |
51 | | -// will redirect the register_handler call from cage to this grate, attach the function ptr |
52 | | -// as the arg and then this grate will call the register_handler syscall to register |
53 | | -// the handler in the target cage. |
54 | | -int register_grate(uint64_t cageid, |
55 | | - uint64_t arg1, uint64_t arg1cage, |
56 | | - uint64_t arg2, uint64_t arg2cage, |
57 | | - uint64_t arg3, uint64_t arg3cage, |
58 | | - uint64_t arg4, uint64_t arg4cage, |
59 | | - uint64_t arg5, uint64_t arg5cage, |
60 | | - uint64_t arg6, uint64_t arg6cage) { |
61 | | - printf("[Grate|interpose-register] In register_grate %d handler for cage: %llu\n", |
62 | | - getpid(), cageid); |
63 | | - int self_grate_id = getpid(); |
64 | | - uint64_t fn_ptr_addr = (uint64_t)(uintptr_t)&geteuid_grate; |
65 | | - printf("[Grate|geteuid] Registering geteuid handler for cage %llu in " |
66 | | - "grate %d with fn ptr addr: %llu\n", |
67 | | - cageid, self_grate_id, fn_ptr_addr); |
68 | | - int ret = make_threei_call( |
69 | | - 1001, // syscallnum for register_handler |
70 | | - 0, // callname is not used in the trampoline, set to 0 |
71 | | - self_grate_id, // self_grate_id is used in the 3i |
72 | | - arg1cage, // target_cageid is used in the 3i |
73 | | - arg1, arg1cage, |
74 | | - arg2, arg2cage, |
75 | | - fn_ptr_addr, arg3cage, |
76 | | - arg4, arg4cage, |
77 | | - arg5, arg5cage, |
78 | | - arg6, arg6cage, |
79 | | - 0 // we will handle the errno in this grate instead of translating it to -1 in the trampoline |
80 | | - ); |
81 | | - return ret; |
| 50 | +// We interpose on a child grate's register_handler syscall. |
| 51 | +// |
| 52 | +// This implementation overrides the (fn_ptr_addr, grate-2) with |
| 53 | +// (&geteuid_grate, grate-1) |
| 54 | +int register_grate(uint64_t cageid, uint64_t arg1, uint64_t arg1cage, |
| 55 | + uint64_t arg2, uint64_t arg2cage, uint64_t arg3, |
| 56 | + uint64_t arg3cage, uint64_t arg4, uint64_t arg4cage, |
| 57 | + uint64_t arg5, uint64_t arg5cage, uint64_t arg6, |
| 58 | + uint64_t arg6cage) { |
| 59 | + printf("[Grate|interpose-register] In register_grate %d handler for " |
| 60 | + "cage: %llu\n", |
| 61 | + getpid(), cageid); |
| 62 | + |
| 63 | + int self_grate_id = getpid(); |
| 64 | + int target_cage = arg1; |
| 65 | + int syscall_num = arg1cage; |
| 66 | + uint64_t fn_ptr_addr = (uint64_t)(uintptr_t)&geteuid_grate; |
| 67 | + |
| 68 | + printf("[Grate|geteuid] Registering geteuid handler for cage %llu in " |
| 69 | + "grate %d with fn ptr addr: %llu\n", |
| 70 | + cageid, self_grate_id, fn_ptr_addr); |
| 71 | + |
| 72 | + int ret = register_handler(target_cage, syscall_num, self_grate_id, |
| 73 | + fn_ptr_addr); |
| 74 | + |
| 75 | + return ret; |
82 | 76 | } |
83 | 77 |
|
84 | 78 | // Main function will always be same in all grates |
85 | 79 | int main(int argc, char *argv[]) { |
86 | | - // Should be at least two inputs (at least one grate file and one cage file) |
87 | | - if (argc < 2) { |
88 | | - fprintf(stderr, "Usage: %s <cage_file> <grate_file> <cage_file> [...]\n", |
89 | | - argv[0]); |
90 | | - assert(0); |
91 | | - } |
92 | | - |
93 | | - int grateid = getpid(); |
94 | | - |
95 | | - for (int i = 1; i < (argc < 3 ? argc : 3); i++) { |
96 | | - pid_t pid = fork(); |
97 | | - if (pid < 0) { |
98 | | - perror("fork failed"); |
99 | | - assert(0); |
100 | | - } else if (pid == 0) { |
101 | | - // Next one is cage, only set the register_handler when next one is cage |
102 | | - int cageid = getpid(); |
103 | | - // Set the register_handler (syscallnum=1001) of this cage to call this grate |
104 | | - // function register_grate |
105 | | - // Syntax of register_handler: |
106 | | - // <targetcage, targetcallnum, this_grate_id, fn_ptr_u64)> |
107 | | - uint64_t fn_ptr_addr = (uint64_t)(uintptr_t)®ister_grate; |
108 | | - printf("[Grate|interpose-register] Registering register_handler for cage %d in " |
109 | | - "grate %d with fn ptr addr: %llu\n", |
110 | | - cageid, grateid, fn_ptr_addr); |
111 | | - int ret = register_handler(cageid, 1001, grateid, fn_ptr_addr); |
112 | | - if (ret != 0) { |
113 | | - fprintf(stderr, "[Grate|interpose-register] Failed to register handler for cage %d in " |
114 | | - "grate %d with fn ptr addr: %llu, ret: %d\n", |
115 | | - cageid, grateid, fn_ptr_addr, ret); |
116 | | - assert(0); |
117 | | - } |
118 | | - |
119 | | - if (execv(argv[i], &argv[i]) == -1) { |
120 | | - perror("execv failed"); |
121 | | - assert(0); |
122 | | - } |
123 | | - } |
124 | | - } |
125 | | - |
126 | | - int status; |
127 | | - int failed = 0; |
128 | | - while (wait(&status) > 0) { |
129 | | - if (status != 0) { |
130 | | - fprintf(stderr, "[Grate|interpose-register] FAIL: child exited with status %d\n", status); |
131 | | - assert(0); |
132 | | - } |
133 | | - } |
134 | | - |
135 | | - printf("[Grate|interpose-register] PASS\n"); |
136 | | - return 0; |
| 80 | + // Should be at least two inputs (at least one grate file and one cage |
| 81 | + // file) |
| 82 | + if (argc < 2) { |
| 83 | + fprintf( |
| 84 | + stderr, |
| 85 | + "Usage: %s <cage_file> <grate_file> <cage_file> [...]\n", |
| 86 | + argv[0]); |
| 87 | + assert(0); |
| 88 | + } |
| 89 | + |
| 90 | + int grateid = getpid(); |
| 91 | + |
| 92 | + pid_t pid = fork(); |
| 93 | + if (pid < 0) { |
| 94 | + perror("fork failed"); |
| 95 | + assert(0); |
| 96 | + } else if (pid == 0) { |
| 97 | + int cageid = getpid(); |
| 98 | + // Set the register_handler (syscallnum=1001) of this cage to |
| 99 | + // call this grate function register_grate Syntax of |
| 100 | + // register_handler: <targetcage, targetcallnum, this_grate_id, |
| 101 | + // fn_ptr_u64)> |
| 102 | + uint64_t fn_ptr_addr = (uint64_t)(uintptr_t)®ister_grate; |
| 103 | + printf("[Grate|interpose-register] Registering " |
| 104 | + "register_handler for cage %d in " |
| 105 | + "grate %d with fn ptr addr: %llu\n", |
| 106 | + cageid, grateid, fn_ptr_addr); |
| 107 | + |
| 108 | + int ret = register_handler(cageid, 1001, grateid, fn_ptr_addr); |
| 109 | + if (ret != 0) { |
| 110 | + fprintf(stderr, |
| 111 | + "[Grate|interpose-register] Failed to register " |
| 112 | + "handler for cage %d in " |
| 113 | + "grate %d with fn ptr addr: %llu, ret: %d\n", |
| 114 | + cageid, grateid, fn_ptr_addr, ret); |
| 115 | + assert(0); |
| 116 | + } |
| 117 | + |
| 118 | + if (execv(argv[1], &argv[1]) == -1) { |
| 119 | + perror("execv failed"); |
| 120 | + assert(0); |
| 121 | + } |
| 122 | + } |
| 123 | + |
| 124 | + int status; |
| 125 | + int failed = 0; |
| 126 | + while (wait(&status) > 0) { |
| 127 | + if (status != 0) { |
| 128 | + fprintf(stderr, |
| 129 | + "[Grate|interpose-register] FAIL: child exited " |
| 130 | + "with status %d\n", |
| 131 | + status); |
| 132 | + assert(0); |
| 133 | + } |
| 134 | + } |
| 135 | + |
| 136 | + printf("[Grate|interpose-register] PASS\n"); |
| 137 | + return 0; |
137 | 138 | } |
0 commit comments