| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 1 #include "sandbox_impl.h" | 5 #include "sandbox_impl.h" |
| 2 #include "syscall_table.h" | 6 #include "syscall_table.h" |
| 3 | 7 |
| 4 namespace playground { | 8 namespace playground { |
| 5 | 9 |
| 6 void Sandbox::createTrustedThread(int processFdPub, int cloneFdPub, | 10 void Sandbox::createTrustedThread(int processFdPub, int cloneFdPub, |
| 7 SecureMem::Args* secureMem) { | 11 SecureMem::Args* secureMem) { |
| 8 SecureMem::Args args = { { { { { 0 } } } } }; | 12 SecureMem::Args args = { { { { { 0 } } } } }; |
| 9 args.self = &args; | 13 args.self = &args; |
| 10 args.newSecureMem = secureMem; | 14 args.newSecureMem = secureMem; |
| 11 args.processFdPub = processFdPub; | 15 args.processFdPub = processFdPub; |
| 12 args.cloneFdPub = cloneFdPub; | 16 args.cloneFdPub = cloneFdPub; |
| 13 #if defined(__x86_64__) | 17 #if defined(__x86_64__) |
| 14 asm volatile( | 18 asm volatile( |
| 15 "push %%rbx\n" | 19 "push %%rbx\n" |
| 16 "push %%rbp\n" | 20 "push %%rbp\n" |
| 17 "mov %0, %%rbp\n" // %rbp = args | 21 "mov %0, %%rbp\n" // %rbp = args |
| 18 "xor %%rbx, %%rbx\n" // initial sequence number | 22 "xor %%rbx, %%rbx\n" // initial sequence number |
| 19 "lea 999f(%%rip), %%r15\n" // continue in same thread | 23 "lea 999f(%%rip), %%r15\n" // continue in same thread |
| 20 "jmp 19f\n" // create trusted thread | 24 "jmp 20f\n" // create trusted thread |
| 21 | 25 |
| 22 // TODO(markus): Coalesce the read() operations by reading into a bigger | 26 // TODO(markus): Coalesce the read() operations by reading into a bigger |
| 23 // buffer. | 27 // buffer. |
| 24 | 28 |
| 25 // Parameters: | 29 // Parameters: |
| 26 // *%fs: secure memory region | 30 // *%fs: secure memory region |
| 27 // the page following this one contains the scratch space | 31 // the page following this one contains the scratch space |
| 28 // %r13: thread's side of threadFd | 32 // %r13: thread's side of threadFd |
| 29 // %r15: processFdPub | 33 // %r15: processFdPub |
| 30 | 34 |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 133 "jnz 4f\n" | 137 "jnz 4f\n" |
| 134 "syscall\n" | 138 "syscall\n" |
| 135 "mov %%rax, %%r8\n" | 139 "mov %%rax, %%r8\n" |
| 136 "mov $56, %%eax\n" // NR_clone | 140 "mov $56, %%eax\n" // NR_clone |
| 137 "mov $17, %%edi\n" // flags = SIGCHLD | 141 "mov $17, %%edi\n" // flags = SIGCHLD |
| 138 "mov $1, %%esi\n" // stack = 1 | 142 "mov $1, %%esi\n" // stack = 1 |
| 139 "syscall\n" | 143 "syscall\n" |
| 140 "test %%rax, %%rax\n" | 144 "test %%rax, %%rax\n" |
| 141 "js 25f\n" // exit process | 145 "js 25f\n" // exit process |
| 142 "mov %%rax, %%rdi\n" | 146 "mov %%rax, %%rdi\n" |
| 143 "jnz 7f\n" // wait for child, then return result | 147 "jnz 8f\n" // wait for child, then return result |
| 144 "mov %%fs:0x0, %%rdi\n" // start = secure_mem | 148 "mov %%fs:0x0, %%rdi\n" // start = secure_mem |
| 145 "mov $4096, %%esi\n" // len = 4096 | 149 "mov $4096, %%esi\n" // len = 4096 |
| 146 "mov $3, %%edx\n" // prot = PROT_READ | PROT_WRITE | 150 "mov $3, %%edx\n" // prot = PROT_READ | PROT_WRITE |
| 147 "mov $10, %%eax\n" // NR_mprotect | 151 "mov $10, %%eax\n" // NR_mprotect |
| 148 "syscall\n" | 152 "syscall\n" |
| 149 "mov %%r8d, 0xD4(%%rdi)\n" // set most recently returned SysV shm id | 153 "mov %%r8d, 0xD4(%%rdi)\n" // set most recently returned SysV shm id |
| 150 "xor %%rdi, %%rdi\n" | 154 "xor %%rdi, %%rdi\n" |
| 155 |
| 156 // When debugging messages are enabled, warn about expensive system calls |
| 157 #ifndef NDEBUG |
| 158 "cmpw $0, %%fs:0xD0\n" // debug mode |
| 159 "jz 26f\n" |
| 160 "mov $1, %%eax\n" // NR_write |
| 161 "mov $2, %%edi\n" // fd = stderr |
| 162 "lea 101f(%%rip), %%rsi\n" // "This is an expensive system call" |
| 163 "mov $102f-101f, %%edx\n" // len = strlen(msg) |
| 164 "syscall\n" |
| 165 "xor %%rdi, %%rdi\n" |
| 166 #endif |
| 167 |
| 151 "jmp 26f\n" // exit program, no message | 168 "jmp 26f\n" // exit program, no message |
| 152 "4:syscall\n" | 169 "4:syscall\n" |
| 153 "jmp 14f\n" // return result | 170 "jmp 15f\n" // return result |
| 154 | 171 |
| 155 // If syscall number is -2, execute locked system call from the | 172 // If syscall number is -2, execute locked system call from the |
| 156 // secure memory area | 173 // secure memory area |
| 157 "5:jg 11f\n" | 174 "5:jg 12f\n" |
| 158 "cmp $-2, %%eax\n" | 175 "cmp $-2, %%eax\n" |
| 159 "jnz 8f\n" | 176 "jnz 9f\n" |
| 160 "cmp %%rbx, %%fs:0x8\n" | 177 "cmp %%rbx, %%fs:0x8\n" |
| 161 "jne 25f\n" // exit process | 178 "jne 25f\n" // exit process |
| 179 |
| 180 // When debugging messages are enabled, warn about expensive system calls |
| 181 #ifndef NDEBUG |
| 182 "cmpw $0, %%fs:0xD0\n" // debug mode |
| 183 "jz 6f\n" |
| 184 "mov $1, %%eax\n" // NR_write |
| 185 "mov $2, %%edi\n" // fd = stderr |
| 186 "lea 101f(%%rip), %%rsi\n" // "This is an expensive system call" |
| 187 "mov $102f-101f, %%edx\n" // len = strlen(msg) |
| 188 "syscall\n" |
| 189 "6:" |
| 190 #endif |
| 191 |
| 162 "mov %%fs:0x10, %%rax\n" | 192 "mov %%fs:0x10, %%rax\n" |
| 163 "mov %%fs:0x18, %%rdi\n" | 193 "mov %%fs:0x18, %%rdi\n" |
| 164 "mov %%fs:0x20, %%rsi\n" | 194 "mov %%fs:0x20, %%rsi\n" |
| 165 "mov %%fs:0x28, %%rdx\n" | 195 "mov %%fs:0x28, %%rdx\n" |
| 166 "mov %%fs:0x30, %%r10\n" | 196 "mov %%fs:0x30, %%r10\n" |
| 167 "mov %%fs:0x38, %%r8\n" | 197 "mov %%fs:0x38, %%r8\n" |
| 168 "mov %%fs:0x40, %%r9\n" | 198 "mov %%fs:0x40, %%r9\n" |
| 169 "cmp %%rbx, %%fs:0x8\n" | 199 "cmp %%rbx, %%fs:0x8\n" |
| 170 "jne 25f\n" // exit process | 200 "jne 25f\n" // exit process |
| 171 | 201 |
| 172 // clone() has unusual calling conventions and must be handled specially | 202 // clone() has unusual calling conventions and must be handled specially |
| 173 "cmp $56, %%rax\n" // NR_clone | 203 "cmp $56, %%rax\n" // NR_clone |
| 174 "jz 18f\n" | 204 "jz 19f\n" |
| 175 | 205 |
| 176 // exit() terminates trusted thread | 206 // exit() terminates trusted thread |
| 177 "cmp $60, %%eax\n" // NR_exit | 207 "cmp $60, %%eax\n" // NR_exit |
| 178 "jz 17f\n" | 208 "jz 18f\n" |
| 179 | 209 |
| 180 // Perform requested system call | 210 // Perform requested system call |
| 181 "syscall\n" | 211 "syscall\n" |
| 182 | 212 |
| 183 // Unlock mutex | 213 // Unlock mutex |
| 184 "6:cmp %%rbx, %%fs:0x8\n" | 214 "7:cmp %%rbx, %%fs:0x8\n" |
| 185 "jne 25f\n" // exit process | 215 "jne 25f\n" // exit process |
| 186 "add $2, %%rbx\n" | 216 "add $2, %%rbx\n" |
| 187 "mov %%rax, %%r8\n" | 217 "mov %%rax, %%r8\n" |
| 188 "mov $56, %%eax\n" // NR_clone | 218 "mov $56, %%eax\n" // NR_clone |
| 189 "mov $17, %%rdi\n" // flags = SIGCHLD | 219 "mov $17, %%rdi\n" // flags = SIGCHLD |
| 190 "mov $1, %%rsi\n" // stack = 1 | 220 "mov $1, %%rsi\n" // stack = 1 |
| 191 "syscall\n" | 221 "syscall\n" |
| 192 "test %%rax, %%rax\n" | 222 "test %%rax, %%rax\n" |
| 193 "js 25f\n" // exit process | 223 "js 25f\n" // exit process |
| 194 "jz 22f\n" // unlock and exit | 224 "jz 22f\n" // unlock and exit |
| 195 "mov %%rax, %%rdi\n" | 225 "mov %%rax, %%rdi\n" |
| 196 "7:xor %%rsi, %%rsi\n" | 226 "8:xor %%rsi, %%rsi\n" |
| 197 "xor %%rdx, %%rdx\n" | 227 "xor %%rdx, %%rdx\n" |
| 198 "xor %%r10, %%r10\n" | 228 "xor %%r10, %%r10\n" |
| 199 "mov $61, %%eax\n" // NR_wait4 | 229 "mov $61, %%eax\n" // NR_wait4 |
| 200 "syscall\n" | 230 "syscall\n" |
| 201 "cmp $-4, %%eax\n" // EINTR | 231 "cmp $-4, %%eax\n" // EINTR |
| 202 "jz 7b\n" | 232 "jz 8b\n" |
| 203 "mov %%r8, %%rax\n" | 233 "mov %%r8, %%rax\n" |
| 204 "jmp 14f\n" // return result | 234 "jmp 15f\n" // return result |
| 205 | 235 |
| 206 // If syscall number is -3, read the time stamp counter | 236 // If syscall number is -3, read the time stamp counter |
| 207 "8:cmp $-3, %%eax\n" | 237 "9:cmp $-3, %%eax\n" |
| 208 "jnz 9f\n" | 238 "jnz 10f\n" |
| 209 "rdtsc\n" // sets %edx:%eax | 239 "rdtsc\n" // sets %edx:%eax |
| 210 "xor %%rcx, %%rcx\n" | 240 "xor %%rcx, %%rcx\n" |
| 211 "jmp 10f\n" | 241 "jmp 11f\n" |
| 212 "9:cmp $-4, %%eax\n" | 242 "10:cmp $-4, %%eax\n" |
| 213 "jnz 11f\n" | 243 "jnz 12f\n" |
| 214 "rdtscp\n" // sets %edx:%eax and %ecx | 244 "rdtscp\n" // sets %edx:%eax and %ecx |
| 215 "10:add $0x3C, %%rsi\n" | 245 "11:add $0x3C, %%rsi\n" |
| 216 "mov %%eax, 0(%%rsi)\n" | 246 "mov %%eax, 0(%%rsi)\n" |
| 217 "mov %%edx, 4(%%rsi)\n" | 247 "mov %%edx, 4(%%rsi)\n" |
| 218 "mov %%ecx, 8(%%rsi)\n" | 248 "mov %%ecx, 8(%%rsi)\n" |
| 219 "mov $12, %%edx\n" | 249 "mov $12, %%edx\n" |
| 220 "jmp 15f\n" // return result | 250 "jmp 16f\n" // return result |
| 221 | 251 |
| 222 // Check in syscallTable whether this system call is unrestricted | 252 // Check in syscallTable whether this system call is unrestricted |
| 223 "11:mov %%rax, %%r9\n" | 253 "12:mov %%rax, %%r9\n" |
| 224 #ifndef NDEBUG | 254 #ifndef NDEBUG |
| 225 "cmpw $0, %%fs:0xD0\n" // debug mode | 255 "cmpw $0, %%fs:0xD0\n" // debug mode |
| 226 "jnz 12f\n" | 256 "jnz 13f\n" |
| 227 #endif | 257 #endif |
| 228 "cmp playground$maxSyscall(%%rip), %%eax\n" | 258 "cmp playground$maxSyscall(%%rip), %%eax\n" |
| 229 "ja 25f\n" // exit process | 259 "ja 25f\n" // exit process |
| 230 "shl $4, %%rax\n" | 260 "shl $4, %%rax\n" |
| 231 "lea playground$syscallTable(%%rip), %%rdi\n" | 261 "lea playground$syscallTable(%%rip), %%rdi\n" |
| 232 "add %%rdi, %%rax\n" | 262 "add %%rdi, %%rax\n" |
| 233 "mov 0(%%rax), %%rax\n" | 263 "mov 0(%%rax), %%rax\n" |
| 234 "cmp $1, %%rax\n" | 264 "cmp $1, %%rax\n" |
| 235 "jne 25f\n" // exit process | 265 "jne 25f\n" // exit process |
| 236 | 266 |
| 237 // Default behavior for unrestricted system calls is to just execute | 267 // Default behavior for unrestricted system calls is to just execute |
| 238 // them. Read the remaining arguments first. | 268 // them. Read the remaining arguments first. |
| 239 "12:mov %%rsi, %%r8\n" | 269 "13:mov %%rsi, %%r8\n" |
| 240 "xor %%rax, %%rax\n" // NR_read | 270 "xor %%rax, %%rax\n" // NR_read |
| 241 "mov %%r13, %%rdi\n" // fd = threadFd | 271 "mov %%r13, %%rdi\n" // fd = threadFd |
| 242 "add $4, %%rsi\n" // buf = &scratch + 4 | 272 "add $4, %%rsi\n" // buf = &scratch + 4 |
| 243 "mov $48, %%edx\n" // len = 6*sizeof(void *) | 273 "mov $48, %%edx\n" // len = 6*sizeof(void *) |
| 244 "13:syscall\n" | 274 "14:syscall\n" |
| 245 "cmp $-4, %%rax\n" // EINTR | 275 "cmp $-4, %%rax\n" // EINTR |
| 246 "jz 13b\n" | 276 "jz 14b\n" |
| 247 "cmp %%rdx, %%rax\n" | 277 "cmp %%rdx, %%rax\n" |
| 248 "jnz 25f\n" // exit process | 278 "jnz 25f\n" // exit process |
| 249 "mov %%r9, %%rax\n" | 279 "mov %%r9, %%rax\n" |
| 250 "mov 0x04(%%r8), %%rdi\n" | 280 "mov 0x04(%%r8), %%rdi\n" |
| 251 "mov 0x0C(%%r8), %%rsi\n" | 281 "mov 0x0C(%%r8), %%rsi\n" |
| 252 "mov 0x14(%%r8), %%rdx\n" | 282 "mov 0x14(%%r8), %%rdx\n" |
| 253 "mov 0x1C(%%r8), %%r10\n" | 283 "mov 0x1C(%%r8), %%r10\n" |
| 254 "mov 0x2C(%%r8), %%r9\n" | 284 "mov 0x2C(%%r8), %%r9\n" |
| 255 "mov 0x24(%%r8), %%r8\n" | 285 "mov 0x24(%%r8), %%r8\n" |
| 256 "cmp $231, %%rax\n" // NR_exit_group | 286 "cmp $231, %%rax\n" // NR_exit_group |
| 257 "jz 26f\n" // exit program, no message | 287 "jz 26f\n" // exit program, no message |
| 258 "syscall\n" | 288 "syscall\n" |
| 259 | 289 |
| 260 // Return result of system call to sandboxed thread | 290 // Return result of system call to sandboxed thread |
| 261 "14:mov %%fs:0x0, %%rsi\n" | 291 "15:mov %%fs:0x0, %%rsi\n" |
| 262 "add $0x1034, %%rsi\n" // buf = &scratch + 52 | 292 "add $0x1034, %%rsi\n" // buf = &scratch + 52 |
| 263 "mov %%rax, (%%rsi)\n" | 293 "mov %%rax, (%%rsi)\n" |
| 264 "mov $8, %%edx\n" // len = 8 | 294 "mov $8, %%edx\n" // len = 8 |
| 265 "15:mov %%r13, %%rdi\n" // fd = threadFd | 295 "16:mov %%r13, %%rdi\n" // fd = threadFd |
| 266 "mov $1, %%eax\n" // NR_write | 296 "mov $1, %%eax\n" // NR_write |
| 267 "16:syscall\n" | 297 "17:syscall\n" |
| 268 "cmp %%rdx, %%rax\n" | 298 "cmp %%rdx, %%rax\n" |
| 269 "jz 1b\n" | 299 "jz 1b\n" |
| 270 "cmp $-4, %%rax\n" // EINTR | 300 "cmp $-4, %%rax\n" // EINTR |
| 271 "jz 16b\n" | 301 "jz 17b\n" |
| 272 "jmp 25f\n" // exit process | 302 "jmp 25f\n" // exit process |
| 273 | 303 |
| 274 // NR_exit: | 304 // NR_exit: |
| 275 // Exit trusted thread after cleaning up resources | 305 // Exit trusted thread after cleaning up resources |
| 276 "17:mov %%fs:0x0, %%rsi\n" | 306 "18:mov %%fs:0x0, %%rsi\n" |
| 277 "mov 0xE8(%%rsi), %%rdi\n" // fd = threadFdPub | 307 "mov 0xE8(%%rsi), %%rdi\n" // fd = threadFdPub |
| 278 "mov $3, %%eax\n" // NR_close | 308 "mov $3, %%eax\n" // NR_close |
| 279 "syscall\n" | 309 "syscall\n" |
| 280 "mov %%rsi, %%rdi\n" // start = secure_mem | 310 "mov %%rsi, %%rdi\n" // start = secure_mem |
| 281 "mov $8192, %%esi\n" // length = 4096 | 311 "mov $8192, %%esi\n" // length = 8192 |
| 282 "xor %%rdx, %%rdx\n" // prot = PROT_NONE | 312 "xor %%rdx, %%rdx\n" // prot = PROT_NONE |
| 283 "mov $10, %%eax\n" // NR_mprotect | 313 "mov $10, %%eax\n" // NR_mprotect |
| 284 "syscall\n" | 314 "syscall\n" |
| 285 "mov %%r13, %%rdi\n" // fd = threadFd | 315 "mov %%r13, %%rdi\n" // fd = threadFd |
| 286 "mov $3, %%eax\n" // NR_close | 316 "mov $3, %%eax\n" // NR_close |
| 287 "syscall\n" | 317 "syscall\n" |
| 288 "mov $56, %%eax\n" // NR_clone | 318 "mov $56, %%eax\n" // NR_clone |
| 289 "mov $17, %%rdi\n" // flags = SIGCHLD | 319 "mov $17, %%rdi\n" // flags = SIGCHLD |
| 290 "mov $1, %%rsi\n" // stack = 1 | 320 "mov $1, %%rsi\n" // stack = 1 |
| 291 "syscall\n" | 321 "syscall\n" |
| 292 "mov %%rax, %%rdi\n" | 322 "mov %%rax, %%rdi\n" |
| 293 "test %%rax, %%rax\n" | 323 "test %%rax, %%rax\n" |
| 324 "js 26f\n" // exit process |
| 294 "jne 21f\n" // reap helper, exit thread | 325 "jne 21f\n" // reap helper, exit thread |
| 295 "jmp 22f\n" // unlock mutex | 326 "jmp 22f\n" // unlock mutex |
| 296 | 327 |
| 297 // NR_clone: | 328 // NR_clone: |
| 298 // Original trusted thread calls clone() to create new nascent | 329 // Original trusted thread calls clone() to create new nascent |
| 299 // thread. This thread is (typically) fully privileged and shares all | 330 // thread. This thread is (typically) fully privileged and shares all |
| 300 // resources with the caller (i.e. the previous trusted thread), | 331 // resources with the caller (i.e. the previous trusted thread), |
| 301 // and by extension it shares all resources with the sandbox'd | 332 // and by extension it shares all resources with the sandbox'd |
| 302 // threads. | 333 // threads. |
| 303 // N.B. It is possible to make the thread creation code crash before | 334 // N.B. It is possible to make the thread creation code crash before |
| 304 // it releases seccomp privileges. This is generally OK, as it just | 335 // it releases seccomp privileges. This is generally OK, as it just |
| 305 // terminates the program. But if we ever support signal handling, | 336 // terminates the program. But if we ever support signal handling, |
| 306 // we have to be careful that the user cannot install a SIGSEGV | 337 // we have to be careful that the user cannot install a SIGSEGV |
| 307 // handler that gets executed with elevated privileges. | 338 // handler that gets executed with elevated privileges. |
| 308 "18:mov %%fs:0x0, %%rbp\n" // %rbp = old_shared_mem | 339 "19:mov %%fs:0x0, %%rbp\n" // %rbp = old_shared_mem |
| 309 "syscall\n" // calls NR_clone | 340 "syscall\n" // calls NR_clone |
| 310 "cmp $-4095, %%rax\n" // return codes -1..-4095 are errno values | 341 "cmp $-4095, %%rax\n" // return codes -1..-4095 are errno values |
| 311 "jae 6b\n" | 342 "jae 7b\n" // unlock mutex, return result |
| 312 "add $2, %%rbx\n" | 343 "add $2, %%rbx\n" |
| 313 "test %%rax, %%rax\n" | 344 "test %%rax, %%rax\n" |
| 314 "jne 14b\n" // return result | 345 "jne 15b\n" // return result |
| 315 | 346 |
| 316 // In nascent thread, now. | 347 // In nascent thread, now. |
| 317 "sub $2, %%rbx\n" | 348 "sub $2, %%rbx\n" |
| 318 "xor %%r15, %%r15\n" // Request to return from clone() when done | 349 "xor %%r15, %%r15\n" // Request to return from clone() when done |
| 319 | 350 |
| 320 // Get thread id of nascent thread | 351 // Get thread id of nascent thread |
| 321 "19:mov $186, %%eax\n" // NR_gettid | 352 "20:mov $186, %%eax\n" // NR_gettid |
| 322 "syscall\n" | 353 "syscall\n" |
| 323 "mov %%rax, %%r14\n" | 354 "mov %%rax, %%r14\n" |
| 324 | 355 |
| 325 // Nascent thread creates socketpair() for sending requests to | 356 // Nascent thread creates socketpair() for sending requests to |
| 326 // trusted thread. | 357 // trusted thread. |
| 327 // We can create the filehandles on the stack. Filehandles are | 358 // We can create the filehandles on the stack. Filehandles are |
| 328 // always treated as untrusted. | 359 // always treated as untrusted. |
| 329 // socketpair(AF_UNIX, SOCK_STREAM, 0, fds) | 360 // socketpair(AF_UNIX, SOCK_STREAM, 0, fds) |
| 330 "push %%r15\n" | 361 "push %%r15\n" |
| 331 "mov $53, %%eax\n" // NR_socketpair | 362 "mov $53, %%eax\n" // NR_socketpair |
| 332 "mov $1, %%edi\n" // domain = AF_UNIX | 363 "mov $1, %%edi\n" // domain = AF_UNIX |
| 333 "mov $1, %%esi\n" // type = SOCK_STREAM | 364 "mov $1, %%esi\n" // type = SOCK_STREAM |
| 334 "xor %%rdx, %%rdx\n" // protocol = 0 | 365 "xor %%rdx, %%rdx\n" // protocol = 0 |
| 335 "sub $8, %%rsp\n" // sv = %rsp | 366 "sub $8, %%rsp\n" // sv = %rsp |
| 336 "mov %%rsp, %%r10\n" | 367 "mov %%rsp, %%r10\n" |
| 337 "syscall\n" | 368 "syscall\n" |
| 338 "test %%rax, %%rax\n" | 369 "test %%rax, %%rax\n" |
| 339 "jz 27f\n" | 370 "jz 27f\n" |
| 340 | 371 |
| 341 // If things went wrong, we don't have an (easy) way of signaling | 372 // If things went wrong, we don't have an (easy) way of signaling |
| 342 // the parent. For our purposes, it is sufficient to fail with a | 373 // the parent. For our purposes, it is sufficient to fail with a |
| 343 // fatal error. | 374 // fatal error. |
| 344 "jmp 25f\n" // exit process | 375 "jmp 25f\n" // exit process |
| 345 "20:mov $56, %%eax\n" // NR_clone | |
| 346 "mov $17, %%rdi\n" // flags = SIGCHLD | |
| 347 "mov $1, %%rsi\n" // stack = 1 | |
| 348 "syscall\n" | |
| 349 "test %%rax, %%rax\n" | |
| 350 "js 25f\n" // exit process | |
| 351 "jz 22f\n" // unlock and exit | |
| 352 "mov %%rax, %%rdi\n" | |
| 353 "21:xor %%rsi, %%rsi\n" | 376 "21:xor %%rsi, %%rsi\n" |
| 354 "xor %%rdx, %%rdx\n" | 377 "xor %%rdx, %%rdx\n" |
| 355 "xor %%r10, %%r10\n" | 378 "xor %%r10, %%r10\n" |
| 356 "mov $61, %%eax\n" // NR_wait4 | 379 "mov $61, %%eax\n" // NR_wait4 |
| 357 "syscall\n" | 380 "syscall\n" |
| 358 "cmp $-4, %%eax\n" // EINTR | 381 "cmp $-4, %%eax\n" // EINTR |
| 359 "jz 21b\n" | 382 "jz 21b\n" |
| 360 "jmp 23f\n" // exit thread (no message) | 383 "jmp 23f\n" // exit thread (no message) |
| 361 "22:lea playground$syscall_mutex(%%rip), %%rdi\n" | 384 "22:lea playground$syscall_mutex(%%rip), %%rdi\n" |
| 362 "mov $4096, %%esi\n" | 385 "mov $4096, %%esi\n" |
| 363 "mov $3, %%edx\n" // prot = PROT_READ | PROT_WRITE | 386 "mov $3, %%edx\n" // prot = PROT_READ | PROT_WRITE |
| 364 "mov $10, %%eax\n" // NR_mprotect | 387 "mov $10, %%eax\n" // NR_mprotect |
| 365 "syscall\n" | 388 "syscall\n" |
| 366 "lock; addl $0x80000000, (%%rdi)\n" | 389 "lock; addl $0x80000000, (%%rdi)\n" |
| 367 "jz 23f\n" // exit thread | 390 "jz 23f\n" // exit thread |
| 368 "mov $1, %%edx\n" | 391 "mov $1, %%edx\n" |
| 369 "mov %%rdx, %%rsi\n" // FUTEX_WAKE | 392 "mov %%rdx, %%rsi\n" // FUTEX_WAKE |
| 370 "mov $202, %%eax\n" // NR_futex | 393 "mov $202, %%eax\n" // NR_futex |
| 371 "syscall\n" | 394 "syscall\n" |
| 372 "23:mov $60, %%eax\n" // NR_exit | 395 "23:mov $60, %%eax\n" // NR_exit |
| 373 "mov $1, %%edi\n" // status = 1 | 396 "mov $1, %%edi\n" // status = 1 |
| 374 "24:syscall\n" | 397 "24:syscall\n" |
| 375 "25:mov $1, %%eax\n" // NR_write | 398 "25:mov $1, %%eax\n" // NR_write |
| 376 "mov $2, %%edi\n" // fd = stderr | 399 "mov $2, %%edi\n" // fd = stderr |
| 377 "lea 100f(%%rip), %%rsi\n" | 400 "lea 100f(%%rip), %%rsi\n" // "Sandbox violation detected" |
| 378 "mov $101f-100f, %%edx\n" // len = strlen(msg) | 401 "mov $101f-100f, %%edx\n" // len = strlen(msg) |
| 379 "syscall\n" | 402 "syscall\n" |
| 380 "mov $1, %%edi\n" | 403 "mov $1, %%edi\n" |
| 381 "26:mov $231, %%eax\n" // NR_exit_group | 404 "26:mov $231, %%eax\n" // NR_exit_group |
| 382 "jmp 24b\n" | 405 "jmp 24b\n" |
| 383 | 406 |
| 384 // The first page is mapped read-only for use as securely shared memory | 407 // The first page is mapped read-only for use as securely shared memory |
| 385 "27:mov 0xC0(%%rbp), %%r12\n" // %r12 = secure shared memory | 408 "27:mov 0xC0(%%rbp), %%r12\n" // %r12 = secure shared memory |
| 386 "cmp %%rbx, 8(%%rbp)\n" | 409 "cmp %%rbx, 8(%%rbp)\n" |
| 387 "jne 25b\n" // exit process | 410 "jne 25b\n" // exit process |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 419 "mov 0(%%rsp), %%r9d\n" // %r9 = threadFdPub | 442 "mov 0(%%rsp), %%r9d\n" // %r9 = threadFdPub |
| 420 "add $8, %%rsp\n" | 443 "add $8, %%rsp\n" |
| 421 | 444 |
| 422 // Set up thread local storage with information on how to talk to | 445 // Set up thread local storage with information on how to talk to |
| 423 // trusted thread and trusted process. | 446 // trusted thread and trusted process. |
| 424 "lea 0xD8(%%r12), %%rsi\n" // args = &secure_mem.TLS; | 447 "lea 0xD8(%%r12), %%rsi\n" // args = &secure_mem.TLS; |
| 425 "mov $158, %%eax\n" // NR_arch_prctl | 448 "mov $158, %%eax\n" // NR_arch_prctl |
| 426 "mov $0x1001, %%edi\n" // option = ARCH_SET_GS | 449 "mov $0x1001, %%edi\n" // option = ARCH_SET_GS |
| 427 "syscall\n" | 450 "syscall\n" |
| 428 "cmp $-4095, %%rax\n" // return codes -1..-4095 are errno values | 451 "cmp $-4095, %%rax\n" // return codes -1..-4095 are errno values |
| 429 "jae 20b\n" // exit thread, unlock global mutex | 452 "jae 25b\n" // exit process |
| 430 | 453 |
| 431 // Check whether this is the initial thread, or a newly created one. | 454 // Check whether this is the initial thread, or a newly created one. |
| 432 // At startup we run the same code as when we create a new thread. At | 455 // At startup we run the same code as when we create a new thread. At |
| 433 // the very top of this function, you will find that we push 999(%rip) | 456 // the very top of this function, you will find that we push 999(%rip) |
| 434 // on the stack. That is the signal that we should return on the same | 457 // on the stack. That is the signal that we should return on the same |
| 435 // stack rather than return to where clone was called. | 458 // stack rather than return to where clone was called. |
| 436 "pop %%r15\n" | 459 "pop %%r15\n" |
| 437 "test %%r15, %%r15\n" | 460 "test %%r15, %%r15\n" |
| 438 "jne 28f\n" | 461 "jne 28f\n" |
| 439 | 462 |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 517 "jmp 26b\n" // exit process (no error message) | 540 "jmp 26b\n" // exit process (no error message) |
| 518 | 541 |
| 519 // Reap helper | 542 // Reap helper |
| 520 "29:mov %%rax, %%rdi\n" | 543 "29:mov %%rax, %%rdi\n" |
| 521 "30:xor %%rsi, %%rsi\n" | 544 "30:xor %%rsi, %%rsi\n" |
| 522 "xor %%rdx, %%rdx\n" | 545 "xor %%rdx, %%rdx\n" |
| 523 "xor %%r10, %%r10\n" | 546 "xor %%r10, %%r10\n" |
| 524 "mov $61, %%eax\n" // NR_wait4 | 547 "mov $61, %%eax\n" // NR_wait4 |
| 525 "syscall\n" | 548 "syscall\n" |
| 526 "cmp $-4, %%eax\n" // EINTR | 549 "cmp $-4, %%eax\n" // EINTR |
| 527 "jz 30\n" | 550 "jz 30b\n" |
| 528 | 551 |
| 529 // Release privileges by entering seccomp mode. | 552 // Release privileges by entering seccomp mode. |
| 530 "mov $157, %%eax\n" // NR_prctl | 553 "mov $157, %%eax\n" // NR_prctl |
| 531 "mov $22, %%edi\n" // PR_SET_SECCOMP | 554 "mov $22, %%edi\n" // PR_SET_SECCOMP |
| 532 "mov $1, %%esi\n" | 555 "mov $1, %%esi\n" |
| 533 "syscall\n" | 556 "syscall\n" |
| 534 "test %%rax, %%rax\n" | 557 "test %%rax, %%rax\n" |
| 535 "jnz 25b\n" // exit process | 558 "jnz 25b\n" // exit process |
| 536 | 559 |
| 537 // Back in the newly created sandboxed thread, wait for trusted process | 560 // Back in the newly created sandboxed thread, wait for trusted process |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 571 "pop %%rdi\n" | 594 "pop %%rdi\n" |
| 572 "pop %%rsi\n" | 595 "pop %%rsi\n" |
| 573 "pop %%rdx\n" | 596 "pop %%rdx\n" |
| 574 "pop %%rcx\n" | 597 "pop %%rcx\n" |
| 575 "pop %%rbx\n" | 598 "pop %%rbx\n" |
| 576 "pop %%rbp\n" | 599 "pop %%rbp\n" |
| 577 "ret\n" | 600 "ret\n" |
| 578 | 601 |
| 579 ".pushsection \".rodata\"\n" | 602 ".pushsection \".rodata\"\n" |
| 580 "100:.ascii \"Sandbox violation detected, program aborted\\n\"\n" | 603 "100:.ascii \"Sandbox violation detected, program aborted\\n\"\n" |
| 581 "101:\n" | 604 "101:.ascii \"WARNING! This is an expensive system call\\n\"\n" |
| 605 "102:\n" |
| 582 ".popsection\n" | 606 ".popsection\n" |
| 583 | 607 |
| 584 "999:pop %%rbp\n" | 608 "999:pop %%rbp\n" |
| 585 "pop %%rbx\n" | 609 "pop %%rbx\n" |
| 586 : | 610 : |
| 587 : "g"(&args) | 611 : "g"(&args) |
| 588 : "rax", "rcx", "rdx", "rdi", "rsi", "r8", "r9", "r10", "r11", "r12", | 612 : "rax", "rcx", "rdx", "rdi", "rsi", "r8", "r9", "r10", "r11", "r12", |
| 589 "r13", "r14", "r15", "rsp", "memory" | 613 "r13", "r14", "r15", "rsp", "memory" |
| 590 #elif defined(__i386__) | 614 #elif defined(__i386__) |
| 591 struct user_desc u; | 615 struct user_desc u; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 606 : | 630 : |
| 607 : "q"(8*u.entry_number+3)); | 631 : "q"(8*u.entry_number+3)); |
| 608 asm volatile( | 632 asm volatile( |
| 609 "push %%ebx\n" | 633 "push %%ebx\n" |
| 610 "push %%ebp\n" | 634 "push %%ebp\n" |
| 611 "movd %0, %%mm6\n" // %mm6 = args | 635 "movd %0, %%mm6\n" // %mm6 = args |
| 612 "lea 999f, %%ebx\n" // continue in same thread | 636 "lea 999f, %%ebx\n" // continue in same thread |
| 613 "movd %%ebx, %%mm3\n" | 637 "movd %%ebx, %%mm3\n" |
| 614 "xor %%ebx, %%ebx\n" // initial sequence number | 638 "xor %%ebx, %%ebx\n" // initial sequence number |
| 615 "movd %%ebx, %%mm2\n" | 639 "movd %%ebx, %%mm2\n" |
| 616 "jmp 19f\n" // create trusted thread | 640 "jmp 20f\n" // create trusted thread |
| 617 | 641 |
| 618 // TODO(markus): Coalesce the read() operations by reading into a bigger | 642 // TODO(markus): Coalesce the read() operations by reading into a bigger |
| 619 // buffer. | 643 // buffer. |
| 620 | 644 |
| 621 // Parameters: | 645 // Parameters: |
| 622 // %mm5: secure memory region | 646 // %mm5: secure memory region |
| 623 // the page following this one contains the scratch space | 647 // the page following this one contains the scratch space |
| 624 // %mm0: thread's side of threadFd | 648 // %mm0: thread's side of threadFd |
| 625 // %mm1: processFdPub | 649 // %mm1: processFdPub |
| 626 // %mm3: return address after creation of new trusted thread | 650 // %mm3: return address after creation of new trusted thread |
| (...skipping 11 matching lines...) Expand all Loading... |
| 638 // 0x00: pointer to the secure shared memory region (i.e. self) | 662 // 0x00: pointer to the secure shared memory region (i.e. self) |
| 639 // 0x04: sequence number; must match %mm2 | 663 // 0x04: sequence number; must match %mm2 |
| 640 // 0x08: system call number; passed to syscall in %eax | 664 // 0x08: system call number; passed to syscall in %eax |
| 641 // 0x0C: first argument; passed to syscall in %ebx | 665 // 0x0C: first argument; passed to syscall in %ebx |
| 642 // 0x10: second argument; passed to syscall in %ecx | 666 // 0x10: second argument; passed to syscall in %ecx |
| 643 // 0x14: third argument; passed to syscall in %edx | 667 // 0x14: third argument; passed to syscall in %edx |
| 644 // 0x18: fourth argument; passed to syscall in %esi | 668 // 0x18: fourth argument; passed to syscall in %esi |
| 645 // 0x1C: fifth argument; passed to syscall in %edi | 669 // 0x1C: fifth argument; passed to syscall in %edi |
| 646 // 0x20: sixth argument; passed to syscall in %ebp | 670 // 0x20: sixth argument; passed to syscall in %ebp |
| 647 // 0x24: stored return address for clone() system call | 671 // 0x24: stored return address for clone() system call |
| 648 // 0x28: second stored return address for clone() system call | 672 // 0x28: stored %ebp value for clone() system call |
| 649 // 0x2C: stored %ebp value for clone() system call | 673 // 0x2C: stored %edi value for clone() system call |
| 650 // 0x30: stored %edi value for clone() system call | 674 // 0x30: stored %esi value for clone() system call |
| 651 // 0x34: stored %esi value for clone() system call | 675 // 0x34: stored %edx value for clone() system call |
| 652 // 0x38: stored %edx value for clone() system call | 676 // 0x38: stored %ecx value for clone() system call |
| 653 // 0x3C: stored %ecx value for clone() system call | 677 // 0x3C: stored %ebx value for clone() system call |
| 654 // 0x40: stored %ebx value for clone() system call | 678 // 0x40: new shared memory for clone() |
| 655 // 0x44: new shared memory for clone() | 679 // 0x44: processFdPub for talking to trusted process |
| 656 // 0x48: processFdPub for talking to trusted process | 680 // 0x48: cloneFdPub for talking to trusted process |
| 657 // 0x4C: cloneFdPub for talking to trusted process | 681 // 0x4C: set to non-zero, if in debugging mode |
| 658 // 0x50: set to non-zero, if in debugging mode | 682 // 0x50: most recent SHM id returned by shmget(IPC_PRIVATE) |
| 659 // 0x54: most recent SHM id returned by shmget(IPC_PRIVATE) | 683 // 0x54: cookie assigned to us by the trusted process (TLS_COOKIE) |
| 660 // 0x58: cookie assigned to us by the trusted process (TLS_COOKIE) | 684 // 0x5C: thread id (TLS_TID) |
| 661 // 0x60: thread id (TLS_TID) | 685 // 0x64: threadFdPub (TLS_THREAD_FD) |
| 662 // 0x68: threadFdPub (TLS_THREAD_FD) | |
| 663 // 0x200-0x1000: securely passed verified file name(s) | 686 // 0x200-0x1000: securely passed verified file name(s) |
| 664 | 687 |
| 665 // Layout of (untrusted) scratch space: | 688 // Layout of (untrusted) scratch space: |
| 666 // 0x00: syscall number; passed in %eax | 689 // 0x00: syscall number; passed in %eax |
| 667 // 0x04: first argument; passed in %ebx | 690 // 0x04: first argument; passed in %ebx |
| 668 // 0x08: second argument; passed in %ecx | 691 // 0x08: second argument; passed in %ecx |
| 669 // 0x0C: third argument; passed in %edx | 692 // 0x0C: third argument; passed in %edx |
| 670 // 0x10: fourth argument; passed in %esi | 693 // 0x10: fourth argument; passed in %esi |
| 671 // 0x14: fifth argument; passed in %edi | 694 // 0x14: fifth argument; passed in %edi |
| 672 // 0x18: sixth argument; passed in %ebp | 695 // 0x18: sixth argument; passed in %ebp |
| 673 // 0x1C: return value | 696 // 0x1C: return value |
| 674 // 0x20: RDTSCP result (%eax) | 697 // 0x20: RDTSCP result (%eax) |
| 675 // 0x24: RDTSCP result (%edx) | 698 // 0x24: RDTSCP result (%edx) |
| 676 // 0x28: RDTSCP result (%ecx) | 699 // 0x28: RDTSCP result (%ecx) |
| 700 // 0x2C: last system call (updated in syscall.cc) |
| 701 // 0x30: number of consecutive calls to a time fnc. (e.g. gettimeofday) |
| 677 | 702 |
| 678 "0:xor %%esp, %%esp\n" | 703 "0:xor %%esp, %%esp\n" |
| 679 "mov $2, %%eax\n" // %mm2 = initial sequence number | 704 "mov $2, %%eax\n" // %mm2 = initial sequence number |
| 680 "movd %%eax, %%mm2\n" | 705 "movd %%eax, %%mm2\n" |
| 681 | 706 |
| 682 // Read request from untrusted thread, or from trusted process. In either | 707 // Read request from untrusted thread, or from trusted process. In either |
| 683 // case, the data that we read has to be considered untrusted. | 708 // case, the data that we read has to be considered untrusted. |
| 684 // read(threadFd, &scratch, 4) | 709 // read(threadFd, &scratch, 4) |
| 685 "1:mov $3, %%eax\n" // NR_read | 710 "1:mov $3, %%eax\n" // NR_read |
| 686 "movd %%mm0, %%ebx\n" // fd = threadFd | 711 "movd %%mm0, %%ebx\n" // fd = threadFd |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 731 "jnz 4f\n" | 756 "jnz 4f\n" |
| 732 "int $0x80\n" | 757 "int $0x80\n" |
| 733 "mov %%eax, %%ebp\n" | 758 "mov %%eax, %%ebp\n" |
| 734 "mov $120, %%eax\n" // NR_clone | 759 "mov $120, %%eax\n" // NR_clone |
| 735 "mov $17, %%ebx\n" // flags = SIGCHLD | 760 "mov $17, %%ebx\n" // flags = SIGCHLD |
| 736 "mov $1, %%ecx\n" // stack = 1 | 761 "mov $1, %%ecx\n" // stack = 1 |
| 737 "int $0x80\n" | 762 "int $0x80\n" |
| 738 "test %%eax, %%eax\n" | 763 "test %%eax, %%eax\n" |
| 739 "js 25f\n" // exit process | 764 "js 25f\n" // exit process |
| 740 "mov %%eax, %%ebx\n" | 765 "mov %%eax, %%ebx\n" |
| 741 "jnz 7f\n" // wait for child, then return result | 766 "jnz 8f\n" // wait for child, then return result |
| 742 "movd %%mm5, %%ebx\n" // start = secure_mem | 767 "movd %%mm5, %%ebx\n" // start = secure_mem |
| 743 "mov $4096, %%ecx\n" // len = 4096 | 768 "mov $4096, %%ecx\n" // len = 4096 |
| 744 "mov $3, %%edx\n" // prot = PROT_READ | PROT_WRITE | 769 "mov $3, %%edx\n" // prot = PROT_READ | PROT_WRITE |
| 745 "mov $125, %%eax\n" // NR_mprotect | 770 "mov $125, %%eax\n" // NR_mprotect |
| 746 "int $0x80\n" | 771 "int $0x80\n" |
| 747 "mov %%ebp, 0x54(%%ebx)\n" // set most recently returned SysV shm id | 772 "mov %%ebp, 0x50(%%ebx)\n" // set most recently returned SysV shm id |
| 748 "xor %%ebx, %%ebx\n" | 773 "xor %%ebx, %%ebx\n" |
| 774 |
| 775 // When debugging messages are enabled, warn about expensive system calls |
| 776 #ifndef NDEBUG |
| 777 "movd %%mm5, %%ecx\n" |
| 778 "cmpw $0, 0x4C(%%ecx)\n" // debug mode |
| 779 "jz 26f\n" |
| 780 "mov $4, %%eax\n" // NR_write |
| 781 "mov $2, %%ebx\n" // fd = stderr |
| 782 "lea 101f, %%ecx\n" // "This is an expensive system call" |
| 783 "mov $102f-101f, %%edx\n" // len = strlen(msg) |
| 784 "int $0x80\n" |
| 785 "xor %%ebx, %%ebx\n" |
| 786 #endif |
| 787 |
| 749 "jmp 26f\n" // exit program, no message | 788 "jmp 26f\n" // exit program, no message |
| 750 "4:int $0x80\n" | 789 "4:int $0x80\n" |
| 751 "jmp 14f\n" // return result | 790 "jmp 15f\n" // return result |
| 752 | 791 |
| 753 // If syscall number is -2, execute locked system call from the | 792 // If syscall number is -2, execute locked system call from the |
| 754 // secure memory area | 793 // secure memory area |
| 755 "5:jg 11f\n" | 794 "5:jg 12f\n" |
| 756 "cmp $-2, %%eax\n" | 795 "cmp $-2, %%eax\n" |
| 757 "jnz 8f\n" | 796 "jnz 9f\n" |
| 758 "movd %%mm2, %%ebp\n" | 797 "movd %%mm2, %%ebp\n" |
| 759 "cmp %%ebp, 0x4-0x1000(%%ecx)\n" | 798 "cmp %%ebp, 0x4-0x1000(%%ecx)\n" |
| 760 "jne 25f\n" // exit process | 799 "jne 25f\n" // exit process |
| 800 |
| 801 // When debugging messages are enabled, warn about expensive system calls |
| 802 #ifndef NDEBUG |
| 803 "cmpw $0, 0x4C-0x1000(%%ecx)\n" |
| 804 "jz 6f\n" // debug mode |
| 805 "mov %%ecx, %%ebp\n" |
| 806 "mov $4, %%eax\n" // NR_write |
| 807 "mov $2, %%ebx\n" // fd = stderr |
| 808 "lea 101f, %%ecx\n" // "This is an expensive system call" |
| 809 "mov $102f-101f, %%edx\n" // len = strlen(msg) |
| 810 "int $0x80\n" |
| 811 "mov %%ebp, %%ecx\n" |
| 812 "6:" |
| 813 #endif |
| 814 |
| 761 "mov 0x08-0x1000(%%ecx), %%eax\n" | 815 "mov 0x08-0x1000(%%ecx), %%eax\n" |
| 762 "mov 0x0C-0x1000(%%ecx), %%ebx\n" | 816 "mov 0x0C-0x1000(%%ecx), %%ebx\n" |
| 763 "mov 0x14-0x1000(%%ecx), %%edx\n" | 817 "mov 0x14-0x1000(%%ecx), %%edx\n" |
| 764 "mov 0x18-0x1000(%%ecx), %%esi\n" | 818 "mov 0x18-0x1000(%%ecx), %%esi\n" |
| 765 "mov 0x1C-0x1000(%%ecx), %%edi\n" | 819 "mov 0x1C-0x1000(%%ecx), %%edi\n" |
| 766 "mov 0x20-0x1000(%%ecx), %%ebp\n" | 820 "mov 0x20-0x1000(%%ecx), %%ebp\n" |
| 767 "mov 0x10-0x1000(%%ecx), %%ecx\n" | 821 "mov 0x10-0x1000(%%ecx), %%ecx\n" |
| 768 "movd %%edi, %%mm4\n" | 822 "movd %%edi, %%mm4\n" |
| 769 "movd %%ebp, %%mm7\n" | 823 "movd %%ebp, %%mm7\n" |
| 770 "movd %%mm2, %%ebp\n" | 824 "movd %%mm2, %%ebp\n" |
| 771 "movd %%mm5, %%edi\n" | 825 "movd %%mm5, %%edi\n" |
| 772 "cmp %%ebp, 4(%%edi)\n" | 826 "cmp %%ebp, 4(%%edi)\n" |
| 773 "jne 25f\n" // exit process | 827 "jne 25f\n" // exit process |
| 774 | 828 |
| 775 // clone() has unusual calling conventions and must be handled specially | 829 // clone() has unusual calling conventions and must be handled specially |
| 776 "cmp $120, %%eax\n" // NR_clone | 830 "cmp $120, %%eax\n" // NR_clone |
| 777 "jz 18f\n" | 831 "jz 19f\n" |
| 778 | 832 |
| 779 // exit() terminates trusted thread | 833 // exit() terminates trusted thread |
| 780 "cmp $1, %%eax\n" // NR_exit | 834 "cmp $1, %%eax\n" // NR_exit |
| 781 "jz 17f\n" | 835 "jz 18f\n" |
| 782 | 836 |
| 783 // Perform requested system call | 837 // Perform requested system call |
| 784 "movd %%mm4, %%edi\n" | 838 "movd %%mm4, %%edi\n" |
| 785 "movd %%mm7, %%ebp\n" | 839 "movd %%mm7, %%ebp\n" |
| 786 "int $0x80\n" | 840 "int $0x80\n" |
| 787 | 841 |
| 788 // Unlock mutex | 842 // Unlock mutex |
| 789 "6:movd %%mm2, %%ebp\n" | 843 "7:movd %%mm2, %%ebp\n" |
| 790 "movd %%mm5, %%edi\n" | 844 "movd %%mm5, %%edi\n" |
| 791 "cmp %%ebp, 4(%%edi)\n" | 845 "cmp %%ebp, 4(%%edi)\n" |
| 792 "jne 25f\n" // exit process | 846 "jne 25f\n" // exit process |
| 793 "add $2, %%ebp\n" | 847 "add $2, %%ebp\n" |
| 794 "movd %%ebp, %%mm2\n" | 848 "movd %%ebp, %%mm2\n" |
| 795 "mov %%eax, %%ebp\n" | 849 "mov %%eax, %%ebp\n" |
| 796 "mov $120, %%eax\n" // NR_clone | 850 "mov $120, %%eax\n" // NR_clone |
| 797 "mov $17, %%ebx\n" // flags = SIGCHLD | 851 "mov $17, %%ebx\n" // flags = SIGCHLD |
| 798 "mov $1, %%ecx\n" // stack = 1 | 852 "mov $1, %%ecx\n" // stack = 1 |
| 799 "int $0x80\n" | 853 "int $0x80\n" |
| 800 "test %%eax, %%eax\n" | 854 "test %%eax, %%eax\n" |
| 801 "js 25f\n" // exit process | 855 "js 25f\n" // exit process |
| 802 "jz 22f\n" // unlock and exit | 856 "jz 22f\n" // unlock and exit |
| 803 "mov %%eax, %%ebx\n" | 857 "mov %%eax, %%ebx\n" |
| 804 "7:xor %%ecx, %%ecx\n" | 858 "8:xor %%ecx, %%ecx\n" |
| 805 "xor %%edx, %%edx\n" | 859 "xor %%edx, %%edx\n" |
| 806 "mov $7, %%eax\n" // NR_waitpid | 860 "mov $7, %%eax\n" // NR_waitpid |
| 807 "int $0x80\n" | 861 "int $0x80\n" |
| 808 "cmp $-4, %%eax\n" // EINTR | 862 "cmp $-4, %%eax\n" // EINTR |
| 809 "jz 6\n" | 863 "jz 6\n" |
| 810 "mov %%ebp, %%eax\n" | 864 "mov %%ebp, %%eax\n" |
| 811 "jmp 14f\n" // return result | 865 "jmp 15f\n" // return result |
| 812 | 866 |
| 813 // If syscall number is -3, read the time stamp counter | 867 // If syscall number is -3, read the time stamp counter |
| 814 "8:cmp $-3, %%eax\n" | 868 "9:cmp $-3, %%eax\n" |
| 815 "jnz 9f\n" | 869 "jnz 10f\n" |
| 816 "rdtsc\n" // sets %edx:%eax | 870 "rdtsc\n" // sets %edx:%eax |
| 817 "xor %%ecx, %%ecx\n" | 871 "xor %%ecx, %%ecx\n" |
| 818 "jmp 10f\n" | 872 "jmp 11f\n" |
| 819 "9:cmp $-4, %%eax\n" | 873 "10:cmp $-4, %%eax\n" |
| 820 "jnz 11f\n" | 874 "jnz 12f\n" |
| 821 "rdtscp\n" // sets %edx:%eax and %ecx | 875 "rdtscp\n" // sets %edx:%eax and %ecx |
| 822 "10:movd %%mm5, %%ebx\n" | 876 "11:movd %%mm5, %%ebx\n" |
| 823 "add $0x1020, %%ebx\n" | 877 "add $0x1020, %%ebx\n" |
| 824 "mov %%eax, 0(%%ebx)\n" | 878 "mov %%eax, 0(%%ebx)\n" |
| 825 "mov %%edx, 4(%%ebx)\n" | 879 "mov %%edx, 4(%%ebx)\n" |
| 826 "mov %%ecx, 8(%%ebx)\n" | 880 "mov %%ecx, 8(%%ebx)\n" |
| 827 "mov %%ebx, %%ecx\n" | 881 "mov %%ebx, %%ecx\n" |
| 828 "mov $12, %%edx\n" | 882 "mov $12, %%edx\n" |
| 829 "jmp 15f\n" // return result | 883 "jmp 16f\n" // return result |
| 830 | 884 |
| 831 // Check in syscallTable whether this system call is unrestricted | 885 // Check in syscallTable whether this system call is unrestricted |
| 832 "11:mov %%eax, %%ebp\n" | 886 "12:mov %%eax, %%ebp\n" |
| 833 #ifndef NDEBUG | 887 #ifndef NDEBUG |
| 834 "cmpw $0, 0x50-0x1000(%%ecx)\n" | 888 "cmpw $0, 0x4C-0x1000(%%ecx)\n" |
| 835 "jnz 12f\n" // debug mode | 889 "jnz 13f\n" // debug mode |
| 836 #endif | 890 #endif |
| 837 "cmp playground$maxSyscall, %%eax\n" | 891 "cmp playground$maxSyscall, %%eax\n" |
| 838 "ja 25f\n" // exit process | 892 "ja 25f\n" // exit process |
| 839 "shl $3, %%eax\n" | 893 "shl $3, %%eax\n" |
| 840 "add $playground$syscallTable, %%eax\n" | 894 "add $playground$syscallTable, %%eax\n" |
| 841 "mov 0(%%eax), %%eax\n" | 895 "mov 0(%%eax), %%eax\n" |
| 842 "cmp $1, %%eax\n" | 896 "cmp $1, %%eax\n" |
| 843 "jne 25f\n" // exit process | 897 "jne 25f\n" // exit process |
| 844 | 898 |
| 845 // Default behavior for unrestricted system calls is to just execute | 899 // Default behavior for unrestricted system calls is to just execute |
| 846 // them. Read the remaining arguments first. | 900 // them. Read the remaining arguments first. |
| 847 "12:mov $3, %%eax\n" // NR_read | 901 "13:mov $3, %%eax\n" // NR_read |
| 848 "movd %%mm0, %%ebx\n" // fd = threadFd | 902 "movd %%mm0, %%ebx\n" // fd = threadFd |
| 849 "add $4, %%ecx\n" // buf = &scratch + 4 | 903 "add $4, %%ecx\n" // buf = &scratch + 4 |
| 850 "mov $24, %%edx\n" // len = 6*sizeof(void *) | 904 "mov $24, %%edx\n" // len = 6*sizeof(void *) |
| 851 "13:int $0x80\n" | 905 "14:int $0x80\n" |
| 852 "cmp $-4, %%eax\n" // EINTR | 906 "cmp $-4, %%eax\n" // EINTR |
| 853 "jz 13b\n" | 907 "jz 14b\n" |
| 854 "cmp %%edx, %%eax\n" | 908 "cmp %%edx, %%eax\n" |
| 855 "jnz 25f\n" // exit process | 909 "jnz 25f\n" // exit process |
| 856 "mov %%ebp, %%eax\n" | 910 "mov %%ebp, %%eax\n" |
| 857 "mov 0x00(%%ecx), %%ebx\n" | 911 "mov 0x00(%%ecx), %%ebx\n" |
| 858 "mov 0x08(%%ecx), %%edx\n" | 912 "mov 0x08(%%ecx), %%edx\n" |
| 859 "mov 0x0C(%%ecx), %%esi\n" | 913 "mov 0x0C(%%ecx), %%esi\n" |
| 860 "mov 0x10(%%ecx), %%edi\n" | 914 "mov 0x10(%%ecx), %%edi\n" |
| 861 "mov 0x14(%%ecx), %%ebp\n" | 915 "mov 0x14(%%ecx), %%ebp\n" |
| 862 "mov 0x04(%%ecx), %%ecx\n" | 916 "mov 0x04(%%ecx), %%ecx\n" |
| 863 "cmp $252, %%eax\n" // NR_exit_group | 917 "cmp $252, %%eax\n" // NR_exit_group |
| 864 "jz 26f\n" // exit program, no message | 918 "jz 26f\n" // exit program, no message |
| 865 "int $0x80\n" | 919 "int $0x80\n" |
| 866 | 920 |
| 867 // Return result of system call to sandboxed thread | 921 // Return result of system call to sandboxed thread |
| 868 "14:movd %%mm5, %%ecx\n" | 922 "15:movd %%mm5, %%ecx\n" |
| 869 "add $0x101C, %%ecx\n" // buf = &scratch + 28 | 923 "add $0x101C, %%ecx\n" // buf = &scratch + 28 |
| 870 "mov %%eax, (%%ecx)\n" | 924 "mov %%eax, (%%ecx)\n" |
| 871 "mov $4, %%edx\n" // len = 4 | 925 "mov $4, %%edx\n" // len = 4 |
| 872 "15:movd %%mm0, %%ebx\n" // fd = threadFd | 926 "16:movd %%mm0, %%ebx\n" // fd = threadFd |
| 873 "mov $4, %%eax\n" // NR_write | 927 "mov $4, %%eax\n" // NR_write |
| 874 "16:int $0x80\n" | 928 "17:int $0x80\n" |
| 875 "cmp %%edx, %%eax\n" | 929 "cmp %%edx, %%eax\n" |
| 876 "jz 1b\n" | 930 "jz 1b\n" |
| 877 "cmp $-4, %%eax\n" // EINTR | 931 "cmp $-4, %%eax\n" // EINTR |
| 878 "jz 16b\n" | 932 "jz 17b\n" |
| 879 "jmp 25f\n" // exit process | 933 "jmp 25f\n" // exit process |
| 880 | 934 |
| 881 // NR_exit: | 935 // NR_exit: |
| 882 // Exit trusted thread after cleaning up resources | 936 // Exit trusted thread after cleaning up resources |
| 883 "17:mov %%edi, %%ecx\n" | 937 "18:mov %%edi, %%ecx\n" |
| 884 "mov 0x68(%%ecx), %%ebx\n" // fd = threadFdPub | 938 "mov 0x64(%%ecx), %%ebx\n" // fd = threadFdPub |
| 885 "mov $6, %%eax\n" // NR_close | 939 "mov $6, %%eax\n" // NR_close |
| 886 "int $0x80\n" | 940 "int $0x80\n" |
| 887 "mov %%ecx, %%ebx\n" // start = secure_mem | 941 "mov %%ecx, %%ebx\n" // start = secure_mem |
| 888 "mov $8192, %%ecx\n" // length = 4096 | 942 "mov $8192, %%ecx\n" // length = 8192 |
| 889 "xor %%edx, %%edx\n" // prot = PROT_NONE | 943 "xor %%edx, %%edx\n" // prot = PROT_NONE |
| 890 "mov $125, %%eax\n" // NR_mprotect | 944 "mov $125, %%eax\n" // NR_mprotect |
| 891 "int $0x80\n" | 945 "int $0x80\n" |
| 892 "movd %%mm0, %%ebx\n" // fd = threadFd | 946 "movd %%mm0, %%ebx\n" // fd = threadFd |
| 893 "mov $6, %%eax\n" // NR_close | 947 "mov $6, %%eax\n" // NR_close |
| 894 "int $0x80\n" | 948 "int $0x80\n" |
| 895 "mov $120, %%eax\n" // NR_clone | 949 "mov $120, %%eax\n" // NR_clone |
| 896 "mov $17, %%ebx\n" // flags = SIGCHLD | 950 "mov $17, %%ebx\n" // flags = SIGCHLD |
| 897 "mov $1, %%ecx\n" // stack = 1 | 951 "mov $1, %%ecx\n" // stack = 1 |
| 898 "int $0x80\n" | 952 "int $0x80\n" |
| 899 "mov %%eax, %%ebx\n" | 953 "mov %%eax, %%ebx\n" |
| 900 "test %%eax, %%eax\n" | 954 "test %%eax, %%eax\n" |
| 955 "js 25f\n" // exit process |
| 901 "jne 21f\n" // reap helper, exit thread | 956 "jne 21f\n" // reap helper, exit thread |
| 902 "jmp 22f\n" // unlock mutex | 957 "jmp 22f\n" // unlock mutex |
| 903 | 958 |
| 904 // NR_clone: | 959 // NR_clone: |
| 905 // Original trusted thread calls clone() to create new nascent | 960 // Original trusted thread calls clone() to create new nascent |
| 906 // thread. This thread is (typically) fully privileged and shares all | 961 // thread. This thread is (typically) fully privileged and shares all |
| 907 // resources with the caller (i.e. the previous trusted thread), | 962 // resources with the caller (i.e. the previous trusted thread), |
| 908 // and by extension it shares all resources with the sandbox'd | 963 // and by extension it shares all resources with the sandbox'd |
| 909 // threads. | 964 // threads. |
| 910 // N.B. It is possible to make the thread creation code crash before | 965 // N.B. It is possible to make the thread creation code crash before |
| 911 // it releases seccomp privileges. This is generally OK, as it just | 966 // it releases seccomp privileges. This is generally OK, as it just |
| 912 // terminates the program. But if we ever support signal handling, | 967 // terminates the program. But if we ever support signal handling, |
| 913 // we have to be careful that the user cannot install a SIGSEGV | 968 // we have to be careful that the user cannot install a SIGSEGV |
| 914 // handler that gets executed with elevated privileges. | 969 // handler that gets executed with elevated privileges. |
| 915 "18:movd %%edi, %%mm6\n" // %mm6 = old_shared_mem | 970 "19:movd %%edi, %%mm6\n" // %mm6 = old_shared_mem |
| 916 "movd %%mm4, %%edi\n" | 971 "movd %%mm4, %%edi\n" |
| 917 "movd %%mm7, %%ebp\n" | 972 "movd %%mm7, %%ebp\n" |
| 918 "int $0x80\n" // calls NR_clone | 973 "int $0x80\n" // calls NR_clone |
| 919 "cmp $-4095, %%eax\n" // return codes -1..-4095 are errno values | 974 "cmp $-4095, %%eax\n" // return codes -1..-4095 are errno values |
| 920 "jae 6b\n" | 975 "jae 7b\n" // unlock mutex, return result |
| 921 "movd %%mm2, %%edi\n" | 976 "movd %%mm2, %%edi\n" |
| 922 "add $2, %%edi\n" | 977 "add $2, %%edi\n" |
| 923 "movd %%edi, %%mm2\n" | 978 "movd %%edi, %%mm2\n" |
| 924 "test %%eax, %%eax\n" | 979 "test %%eax, %%eax\n" |
| 925 "jne 14b\n" // return result | 980 "jne 15b\n" // return result |
| 926 | 981 |
| 927 // In nascent thread, now. | 982 // In nascent thread, now. |
| 928 "sub $2, %%edi\n" | 983 "sub $2, %%edi\n" |
| 929 "movd %%edi, %%mm2\n" | 984 "movd %%edi, %%mm2\n" |
| 930 "movd %%eax, %%mm3\n" // Request to return from clone() when done | 985 "movd %%eax, %%mm3\n" // Request to return from clone() when done |
| 931 | 986 |
| 932 // Get thread id of nascent thread | 987 // Get thread id of nascent thread |
| 933 "19:mov $224, %%eax\n" // NR_gettid | 988 "20:mov $224, %%eax\n" // NR_gettid |
| 934 "int $0x80\n" | 989 "int $0x80\n" |
| 935 "movd %%eax, %%mm4\n" | 990 "movd %%eax, %%mm4\n" |
| 936 | 991 |
| 937 // Nascent thread creates socketpair() for sending requests to | 992 // Nascent thread creates socketpair() for sending requests to |
| 938 // trusted thread. | 993 // trusted thread. |
| 939 // We can create the filehandles on the stack. Filehandles are | 994 // We can create the filehandles on the stack. Filehandles are |
| 940 // always treated as untrusted. | 995 // always treated as untrusted. |
| 941 // socketpair(AF_UNIX, SOCK_STREAM, 0, fds) | 996 // socketpair(AF_UNIX, SOCK_STREAM, 0, fds) |
| 942 "mov $102, %%eax\n" // NR_socketcall | 997 "mov $102, %%eax\n" // NR_socketcall |
| 943 "mov $8, %%ebx\n" // socketpair | 998 "mov $8, %%ebx\n" // socketpair |
| 944 "sub $8, %%esp\n" // sv = %rsp | 999 "sub $8, %%esp\n" // sv = %rsp |
| 945 "push %%esp\n" | 1000 "push %%esp\n" |
| 946 "xor %%ecx, %%ecx\n" // protocol = 0 | 1001 "xor %%ecx, %%ecx\n" // protocol = 0 |
| 947 "push %%ecx\n" | 1002 "push %%ecx\n" |
| 948 "mov $1, %%ecx\n" // type = SOCK_STREAM | 1003 "mov $1, %%ecx\n" // type = SOCK_STREAM |
| 949 "push %%ecx\n" | 1004 "push %%ecx\n" |
| 950 "push %%ecx\n" // domain = AF_UNIX | 1005 "push %%ecx\n" // domain = AF_UNIX |
| 951 "mov %%esp, %%ecx\n" | 1006 "mov %%esp, %%ecx\n" |
| 952 "int $0x80\n" | 1007 "int $0x80\n" |
| 953 "add $0x10, %%esp\n" | 1008 "add $0x10, %%esp\n" |
| 954 "test %%eax, %%eax\n" | 1009 "test %%eax, %%eax\n" |
| 955 "jz 27f\n" | 1010 "jz 27f\n" |
| 956 | 1011 |
| 957 // If things went wrong, we don't have an (easy) way of signaling | 1012 // If things went wrong, we don't have an (easy) way of signaling |
| 958 // the parent. For our purposes, it is sufficient to fail with a | 1013 // the parent. For our purposes, it is sufficient to fail with a |
| 959 // fatal error. | 1014 // fatal error. |
| 960 "jmp 25f\n" // exit process | 1015 "jmp 25f\n" // exit process |
| 961 "20:mov $120, %%eax\n" // NR_clone | |
| 962 "mov $17, %%ebx\n" // flags = SIGCHLD | |
| 963 "mov $1, %%ecx\n" // stack = 1 | |
| 964 "int $0x80\n" | |
| 965 "test %%eax, %%eax\n" | |
| 966 "js 25f\n" // exit process | |
| 967 "jz 22f\n" // unlock and exit | |
| 968 "mov %%eax, %%ebx\n" | |
| 969 "21:xor %%ecx, %%ecx\n" | 1016 "21:xor %%ecx, %%ecx\n" |
| 970 "xor %%edx, %%edx\n" | 1017 "xor %%edx, %%edx\n" |
| 971 "mov $7, %%eax\n" // NR_waitpid | 1018 "mov $7, %%eax\n" // NR_waitpid |
| 972 "int $0x80\n" | 1019 "int $0x80\n" |
| 973 "cmp $-4, %%eax\n" // EINTR | 1020 "cmp $-4, %%eax\n" // EINTR |
| 974 "jz 21b\n" | 1021 "jz 21b\n" |
| 975 "jmp 23f\n" // exit thread (no message) | 1022 "jmp 23f\n" // exit thread (no message) |
| 976 "22:lea playground$syscall_mutex, %%ebx\n" | 1023 "22:lea playground$syscall_mutex, %%ebx\n" |
| 977 "mov $4096, %%ecx\n" | 1024 "mov $4096, %%ecx\n" |
| 978 "mov $3, %%edx\n" // prot = PROT_READ | PROT_WRITE | 1025 "mov $3, %%edx\n" // prot = PROT_READ | PROT_WRITE |
| 979 "mov $125, %%eax\n" // NR_mprotect | 1026 "mov $125, %%eax\n" // NR_mprotect |
| 980 "int $0x80\n" | 1027 "int $0x80\n" |
| 981 "lock; addl $0x80000000, (%%ebx)\n" | 1028 "lock; addl $0x80000000, (%%ebx)\n" |
| 982 "jz 23f\n" // exit thread | 1029 "jz 23f\n" // exit thread |
| 983 "mov $1, %%edx\n" | 1030 "mov $1, %%edx\n" |
| 984 "mov %%edx, %%ecx\n" // FUTEX_WAKE | 1031 "mov %%edx, %%ecx\n" // FUTEX_WAKE |
| 985 "mov $240, %%eax\n" // NR_futex | 1032 "mov $240, %%eax\n" // NR_futex |
| 986 "int $0x80\n" | 1033 "int $0x80\n" |
| 987 "23:mov $1, %%eax\n" // NR_exit | 1034 "23:mov $1, %%eax\n" // NR_exit |
| 988 "mov $1, %%ebx\n" // status = 1 | 1035 "mov $1, %%ebx\n" // status = 1 |
| 989 "24:int $0x80\n" | 1036 "24:int $0x80\n" |
| 990 "25:mov $4, %%eax\n" // NR_write | 1037 "25:mov $4, %%eax\n" // NR_write |
| 991 "mov $2, %%ebx\n" // fd = stderr | 1038 "mov $2, %%ebx\n" // fd = stderr |
| 992 "lea 100f, %%ecx\n" | 1039 "lea 100f, %%ecx\n" // "Sandbox violation detected" |
| 993 "mov $101f-100f, %%edx\n" // len = strlen(msg) | 1040 "mov $101f-100f, %%edx\n" // len = strlen(msg) |
| 994 "int $0x80\n" | 1041 "int $0x80\n" |
| 995 "mov $1, %%ebx\n" | 1042 "mov $1, %%ebx\n" |
| 996 "26:mov $252, %%eax\n" // NR_exit_group | 1043 "26:mov $252, %%eax\n" // NR_exit_group |
| 997 "jmp 24b\n" | 1044 "jmp 24b\n" |
| 998 | 1045 |
| 999 // The first page is mapped read-only for use as securely shared memory | 1046 // The first page is mapped read-only for use as securely shared memory |
| 1000 "27:movd %%mm6, %%ebp\n" | 1047 "27:movd %%mm6, %%ebp\n" |
| 1001 "mov 0x44(%%ebp), %%esi\n" | 1048 "mov 0x40(%%ebp), %%esi\n" |
| 1002 "movd %%esi, %%mm5\n" // %mm5 = secure shared memory | 1049 "movd %%esi, %%mm5\n" // %mm5 = secure shared memory |
| 1003 "movd %%mm2, %%edi\n" | 1050 "movd %%mm2, %%edi\n" |
| 1004 "cmp %%edi, 4(%%ebp)\n" | 1051 "cmp %%edi, 4(%%ebp)\n" |
| 1005 "jne 25b\n" // exit process | 1052 "jne 25b\n" // exit process |
| 1006 "mov $125, %%eax\n" // NR_mprotect | 1053 "mov $125, %%eax\n" // NR_mprotect |
| 1007 "mov %%esi, %%ebx\n" | 1054 "mov %%esi, %%ebx\n" |
| 1008 "mov $4096, %%ecx\n" // len = 4096 | 1055 "mov $4096, %%ecx\n" // len = 4096 |
| 1009 "mov $1, %%edx\n" // prot = PROT_READ | 1056 "mov $1, %%edx\n" // prot = PROT_READ |
| 1010 "int $0x80\n" | 1057 "int $0x80\n" |
| 1011 | 1058 |
| 1012 // The second page is used as scratch space by the trusted thread. | 1059 // The second page is used as scratch space by the trusted thread. |
| 1013 // Make it writable. | 1060 // Make it writable. |
| 1014 "mov $125, %%eax\n" // NR_mprotect | 1061 "mov $125, %%eax\n" // NR_mprotect |
| 1015 "add $4096, %%ebx\n" // addr = secure_mem + 4096 | 1062 "add $4096, %%ebx\n" // addr = secure_mem + 4096 |
| 1016 "mov $3, %%edx\n" // prot = PROT_READ | PROT_WRITE | 1063 "mov $3, %%edx\n" // prot = PROT_READ | PROT_WRITE |
| 1017 "int $0x80\n" | 1064 "int $0x80\n" |
| 1018 | 1065 |
| 1019 // Call clone() to create new trusted thread(). | 1066 // Call clone() to create new trusted thread(). |
| 1020 // clone(CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD| | 1067 // clone(CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD| |
| 1021 // CLONE_SYSVSEM|CLONE_UNTRACED, stack, NULL, NULL, NULL) | 1068 // CLONE_SYSVSEM|CLONE_UNTRACED, stack, NULL, NULL, NULL) |
| 1022 "mov 4(%%esp), %%eax\n" | 1069 "mov 4(%%esp), %%eax\n" |
| 1023 "movd %%eax, %%mm0\n" // %mm0 = threadFd | 1070 "movd %%eax, %%mm0\n" // %mm0 = threadFd |
| 1024 "mov $120, %%eax\n" // NR_clone | 1071 "mov $120, %%eax\n" // NR_clone |
| 1025 "mov $0x850F00, %%ebx\n" // flags = VM|FS|FILES|SIGH|THR|SYSV|UTR | 1072 "mov $0x850F00, %%ebx\n" // flags = VM|FS|FILES|SIGH|THR|SYSV|UTR |
| 1026 "mov $1, %%ecx\n" // stack = 1 | 1073 "mov $1, %%ecx\n" // stack = 1 |
| 1027 "movd 0x48(%%ebp), %%mm1\n" // %mm1 = processFdPub | 1074 "movd 0x44(%%ebp), %%mm1\n" // %mm1 = processFdPub |
| 1028 "cmp %%edi, 4(%%ebp)\n" | 1075 "cmp %%edi, 4(%%ebp)\n" |
| 1029 "jne 25b\n" // exit process | 1076 "jne 25b\n" // exit process |
| 1030 "int $0x80\n" | 1077 "int $0x80\n" |
| 1031 "test %%eax, %%eax\n" | 1078 "test %%eax, %%eax\n" |
| 1032 "js 25b\n" // exit process | 1079 "js 25b\n" // exit process |
| 1033 "jz 0b\n" // invoke trustedThreadFnc() | 1080 "jz 0b\n" // invoke trustedThreadFnc() |
| 1034 | 1081 |
| 1035 // Set up thread local storage | 1082 // Set up thread local storage |
| 1036 "mov $0x51, %%eax\n" // seg_32bit, limit_in_pages, useable | 1083 "mov $0x51, %%eax\n" // seg_32bit, limit_in_pages, useable |
| 1037 "push %%eax\n" | 1084 "push %%eax\n" |
| 1038 "mov $0xFFFFF, %%eax\n" // limit | 1085 "mov $0xFFFFF, %%eax\n" // limit |
| 1039 "push %%eax\n" | 1086 "push %%eax\n" |
| 1040 "add $0x58, %%esi\n" | 1087 "add $0x54, %%esi\n" |
| 1041 "push %%esi\n" // base_addr = &secure_mem.TLS | 1088 "push %%esi\n" // base_addr = &secure_mem.TLS |
| 1042 "mov %%fs, %%eax\n" | 1089 "mov %%fs, %%eax\n" |
| 1043 "shr $3, %%eax\n" | 1090 "shr $3, %%eax\n" |
| 1044 "push %%eax\n" // entry_number | 1091 "push %%eax\n" // entry_number |
| 1045 "mov $243, %%eax\n" // NR_set_thread_area | 1092 "mov $243, %%eax\n" // NR_set_thread_area |
| 1046 "mov %%esp, %%ebx\n" | 1093 "mov %%esp, %%ebx\n" |
| 1047 "int $0x80\n" | 1094 "int $0x80\n" |
| 1048 "test %%eax, %%eax\n" | 1095 "test %%eax, %%eax\n" |
| 1049 "jnz 25b\n" // exit process | 1096 "jnz 25b\n" // exit process |
| 1050 "add $16, %%esp\n" | 1097 "add $16, %%esp\n" |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1073 "mov 0x2C(%%ebp), %%eax\n" | 1120 "mov 0x2C(%%ebp), %%eax\n" |
| 1074 "push %%eax\n" | 1121 "push %%eax\n" |
| 1075 "mov 0x30(%%ebp), %%eax\n" | 1122 "mov 0x30(%%ebp), %%eax\n" |
| 1076 "push %%eax\n" | 1123 "push %%eax\n" |
| 1077 "mov 0x34(%%ebp), %%eax\n" | 1124 "mov 0x34(%%ebp), %%eax\n" |
| 1078 "push %%eax\n" | 1125 "push %%eax\n" |
| 1079 "mov 0x38(%%ebp), %%eax\n" | 1126 "mov 0x38(%%ebp), %%eax\n" |
| 1080 "push %%eax\n" | 1127 "push %%eax\n" |
| 1081 "mov 0x3C(%%ebp), %%eax\n" | 1128 "mov 0x3C(%%ebp), %%eax\n" |
| 1082 "push %%eax\n" | 1129 "push %%eax\n" |
| 1083 "mov 0x40(%%ebp), %%eax\n" | |
| 1084 "push %%eax\n" | |
| 1085 "cmp %%edi, 4(%%ebp)\n" | 1130 "cmp %%edi, 4(%%ebp)\n" |
| 1086 "jne 25b\n" // exit process | 1131 "jne 25b\n" // exit process |
| 1087 | 1132 |
| 1088 // Nascent thread launches a helper that doesn't share any of our | 1133 // Nascent thread launches a helper that doesn't share any of our |
| 1089 // resources, except for pages mapped as MAP_SHARED. | 1134 // resources, except for pages mapped as MAP_SHARED. |
| 1090 // clone(0, %esp) | 1135 // clone(0, %esp) |
| 1091 "28:mov $120, %%eax\n" // NR_clone | 1136 "28:mov $120, %%eax\n" // NR_clone |
| 1092 "mov $17, %%ebx\n" // flags = SIGCHLD | 1137 "mov $17, %%ebx\n" // flags = SIGCHLD |
| 1093 "mov %%esp, %%ecx\n" // stack = %esp | 1138 "mov %%esp, %%ecx\n" // stack = %esp |
| 1094 "int $0x80\n" | 1139 "int $0x80\n" |
| 1095 "test %%eax, %%eax\n" | 1140 "test %%eax, %%eax\n" |
| 1096 "js 25b\n" // exit process | 1141 "js 25b\n" // exit process |
| 1097 "jne 29f\n" | 1142 "jne 29f\n" |
| 1098 | 1143 |
| 1099 // Use sendmsg() to send to the trusted process the file handles for | 1144 // Use sendmsg() to send to the trusted process the file handles for |
| 1100 // communicating with the new trusted thread. We also send the address | 1145 // communicating with the new trusted thread. We also send the address |
| 1101 // of the secure memory area (for sanity checks) and the thread id. | 1146 // of the secure memory area (for sanity checks) and the thread id. |
| 1102 "push %%esi\n" // threadFdPub | 1147 "push %%esi\n" // threadFdPub |
| 1103 "movd %%mm4, %%eax\n" // threadId | 1148 "movd %%mm4, %%eax\n" // threadId |
| 1104 "push %%eax\n" | 1149 "push %%eax\n" |
| 1105 "movd %%mm5, %%eax\n" // secure_mem | 1150 "movd %%mm5, %%eax\n" // secure_mem |
| 1106 "push %%eax\n" | 1151 "push %%eax\n" |
| 1107 "mov %%esp, %%ebx\n" // buf = &data | 1152 "mov %%esp, %%ebx\n" // buf = &data |
| 1108 "mov $12, %%eax\n" // len = sizeof(void*) + 2*sizeof(int) | 1153 "mov $12, %%eax\n" // len = sizeof(void*) + 2*sizeof(int) |
| 1109 "push %%eax\n" | 1154 "push %%eax\n" |
| 1110 "push %%ebx\n" | 1155 "push %%ebx\n" |
| 1111 "movd %%mm0, %%eax\n" // fd1 = threadFd | 1156 "movd %%mm0, %%eax\n" // fd1 = threadFd |
| 1112 "push %%eax\n" | 1157 "push %%eax\n" |
| 1113 "push %%esi\n" // fd0 = threadFdPub | 1158 "push %%esi\n" // fd0 = threadFdPub |
| 1114 "mov 0x4C(%%ebp), %%eax\n" // transport = Sandbox::cloneFdPub() | 1159 "mov 0x48(%%ebp), %%eax\n" // transport = Sandbox::cloneFdPub() |
| 1115 "cmp %%edi, 4(%%ebp)\n" | 1160 "cmp %%edi, 4(%%ebp)\n" |
| 1116 "jne 25b\n" // exit process | 1161 "jne 25b\n" // exit process |
| 1117 "push %%eax\n" | 1162 "push %%eax\n" |
| 1118 "call playground$sendFd\n" | 1163 "call playground$sendFd\n" |
| 1119 | 1164 |
| 1120 // Release syscall_mutex_. This signals the trusted process that | 1165 // Release syscall_mutex_. This signals the trusted process that |
| 1121 // it can write into the original thread's secure memory again. | 1166 // it can write into the original thread's secure memory again. |
| 1122 "mov $125, %%eax\n" // NR_mprotect | 1167 "mov $125, %%eax\n" // NR_mprotect |
| 1123 "lea playground$syscall_mutex, %%ebx\n" | 1168 "lea playground$syscall_mutex, %%ebx\n" |
| 1124 "mov $4096, %%ecx\n" | 1169 "mov $4096, %%ecx\n" |
| 1125 "mov $3, %%edx\n" // PROT_READ | PROT_WRITE | 1170 "mov $3, %%edx\n" // PROT_READ | PROT_WRITE |
| 1126 "int $0x80\n" | 1171 "int $0x80\n" |
| 1127 "lock; addl $0x80000000, (%%ebx)\n" | 1172 "lock; addl $0x80000000, (%%ebx)\n" |
| 1128 "jz 26b\n" // exit process (no error message) | 1173 "jz 26b\n" // exit process (no error message) |
| 1129 "mov $1, %%edx\n" | 1174 "mov $1, %%edx\n" |
| 1130 "mov %%edx, %%ecx\n" // FUTEX_WAKE | 1175 "mov %%edx, %%ecx\n" // FUTEX_WAKE |
| 1131 "mov $240, %%eax\n" // NR_futex | 1176 "mov $240, %%eax\n" // NR_futex |
| 1132 "int $0x80\n" | 1177 "int $0x80\n" |
| 1133 "jmp 26b\n" // exit process (no error message) | 1178 "jmp 26b\n" // exit process (no error message) |
| 1134 | 1179 |
| 1135 // Reap helper | 1180 // Reap helper |
| 1136 "29:mov %%eax, %%ebx\n" | 1181 "29:mov %%eax, %%ebx\n" |
| 1137 "30:xor %%ecx, %%ecx\n" | 1182 "30:xor %%ecx, %%ecx\n" |
| 1138 "xor %%edx, %%edx\n" | 1183 "xor %%edx, %%edx\n" |
| 1139 "mov $7, %%eax\n" // NR_waitpid | 1184 "mov $7, %%eax\n" // NR_waitpid |
| 1140 "int $0x80\n" | 1185 "int $0x80\n" |
| 1141 "cmp $-4, %%eax\n" // EINTR | 1186 "cmp $-4, %%eax\n" // EINTR |
| 1142 "jz 30\n" | 1187 "jz 30b\n" |
| 1143 | 1188 |
| 1144 // Release privileges by entering seccomp mode. | 1189 // Release privileges by entering seccomp mode. |
| 1145 "mov $172, %%eax\n" // NR_prctl | 1190 "mov $172, %%eax\n" // NR_prctl |
| 1146 "mov $22, %%ebx\n" // PR_SET_SECCOMP | 1191 "mov $22, %%ebx\n" // PR_SET_SECCOMP |
| 1147 "mov $1, %%ecx\n" | 1192 "mov $1, %%ecx\n" |
| 1148 "int $0x80\n" | 1193 "int $0x80\n" |
| 1149 "test %%eax, %%eax\n" | 1194 "test %%eax, %%eax\n" |
| 1150 "jnz 25b\n" // exit process | 1195 "jnz 25b\n" // exit process |
| 1151 | 1196 |
| 1152 // Back in the newly created sandboxed thread, wait for trusted process | 1197 // Back in the newly created sandboxed thread, wait for trusted process |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1183 "32:pop %%ebx\n" | 1228 "32:pop %%ebx\n" |
| 1184 "pop %%ecx\n" | 1229 "pop %%ecx\n" |
| 1185 "pop %%edx\n" | 1230 "pop %%edx\n" |
| 1186 "pop %%esi\n" | 1231 "pop %%esi\n" |
| 1187 "pop %%edi\n" | 1232 "pop %%edi\n" |
| 1188 "pop %%ebp\n" | 1233 "pop %%ebp\n" |
| 1189 "ret\n" | 1234 "ret\n" |
| 1190 | 1235 |
| 1191 ".pushsection \".rodata\"\n" | 1236 ".pushsection \".rodata\"\n" |
| 1192 "100:.ascii \"Sandbox violation detected, program aborted\\n\"\n" | 1237 "100:.ascii \"Sandbox violation detected, program aborted\\n\"\n" |
| 1193 "101:\n" | 1238 "101:.ascii \"WARNING! This is an expensive system call\\n\"\n" |
| 1239 "102:\n" |
| 1194 ".popsection\n" | 1240 ".popsection\n" |
| 1195 | 1241 |
| 1196 "999:pop %%ebp\n" | 1242 "999:pop %%ebp\n" |
| 1197 "pop %%ebx\n" | 1243 "pop %%ebx\n" |
| 1198 : | 1244 : |
| 1199 : "g"(&args) | 1245 : "g"(&args) |
| 1200 : "eax", "ecx", "edx", "edi", "esi", "esp", "memory" | 1246 : "eax", "ecx", "edx", "edi", "esi", "esp", "memory" |
| 1201 #else | 1247 #else |
| 1202 #error Unsupported target platform | 1248 #error Unsupported target platform |
| 1203 #endif | 1249 #endif |
| 1204 ); | 1250 ); |
| 1205 } | 1251 } |
| 1206 | 1252 |
| 1207 } // namespace | 1253 } // namespace |
| OLD | NEW |