Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1412)

Unified Diff: sandbox/linux/seccomp/sandbox.cc

Issue 1739011: Added support for sigreturn() and rt_sigreturn(). On x86-32, this is... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 10 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « sandbox/linux/seccomp/library.cc ('k') | sandbox/linux/seccomp/sandbox_impl.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: sandbox/linux/seccomp/sandbox.cc
===================================================================
--- sandbox/linux/seccomp/sandbox.cc (revision 45661)
+++ sandbox/linux/seccomp/sandbox.cc (working copy)
@@ -121,7 +121,8 @@
// Set up SEGV handler for dealing with RDTSC instructions, system calls
// that have been rewritten to use INT0, and for sigpending() emulation.
- sa.sa_handler_ = segv();
+ sa.sa_sigaction_ = segv();
+ sa.sa_flags = SA_SIGINFO;
sys.sigaction(SIGSEGV, &sa, NULL);
// Unblock SIGSEGV and SIGCHLD
@@ -131,8 +132,8 @@
sys.sigprocmask(SIG_UNBLOCK, &mask, 0);
}
-void (*Sandbox::segv())(int signo) {
- void (*fnc)(int signo);
+void (*Sandbox::segv())(int signo, SysCalls::siginfo *context, void *unused) {
+ void (*fnc)(int signo, SysCalls::siginfo *context, void *unused);
asm volatile(
"call 999f\n"
#if defined(__x86_64__)
@@ -198,7 +199,7 @@
// rewrite the system call instruction. Retrieve the CPU register
// at the time of the segmentation fault and invoke syscallWrapper().
"8:cmpw $0x00CD, (%%r15)\n" // INT $0x0
- "jnz 14f\n"
+ "jnz 16f\n"
#ifndef NDEBUG
"lea 200f(%%rip), %%rdi\n"
"call playground$debugMessage\n"
@@ -239,10 +240,18 @@
"mov %%r10, 0(%%rdx)\n" // old_set
"jmp 7b\n"
+ // Handle rt_sigreturn()
+ "12:cmp $15, %%rax\n" // NR_rt_sigreturn
+ "jnz 14f\n"
+ "mov 0xA8(%%rsp), %%rsp\n" // %rsp at time of segmentation fault
+ "13:syscall\n" // rt_sigreturn() is unrestricted
+ "mov $66, %%edi\n" // rt_sigreturn() should never return
+ "mov $231, %%eax\n" // NR_exit_group
+ "jmp 13b\n"
// Copy signal frame onto new stack. See clone.cc for details
- "12:cmp $56+0xF000, %%rax\n" // NR_clone + 0xF000
- "jnz 13f\n"
+ "14:cmp $56+0xF000, %%rax\n" // NR_clone + 0xF000
+ "jnz 15f\n"
"mov 0xA8(%%rsp), %%rcx\n" // %rsp at time of segmentation fault
"sub %%rsp, %%rcx\n" // %rcx = size of stack frame
"sub $8, %%rcx\n" // skip return address
@@ -256,7 +265,7 @@
"jmp 7b\n"
// Forward system call to syscallWrapper()
- "13:lea 7b(%%rip), %%rcx\n"
+ "15:lea 7b(%%rip), %%rcx\n"
"push %%rcx\n"
"push 0xB8(%%rsp)\n" // %rip at time of segmentation fault
"lea playground$syscallWrapper(%%rip), %%rcx\n"
@@ -265,7 +274,7 @@
// This was a genuine segmentation fault. Trigger the kernel's default
// signal disposition. The only way we can do this from seccomp mode
// is by blocking the signal and retriggering it.
- "14:mov $2, %%edi\n" // stderr
+ "16:mov $2, %%edi\n" // stderr
"lea 300f(%%rip), %%rsi\n" // "Segmentation fault\n"
"mov $301f-300f, %%edx\n"
"mov $1, %%eax\n" // NR_write
@@ -277,13 +286,13 @@
// happened. If it is RDTSC, forward the request to the trusted
// thread.
"mov $-3, %%ebx\n" // request for RDTSC
- "mov 0x40(%%esp), %%ebp\n" // %eip at time of segmentation fault
+ "mov 0xDC(%%esp), %%ebp\n" // %eip at time of segmentation fault
"cmpw $0x310F, (%%ebp)\n" // RDTSC
"jz 0f\n"
- "cmpw $0x010F, (%%ebp)\n"
- "jnz 8f\n"
+ "cmpw $0x010F, (%%ebp)\n" // RDTSCP
+ "jnz 9f\n"
"cmpb $0xF9, 2(%%ebp)\n"
- "jnz 8f\n"
+ "jnz 9f\n"
"mov $-4, %%ebx\n" // request for RDTSCP
"0:"
#ifndef NDEBUG
@@ -292,7 +301,7 @@
"call playground$debugMessage\n"
"sub $4, %%esp\n"
#else
- "sub $8, %%esp\n"
+ "sub $8, %%esp\n" // allocate buffer for receiving timestamp
#endif
"push %%ebx\n"
"mov %%fs:16, %%ebx\n" // fd = threadFdPub
@@ -301,126 +310,178 @@
"1:mov %%edx, %%eax\n" // NR_write
"int $0x80\n"
"cmp %%eax, %%edx\n"
- "jz 5f\n"
+ "jz 7f\n"
"cmp $-4, %%eax\n" // EINTR
"jz 1b\n"
- "2:add $12, %%esp\n"
- "movl $0, 0x34(%%esp)\n" // %eax at time of segmentation fault
- "movl $0, 0x2C(%%esp)\n" // %edx at time of segmentation fault
+ "2:add $12, %%esp\n" // remove temporary buffer from stack
+ "xor %%eax, %%eax\n"
+ "movl $0, 0xC8(%%esp)\n" // %edx at time of segmentation fault
"cmpw $0x310F, (%%ebp)\n" // RDTSC
"jz 3f\n"
- "movl $0, 0x30(%%esp)\n" // %ecx at time of segmentation fault
- "3:addl $2, 0x40(%%esp)\n" // %eip at time of segmentation fault
- "mov 0x40(%%esp), %%ebp\n" // %eip at time of segmentation fault
- "cmpw $0x010F, (%%ebp)\n" // RDTSC
- "jnz 4f\n"
- "addl $1, 0x40(%%esp)\n" // %eip at time of segmentation fault
- "4:ret\n"
- "5:mov $12, %%edx\n" // len = 3*sizeof(int)
- "6:mov $3, %%eax\n" // NR_read
+ "movl $0, 0xCC(%%esp)\n" // %ecx at time of segmentation fault
+ "3:mov %%eax, 0xD0(%%esp)\n" // %eax at time of segmentation fault
+ "4:mov 0xDC(%%esp), %%ebp\n" // %eip at time of segmentation fault
+ "addl $2, 0xDC(%%esp)\n" // %eip at time of segmentation fault
+ "cmpw $0x010F, (%%ebp)\n" // RDTSCP
+ "jnz 5f\n"
+ "addl $1, 0xDC(%%esp)\n" // %eip at time of segmentation fault
+ "5:sub $0x1C8, %%esp\n" // a legacy signal stack is much larger
+ "mov 0x1CC(%%esp), %%eax\n" // push signal number
+ "push %%eax\n"
+ "lea 0x270(%%esp), %%esi\n" // copy siginfo register values
+ "lea 0x4(%%esp), %%edi\n" // into new location
+ "mov $22, %%ecx\n"
+ "cld\n"
+ "rep movsl\n"
+ "mov 0x2C8(%%esp), %%ebx\n" // copy first half of signal mask
+ "mov %%ebx, 0x54(%%esp)\n"
+ "lea 6f, %%esi\n" // copy "magic" restorer function
+ "push %%esi\n" // push restorer function
+ "lea 0x2D4(%%esp), %%edi\n" // patch up retcode magic numbers
+ "movb $2, %%cl\n"
+ "rep movsl\n"
+ "ret\n" // return to restorer function
+
+ // The restorer function is sometimes used by gdb as a magic marker to
+ // recognize signal stack frames. Don't change any of the next three
+ // instructions.
+ "6:pop %%eax\n" // remove dummy argument (signo)
+ "mov $119, %%eax\n" // NR_sigreturn
"int $0x80\n"
+ "7:mov $12, %%edx\n" // len = 3*sizeof(int)
+ "8:mov $3, %%eax\n" // NR_read
+ "int $0x80\n"
"cmp $-4, %%eax\n" // EINTR
- "jz 6b\n"
+ "jz 8b\n"
"cmp %%eax, %%edx\n"
"jnz 2b\n"
"pop %%eax\n"
"pop %%edx\n"
"pop %%ecx\n"
- "mov %%edx, 0x2C(%%esp)\n" // %edx at time of segmentation fault
+ "mov %%edx, 0xC8(%%esp)\n" // %edx at time of segmentation fault
"cmpw $0x310F, (%%ebp)\n" // RDTSC
- "jz 7f\n"
- "mov %%ecx, 0x30(%%esp)\n" // %ecx at time of segmentation fault
- "7:mov %%eax, 0x34(%%esp)\n" // %eax at time of segmentation fault
+ "jz 3b\n"
+ "mov %%ecx, 0xCC(%%esp)\n" // %ecx at time of segmentation fault
"jmp 3b\n"
// If the instruction is INT 0, then this was probably the result
// of playground::Library being unable to find a way to safely
// rewrite the system call instruction. Retrieve the CPU register
// at the time of the segmentation fault and invoke syscallWrapper().
- "8:cmpw $0x00CD, (%%ebp)\n" // INT $0x0
- "jnz 16f\n"
+ "9:cmpw $0x00CD, (%%ebp)\n" // INT $0x0
+ "jnz 20f\n"
#ifndef NDEBUG
"lea 200f, %%eax\n"
"push %%eax\n"
"call playground$debugMessage\n"
"add $0x4, %%esp\n"
#endif
- "mov 0x34(%%esp), %%eax\n" // %eax at time of segmentation fault
- "mov 0x28(%%esp), %%ebx\n" // %ebx at time of segmentation fault
- "mov 0x30(%%esp), %%ecx\n" // %ecx at time of segmentation fault
- "mov 0x2C(%%esp), %%edx\n" // %edx at time of segmentation fault
- "mov 0x1C(%%esp), %%esi\n" // %esi at time of segmentation fault
- "mov 0x18(%%esp), %%edi\n" // %edi at time of segmentation fault
- "mov 0x20(%%esp), %%ebp\n" // %ebp at time of segmentation fault
+ "mov 0xD0(%%esp), %%eax\n" // %eax at time of segmentation fault
+ "mov 0xC4(%%esp), %%ebx\n" // %ebx at time of segmentation fault
+ "mov 0xCC(%%esp), %%ecx\n" // %ecx at time of segmentation fault
+ "mov 0xC8(%%esp), %%edx\n" // %edx at time of segmentation fault
+ "mov 0xB8(%%esp), %%esi\n" // %esi at time of segmentation fault
+ "mov 0xB4(%%esp), %%edi\n" // %edi at time of segmentation fault
+ "mov 0xB2(%%esp), %%ebp\n" // %ebp at time of segmentation fault
// Handle sigprocmask() and rt_sigprocmask()
"cmp $175, %%eax\n" // NR_rt_sigprocmask
- "jnz 9f\n"
+ "jnz 10f\n"
"mov $-22, %%eax\n" // -EINVAL
"cmp $8, %%esi\n" // %esi = sigsetsize (8 bytes = 64 signals)
- "jl 7b\n"
- "jmp 10f\n"
- "9:cmp $126, %%eax\n" // NR_sigprocmask
- "jnz 14f\n"
+ "jl 3b\n"
+ "jmp 11f\n"
+ "10:cmp $126, %%eax\n" // NR_sigprocmask
+ "jnz 15f\n"
"mov $-22, %%eax\n"
- "10:mov 0x58(%%esp), %%edi\n" // signal mask at time of segmentation fault
- "mov 0x5C(%%esp), %%ebp\n"
+ "11:mov 0xFC(%%esp), %%edi\n" // signal mask at time of segmentation fault
+ "mov 0x100(%%esp), %%ebp\n"
"test %%ecx, %%ecx\n" // only set mask, if set is non-NULL
- "jz 13f\n"
+ "jz 14f\n"
"mov 0(%%ecx), %%esi\n"
"mov 4(%%ecx), %%ecx\n"
"cmp $0, %%ebx\n" // %ebx = how (SIG_BLOCK)
- "jnz 11f\n"
- "or %%esi, 0x58(%%esp)\n" // signal mask at time of segmentation fault
- "or %%ecx, 0x5C(%%esp)\n"
- "jmp 13f\n"
- "11:cmp $1, %%ebx\n" // %ebx = how (SIG_UNBLOCK)
"jnz 12f\n"
+ "or %%esi, 0xFC(%%esp)\n" // signal mask at time of segmentation fault
+ "or %%ecx, 0x100(%%esp)\n"
+ "jmp 14f\n"
+ "12:cmp $1, %%ebx\n" // %ebx = how (SIG_UNBLOCK)
+ "jnz 13f\n"
"xor $-1, %%esi\n"
"xor $-1, %%ecx\n"
- "and %%esi, 0x58(%%esp)\n" // signal mask at time of segmentation fault
- "and %%ecx, 0x5C(%%esp)\n"
- "jmp 13f\n"
- "12:cmp $2, %%ebx\n" // %ebx = how (SIG_SETMASK)
- "jnz 7b\n"
- "mov %%esi, 0x58(%%esp)\n" // signal mask at time of segmentation fault
- "mov %%ecx, 0x5C(%%esp)\n"
- "13:xor %%eax, %%eax\n"
+ "and %%esi, 0xFC(%%esp)\n" // signal mask at time of segmentation fault
+ "and %%ecx, 0x100(%%esp)\n"
+ "jmp 14f\n"
+ "13:cmp $2, %%ebx\n" // %ebx = how (SIG_SETMASK)
+ "jnz 3b\n"
+ "mov %%esi, 0xFC(%%esp)\n" // signal mask at time of segmentation fault
+ "mov %%ecx, 0x100(%%esp)\n"
+ "14:xor %%eax, %%eax\n"
"test %%edx, %%edx\n" // only return old mask, if set is non-NULL
- "jz 7b\n"
+ "jz 3b\n"
"mov %%edi, 0(%%edx)\n" // old_set
"mov %%ebp, 4(%%edx)\n"
- "jmp 7b\n"
+ "jmp 3b\n"
- // Copy signal frame onto new stack. See clone.cc for details
- "14:cmp $120+0xF000, %%eax\n" // NR_clone + 0xF000
- "jnz 15f\n"
- "mov 0x24(%%esp), %%ecx\n" // %esp at time of segmentation fault
- "sub %%esp, %%ecx\n" // %ecx = size of stack frame
- "sub $8, %%ecx\n" // skip return address and dummy
- "mov %%ecx, %%eax\n" // return size of signal stack frame
+ // Handle sigreturn() and rt_sigreturn()
+ // See syscall.cc for a discussion on how we can emulate rt_sigreturn()
+ // by calling sigreturn() with a suitably adjusted stack.
+ "15:cmp $119, %%eax\n" // NR_sigreturn
+ "jnz 17f\n"
+ "mov 0xC0(%%esp), %%esp\n" // %esp at time of segmentation fault
+ "16:int $0x80\n" // sigreturn() is unrestricted
+ "17:cmp $173, %%eax\n" // NR_rt_sigreturn
+ "jnz 18f\n"
+ "mov 0xC0(%%esp), %%esp\n" // %esp at time of segmentation fault
+ "sub $4, %%esp\n" // add fake return address
+ "jmp 4b\n"
+
+ // Copy signal frame onto new stack. In the process, we have to convert
+ // it from an RT signal frame to a legacy signal frame.
+ // See clone.cc for details
+ "18:cmp $120+0xF000, %%eax\n" // NR_clone + 0xF000
+ "jnz 19f\n"
+ "mov 0xC0(%%esp), %%ecx\n" // %esp at time of segmentation fault
+ "sub %%esp, %%ecx\n" // %ecx = size of RT stack frame
+ "mov %%ecx, %%eax\n"
+ "add $0x1C8, %%eax\n" // adjust for size of legacy stack frame
+ "sub $0x100, %%ecx\n"
"mov 0(%%edx), %%edi\n" // stack for newly clone()'d thread
"sub %%ecx, %%edi\n" // copy onto new stack
+ "lea 0x100(%%esp), %%esi\n"
+ "cld\n"
+ "rep movsb\n" // copy parts of RT stack(sigmask, FP state)
+ "mov 0xF0(%%esp), %%ebx\n" // adjust pointer to fpstate
+ "sub %%esi, %%ebx\n"
+ "add %%edi, %%ebx\n"
+ "sub %%eax, %%edi\n"
"mov %%edi, 0(%%edx)\n" // allocate space on new stack
- "lea 8(%%esp), %%esi\n" // copy from current stack
- "cld\n"
- "rep movsb\n"
- "jmp 7b\n"
+ "lea 0xA4(%%esp), %%esi\n" // copy sigcontext from current stack
+ "mov $0x16, %%ecx\n"
+ "rep movsl\n"
+ "mov %%ebx, -0xC(%%edi)\n" // set pointer to fpstate
+ "mov 0xFC(%%esp), %%ebx\n" // copy first half of signal mask
+ "mov %%ebx, -0x8(%%edi)\n"
+ "mov %%eax, -0x2C(%%edi)\n" // return size of stack frame in %%eax
+ "addl $2, -0x20(%%edi)\n" // adjust %eip
+ "mov 0(%%edx), %%esp\n"
+ "mov $119, %%eax\n" // NR_sigreturn
+ "int $0x80\n"
// Forward system call to syscallWrapper()
- "15:call playground$syscallWrapper\n"
- "jmp 7b\n"
+ "19:call playground$syscallWrapper\n"
+ "jmp 3b\n"
// This was a genuine segmentation fault. Trigger the kernel's default
// signal disposition. The only way we can do this from seccomp mode
// is by blocking the signal and retriggering it.
- "16:mov $2, %%ebx\n" // stderr
+ "20:mov $2, %%ebx\n" // stderr
"lea 300f, %%ecx\n" // "Segmentation fault\n"
"mov $301f-300f, %%edx\n"
"mov $4, %%eax\n" // NR_write
"int $0x80\n"
- "orb $4, 0x59(%%esp)\n" // signal mask at time of segmentation fault
- "ret\n"
+ "orb $4, 0xFD(%%esp)\n" // signal mask at time of segmentation fault
+ "jmp 4b\n"
#else
#error Unsupported target platform
#endif
« no previous file with comments | « sandbox/linux/seccomp/library.cc ('k') | sandbox/linux/seccomp/sandbox_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698