| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 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 | 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 "syscall_entrypoint.h" | 5 #include "syscall_entrypoint.h" |
| 6 | 6 |
| 7 #include "debug.h" | 7 #include "debug.h" |
| 8 #include "sandbox_impl.h" | 8 #include "sandbox_impl.h" |
| 9 #include "system_call_table.h" | 9 #include "system_call_table.h" |
| 10 | 10 |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 169 "jmp 2b\n" | 169 "jmp 2b\n" |
| 170 #elif defined(__i386__) | 170 #elif defined(__i386__) |
| 171 "cmp $119, %eax\n" // NR_sigreturn | 171 "cmp $119, %eax\n" // NR_sigreturn |
| 172 "jnz 1f\n" | 172 "jnz 1f\n" |
| 173 "add $0x8, %esp\n" // pop return address | 173 "add $0x8, %esp\n" // pop return address |
| 174 "0:int $0x80\n" // sigreturn() is unrestricted | 174 "0:int $0x80\n" // sigreturn() is unrestricted |
| 175 "mov $66, %ebx\n" // sigreturn() should never return | 175 "mov $66, %ebx\n" // sigreturn() should never return |
| 176 "mov %ebx, %eax\n" // NR_exit | 176 "mov %ebx, %eax\n" // NR_exit |
| 177 "jmp 0b\n" | 177 "jmp 0b\n" |
| 178 "1:cmp $173, %eax\n" // NR_rt_sigreturn | 178 "1:cmp $173, %eax\n" // NR_rt_sigreturn |
| 179 "jnz 3f\n" | 179 "jnz 4f\n" |
| 180 | 180 |
| 181 // Convert rt_sigframe into sigframe, allowing us to call sigreturn(). | 181 // Convert rt_sigframe into sigframe, allowing us to call sigreturn(). |
| 182 // This is possible since the first part of signal stack frames have | 182 // This is possible since the first part of signal stack frames have |
| 183 // stayed very stable since the earliest kernel versions. While never | 183 // stayed very stable since the earliest kernel versions. While never |
| 184 // officially documented, lots of user space applications rely on this | 184 // officially documented, lots of user space applications rely on this |
| 185 // part of the ABI, and kernel developers have been careful to maintain | 185 // part of the ABI, and kernel developers have been careful to maintain |
| 186 // backwards compatibility. | 186 // backwards compatibility. |
| 187 // In general, the rt_sigframe includes a lot of extra information that | 187 // In general, the rt_sigframe includes a lot of extra information that |
| 188 // the signal handler can look at. Most notably, this means a complete | 188 // the signal handler can look at. Most notably, this means a complete |
| 189 // siginfo record. | 189 // siginfo record. |
| 190 // Fortunately though, the kernel doesn't look at any of this extra data | 190 // Fortunately though, the kernel doesn't look at any of this extra data |
| 191 // when returning from a signal handler. So, we can safely convert an | 191 // when returning from a signal handler. So, we can safely convert an |
| 192 // rt_sigframe to a legacy sigframe, discarding the extra data in the | 192 // rt_sigframe to a legacy sigframe, discarding the extra data in the |
| 193 // process. Interestingly, the legacy signal frame is actually larger than | 193 // process. Interestingly, the legacy signal frame is actually larger than |
| 194 // the rt signal frame, as it includes a lot more padding. | 194 // the rt signal frame, as it includes a lot more padding. |
| 195 "sub $0x1C4, %esp\n" // a legacy signal stack is much larger | 195 "sub $0x1C4, %esp\n" // a legacy signal stack is much larger |
| 196 "mov 0x1CC(%esp), %eax\n" // push signal number | 196 "mov 0x1CC(%esp), %eax\n" // push signal number |
| 197 "push %eax\n" | 197 "push %eax\n" |
| 198 "lea 0x270(%esp), %esi\n" // copy siginfo register values | 198 "lea 0x270(%esp), %esi\n" // copy siginfo register values |
| 199 "lea 0x4(%esp), %edi\n" // into new location | 199 "lea 0x4(%esp), %edi\n" // into new location |
| 200 "mov $0x16, %ecx\n" | 200 "mov $0x16, %ecx\n" |
| 201 "cld\n" | 201 "cld\n" |
| 202 "rep movsl\n" | 202 "rep movsl\n" |
| 203 "mov 0x2C8(%esp), %ebx\n" // copy first half of signal mask | 203 "mov 0x2C8(%esp), %ebx\n" // copy first half of signal mask |
| 204 "mov %ebx, 0x54(%esp)\n" | 204 "mov %ebx, 0x54(%esp)\n" |
| 205 "lea 2f, %esi\n" | 205 "call 2f\n" |
| 206 "2:pop %esi\n" |
| 207 "add $(3f-2b), %esi\n" |
| 206 "push %esi\n" // push restorer function | 208 "push %esi\n" // push restorer function |
| 207 "lea 0x2D4(%esp), %edi\n" // patch up retcode magic numbers | 209 "lea 0x2D4(%esp), %edi\n" // patch up retcode magic numbers |
| 208 "movb $2, %cl\n" | 210 "movb $2, %cl\n" |
| 209 "rep movsl\n" | 211 "rep movsl\n" |
| 210 "ret\n" // return to restorer function | 212 "ret\n" // return to restorer function |
| 211 "2:pop %eax\n" // remove dummy argument (signo) | 213 "3:pop %eax\n" // remove dummy argument (signo) |
| 212 "mov $119, %eax\n" // NR_sigaction | 214 "mov $119, %eax\n" // NR_sigaction |
| 213 "int $0x80\n" | 215 "int $0x80\n" |
| 214 | 216 |
| 215 | 217 |
| 216 // Preserve all registers | 218 // Preserve all registers |
| 217 "3:push %ebp\n" | 219 "4:push %ebp\n" |
| 218 "push $0xDEADBEEF\n" // marker used by breakpad | 220 "push $0xDEADBEEF\n" // marker used by breakpad |
| 219 "push %ebx\n" | 221 "push %ebx\n" |
| 220 "push %ecx\n" | 222 "push %ecx\n" |
| 221 "push %edx\n" | 223 "push %edx\n" |
| 222 "push %esi\n" | 224 "push %esi\n" |
| 223 "push %edi\n" | 225 "push %edi\n" |
| 224 | 226 |
| 225 // Align stack pointer, so that called functions can push SSE registers | 227 // Align stack pointer, so that called functions can push SSE registers |
| 226 // onto stack. This apparently is a requirement of the x86-32 ABI. | 228 // onto stack. This apparently is a requirement of the x86-32 ABI. |
| 227 "mov %esp, %ebp\n" | 229 "mov %esp, %ebp\n" |
| 228 "and $-16, %esp\n" | 230 "and $-16, %esp\n" |
| 229 "sub $4, %esp\n" | 231 "sub $4, %esp\n" |
| 230 "push %ebp\n" // push old un-aligned stack pointer | 232 "push %ebp\n" // push old un-aligned stack pointer |
| 231 "lea 0x14(%ebp), %ebp\n" // frame pointer points to 0xDEADBEEF | 233 "lea 0x14(%ebp), %ebp\n" // frame pointer points to 0xDEADBEEF |
| 232 "push %eax\n" | 234 "push %eax\n" |
| 233 "mov 4(%ebp), %eax\n" // push original value of %ebp | 235 "mov 4(%ebp), %eax\n" // push original value of %ebp |
| 234 "xchg %eax, 0(%esp)\n" | 236 "xchg %eax, 0(%esp)\n" |
| 235 | 237 |
| 236 // Convert from syscall calling conventions to C calling conventions | 238 // Convert from syscall calling conventions to C calling conventions |
| 237 "push %edi\n" | 239 "push %edi\n" |
| 238 "push %esi\n" | 240 "push %esi\n" |
| 239 "push %edx\n" | 241 "push %edx\n" |
| 240 "push %ecx\n" | 242 "push %ecx\n" |
| 241 "push %ebx\n" | 243 "push %ebx\n" |
| 242 "push %eax\n" | 244 "push %eax\n" |
| 243 | 245 |
| 244 // Check range of system call | 246 // Check range of system call |
| 245 "cmp playground$maxSyscall, %eax\n" | 247 "call 5f\n" |
| 246 "ja 9f\n" | 248 "5:pop %edx\n" |
| 249 "add $(_GLOBAL_OFFSET_TABLE_+(.-5b)), %edx\n" |
| 250 "mov playground$maxSyscall@GOT(%edx), %edx\n" |
| 251 "cmp 0(%edx), %eax\n" |
| 252 "ja 14f\n" |
| 247 | 253 |
| 248 // We often have long sequences of calls to gettimeofday(). This is | 254 // We often have long sequences of calls to gettimeofday(). This is |
| 249 // needlessly expensive. Coalesce them into a single call. | 255 // needlessly expensive. Coalesce them into a single call. |
| 250 // | 256 // |
| 251 // We keep track of state in TLS storage that we can access through | 257 // We keep track of state in TLS storage that we can access through |
| 252 // the %fs segment register. See trusted_thread.cc for the exact | 258 // the %fs segment register. See trusted_thread.cc for the exact |
| 253 // memory layout. | 259 // memory layout. |
| 254 // | 260 // |
| 255 // TODO(markus): maybe, we should proactively call gettimeofday() and | 261 // TODO(markus): maybe, we should proactively call gettimeofday() and |
| 256 // clock_gettime(), whenever we talk to the trusted thread? | 262 // clock_gettime(), whenever we talk to the trusted thread? |
| 257 // or maybe, if we have recently seen requests to compute | 263 // or maybe, if we have recently seen requests to compute |
| 258 // the time. There might be a repeated pattern of those. | 264 // the time. There might be a repeated pattern of those. |
| 259 "cmp $78, %eax\n" // __NR_gettimeofday | 265 "cmp $78, %eax\n" // __NR_gettimeofday |
| 260 "jnz 6f\n" | 266 "jnz 10f\n" |
| 261 "cmp %eax, %fs:0x102C-0x58\n" // last system call | 267 "cmp %eax, %fs:0x102C-0x58\n" // last system call |
| 262 "jnz 4f\n" | 268 "jnz 7f\n" |
| 263 | 269 |
| 264 // This system call and the last system call prior to this one both are | 270 // This system call and the last system call prior to this one both are |
| 265 // calls to gettimeofday(). Try to avoid making the new call and just | 271 // calls to gettimeofday(). Try to avoid making the new call and just |
| 266 // return the same result as in the previous call. | 272 // return the same result as in the previous call. |
| 267 // Just in case the caller is spinning on the result from gettimeofday(), | 273 // Just in case the caller is spinning on the result from gettimeofday(), |
| 268 // every so often, call the actual system call. | 274 // every so often, call the actual system call. |
| 269 "decl %fs:0x1030-0x58\n" // countdown calls to gettimofday() | 275 "decl %fs:0x1030-0x58\n" // countdown calls to gettimofday() |
| 270 "jz 4f\n" | 276 "jz 7f\n" |
| 271 | 277 |
| 272 // Atomically read the 64bit word representing last-known timestamp and | 278 // Atomically read the 64bit word representing last-known timestamp and |
| 273 // return it to the caller. On x86-32 this is a little more complicated and | 279 // return it to the caller. On x86-32 this is a little more complicated and |
| 274 // requires the use of the cmpxchg8b instruction. | 280 // requires the use of the cmpxchg8b instruction. |
| 275 "mov %ebx, %eax\n" | 281 "mov %ebx, %eax\n" |
| 276 "mov %ecx, %edx\n" | 282 "mov %ecx, %edx\n" |
| 277 "lock; cmpxchg8b 100f\n" | 283 "call 6f\n" |
| 284 "6:pop %ebp\n" |
| 285 "add $(100f-6b), %ebp\n" |
| 286 "lock; cmpxchg8b 0(%ebp)\n" |
| 278 "mov %eax, 0(%ebx)\n" | 287 "mov %eax, 0(%ebx)\n" |
| 279 "mov %edx, 4(%ebx)\n" | 288 "mov %edx, 4(%ebx)\n" |
| 280 "xor %eax, %eax\n" | 289 "xor %eax, %eax\n" |
| 281 "add $28, %esp\n" | 290 "add $28, %esp\n" |
| 282 "jmp 8f\n" | 291 "jmp 13f\n" |
| 283 | 292 |
| 284 // This is a call to gettimeofday(), but we don't have a valid cached | 293 // This is a call to gettimeofday(), but we don't have a valid cached |
| 285 // result, yet. | 294 // result, yet. |
| 286 "4:mov %eax, %fs:0x102C-0x58\n" // remember syscall number | 295 "7:mov %eax, %fs:0x102C-0x58\n" // remember syscall number |
| 287 "movl $500, %fs:0x1030-0x58\n" // make system call, each 500 invocations | 296 "movl $500, %fs:0x1030-0x58\n" // make system call, each 500 invocations |
| 288 "call playground$defaultSystemCallHandler\n" | 297 "call playground$defaultSystemCallHandler@PLT\n" |
| 289 | 298 |
| 290 // Returned from gettimeofday(). Remember return value, in case the | 299 // Returned from gettimeofday(). Remember return value, in case the |
| 291 // application calls us again right away. | 300 // application calls us again right away. |
| 292 // Again, this has to happen atomically and requires cmpxchg8b. | 301 // Again, this has to happen atomically and requires cmpxchg8b. |
| 293 "mov 4(%ebx), %ecx\n" | 302 "mov 4(%ebx), %ecx\n" |
| 294 "mov 0(%ebx), %ebx\n" | 303 "mov 0(%ebx), %ebx\n" |
| 295 "mov 100f, %eax\n" | 304 "call 8f\n" |
| 296 "mov 101f, %edx\n" | 305 "8:pop %ebp\n" |
| 297 "5:lock; cmpxchg8b 100f\n" | 306 "add $(100f-8b), %ebp\n" |
| 298 "jnz 5b\n" | 307 "mov 0(%ebp), %eax\n" |
| 308 "mov 4(%ebp), %edx\n" |
| 309 "9:lock; cmpxchg8b 0(%ebp)\n" |
| 310 "jnz 9b\n" |
| 299 "xor %eax, %eax\n" | 311 "xor %eax, %eax\n" |
| 300 "jmp 10f\n" | 312 "jmp 15f\n" |
| 301 | 313 |
| 302 // Remember the number of the last system call made. We deliberately do | 314 // Remember the number of the last system call made. We deliberately do |
| 303 // not remember calls to gettid(), as we have often seen long sequences | 315 // not remember calls to gettid(), as we have often seen long sequences |
| 304 // of calls to just gettimeofday() and gettid(). In that situation, we | 316 // of calls to just gettimeofday() and gettid(). In that situation, we |
| 305 // would still like to coalesce the gettimeofday() calls. | 317 // would still like to coalesce the gettimeofday() calls. |
| 306 "6:cmp $224, %eax\n" // __NR_gettid | 318 "10:cmp $224, %eax\n" // __NR_gettid |
| 307 "jz 7f\n" | 319 "jz 11f\n" |
| 308 "mov %eax, %fs:0x102C-0x58\n" // remember syscall number | 320 "mov %eax, %fs:0x102C-0x58\n" // remember syscall number |
| 309 | 321 |
| 310 // Retrieve function call from system call table (c.f.system_call_table.cc) | 322 // Retrieve function call from system call table (c.f.system_call_table.cc) |
| 311 // We have three different types of entries; zero for denied system calls, | 323 // We have three different types of entries; zero for denied system calls, |
| 312 // that should be handled by the defaultSystemCallHandler(); minus one | 324 // that should be handled by the defaultSystemCallHandler(); minus one |
| 313 // for unrestricted system calls that need to be forwarded to the trusted | 325 // for unrestricted system calls that need to be forwarded to the trusted |
| 314 // thread; and function pointers to specific handler functions. | 326 // thread; and function pointers to specific handler functions. |
| 315 "7:shl $3, %eax\n" | 327 "11:shl $3, %eax\n" |
| 316 "mov playground$syscallTable, %ebx\n" | 328 "call 12f\n" |
| 317 "add %ebx, %eax\n" | 329 "12:pop %ebx\n" |
| 330 "add $(_GLOBAL_OFFSET_TABLE_+(.-12b)), %ebx\n" |
| 331 "mov playground$syscallTable@GOT(%ebx), %ebx\n" |
| 332 "add 0(%ebx), %eax\n" |
| 318 "mov 0(%eax), %eax\n" | 333 "mov 0(%eax), %eax\n" |
| 319 | 334 |
| 320 // Jump to function if non-null and not UNRESTRICTED_SYSCALL, otherwise | 335 // Jump to function if non-null and not UNRESTRICTED_SYSCALL, otherwise |
| 321 // jump to fallback handler. | 336 // jump to fallback handler. |
| 322 "cmp $1, %eax\n" | 337 "cmp $1, %eax\n" |
| 323 "jbe 9f\n" | 338 "jbe 14f\n" |
| 324 "add $4, %esp\n" | 339 "add $4, %esp\n" |
| 325 "call *%eax\n" | 340 "call *%eax\n" |
| 326 "add $24, %esp\n" | 341 "add $24, %esp\n" |
| 327 | 342 |
| 328 // Restore CPU registers, except for %eax which was set by the system call. | 343 // Restore CPU registers, except for %eax which was set by the system call. |
| 329 "8:pop %esp\n" | 344 "13:pop %esp\n" |
| 330 "pop %edi\n" | 345 "pop %edi\n" |
| 331 "pop %esi\n" | 346 "pop %esi\n" |
| 332 "pop %edx\n" | 347 "pop %edx\n" |
| 333 "pop %ecx\n" | 348 "pop %ecx\n" |
| 334 "pop %ebx\n" | 349 "pop %ebx\n" |
| 335 "pop %ebp\n" // 0xDEADBEEF marker | 350 "pop %ebp\n" // 0xDEADBEEF marker |
| 336 "pop %ebp\n" | 351 "pop %ebp\n" |
| 337 | 352 |
| 338 // Remove fake return address. This is added in the patching code in | 353 // Remove fake return address. This is added in the patching code in |
| 339 // library.cc and it makes stack traces a little cleaner. | 354 // library.cc and it makes stack traces a little cleaner. |
| 340 "add $4, %esp\n" | 355 "add $4, %esp\n" |
| 341 | 356 |
| 342 // Return to caller | 357 // Return to caller |
| 343 "ret\n" | 358 "ret\n" |
| 344 | 359 |
| 345 // Call default handler. | 360 // Call default handler. |
| 346 "9:call playground$defaultSystemCallHandler\n" | 361 "14:call playground$defaultSystemCallHandler@PLT\n" |
| 347 "10:add $28, %esp\n" | 362 "15:add $28, %esp\n" |
| 348 "jmp 8b\n" | 363 "jmp 13b\n" |
| 349 | 364 |
| 350 ".pushsection \".bss\"\n" | 365 ".pushsection \".bss\"\n" |
| 351 ".balign 8\n" | 366 ".balign 8\n" |
| 352 "100:.byte 0, 0, 0, 0\n" | 367 "100:.byte 0, 0, 0, 0, 0, 0, 0, 0\n" |
| 353 "101:.byte 0, 0, 0, 0\n" | |
| 354 ".popsection\n" | 368 ".popsection\n" |
| 355 | 369 |
| 356 #else | 370 #else |
| 357 #error Unsupported target platform | 371 #error Unsupported target platform |
| 358 #endif | 372 #endif |
| 359 ".size playground$syscallEntryPointWithFrame," | 373 ".size playground$syscallEntryPointWithFrame," |
| 360 ".-playground$syscallEntryPointWithFrame\n" | 374 ".-playground$syscallEntryPointWithFrame\n" |
| 361 ".popsection\n" | 375 ".popsection\n" |
| 362 ); | 376 ); |
| 363 | 377 |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 417 } | 431 } |
| 418 } | 432 } |
| 419 if (rc < 0) { | 433 if (rc < 0) { |
| 420 rc = -sys.my_errno; | 434 rc = -sys.my_errno; |
| 421 } | 435 } |
| 422 Debug::elapsed(tm, syscallNum); | 436 Debug::elapsed(tm, syscallNum); |
| 423 return (void *)rc; | 437 return (void *)rc; |
| 424 } | 438 } |
| 425 | 439 |
| 426 } // namespace | 440 } // namespace |
| OLD | NEW |