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

Unified Diff: sandbox.cc

Issue 4688002: On older 32bit kernels (e.g. Ubuntu Hardy), the seccomp sandbox fails to hand... (Closed) Base URL: http://seccompsandbox.googlecode.com/svn/trunk/
Patch Set: Created 10 years, 1 month 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 | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: sandbox.cc
===================================================================
--- sandbox.cc (revision 145)
+++ sandbox.cc (working copy)
@@ -355,9 +355,9 @@
"cmpw $0x310F, (%%ebp)\n" // RDTSC
"jz 0f\n"
"cmpw $0x010F, (%%ebp)\n" // RDTSCP
- "jnz 9f\n"
+ "jnz 10f\n"
"cmpb $0xF9, 2(%%ebp)\n"
- "jnz 9f\n"
+ "jnz 10f\n"
"mov $-4, %%ebx\n" // request for RDTSCP
"0:"
#ifndef NDEBUG
@@ -375,7 +375,7 @@
"1:mov %%edx, %%eax\n" // NR_write
"int $0x80\n"
"cmp %%eax, %%edx\n"
- "jz 7f\n"
+ "jz 8f\n"
"cmp $-4, %%eax\n" // EINTR
"jz 1b\n"
"2:add $12, %%esp\n" // remove temporary buffer from stack
@@ -390,7 +390,8 @@
"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
+ "5:add $0x4, %%esp\n"
+ "6:sub $0x1CC, %%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
@@ -400,24 +401,14 @@
"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)
+ "7: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
+ "8:mov $12, %%edx\n" // len = 3*sizeof(int)
+ "9:mov $3, %%eax\n" // NR_read
"int $0x80\n"
"cmp $-4, %%eax\n" // EINTR
- "jz 8b\n"
+ "jz 9b\n"
"cmp %%eax, %%edx\n"
"jnz 2b\n"
"pop %%eax\n"
@@ -434,7 +425,7 @@
// rewrite the system call instruction. Retrieve the CPU register
// at the time of the segmentation fault and invoke
// syscallEntryPointWithFrame().
- "9:cmpw $0x00CD, (%%ebp)\n" // INT $0x0
+ "10:cmpw $0x00CD, (%%ebp)\n" // INT $0x0
"jnz 20f\n"
#ifndef NDEBUG
"lea 200f, %%eax\n"
@@ -452,37 +443,37 @@
// Handle sigprocmask() and rt_sigprocmask()
"cmp $175, %%eax\n" // NR_rt_sigprocmask
- "jnz 10f\n"
+ "jnz 11f\n"
"mov $-22, %%eax\n" // -EINVAL
"cmp $8, %%esi\n" // %esi = sigsetsize (8 bytes = 64 signals)
"jl 3b\n"
- "jmp 11f\n"
- "10:cmp $126, %%eax\n" // NR_sigprocmask
- "jnz 15f\n"
+ "jmp 12f\n"
+ "11:cmp $126, %%eax\n" // NR_sigprocmask
+ "jnz 16f\n"
"mov $-22, %%eax\n"
- "11:mov 0xFC(%%esp), %%edi\n" // signal mask at time of segmentation fault
+ "12: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 14f\n"
+ "jz 15f\n"
"mov 0(%%ecx), %%esi\n"
"mov 4(%%ecx), %%ecx\n"
"cmp $0, %%ebx\n" // %ebx = how (SIG_BLOCK)
- "jnz 12f\n"
+ "jnz 13f\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"
+ "jmp 15f\n"
+ "13:cmp $1, %%ebx\n" // %ebx = how (SIG_UNBLOCK)
+ "jnz 14f\n"
"xor $-1, %%esi\n"
"xor $-1, %%ecx\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)
+ "jmp 15f\n"
+ "14: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"
+ "15:xor %%eax, %%eax\n"
"test %%edx, %%edx\n" // only return old mask, if set is non-NULL
"jz 3b\n"
"mov %%edi, 0(%%edx)\n" // old_set
@@ -492,10 +483,10 @@
// 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
+ "16: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
+ "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
@@ -516,45 +507,29 @@
"push 0xE0(%%esp)\n" // %eip at time of segmentation fault
"jmp playground$syscallEntryPointWithFrame\n"
+ // This was a genuine segmentation fault. Check Sandbox::sa_segv_ for
+ // what we are supposed to do.
// In order to implement SA_NODEFER, we have to keep track of recursive
// calls to SIGSEGV handlers. This means we have to increment a counter
// before calling the user's signal handler, and decrement it on
// leaving the user's signal handler.
- // Some signal handlers look at the return address of the signal
- // stack, and more importantly "gdb" uses the call to {,rt_}sigreturn()
- // as a magic signature when doing stacktraces. So, we have to use
- // a little more unusual code to regain control after the user's
- // signal handler is done. We adjust the return address to point to
- // non-executable memory. And when we trigger another SEGV we pop the
- // extraneous signal frame and then call sigreturn().
// N.B. We currently do not correctly adjust the SEGV counter, if the
// user's signal handler exits in way other than by returning (e.g. by
// directly calling {,rt_}sigreturn(), or by calling siglongjmp()).
- "20:lea 30f, %%edi\n" // rt-style restorer function
- "lea 31f, %%esi\n" // legacy restorer function
- "cmp %%ebp, %%edi\n" // check if returning from user's handler
- "jnz 21f\n"
- "decl %%fs:0x1040-0x58\n" // decrement SEGV recursion counter
- "mov 0xC0(%%esp), %%esp\n" // %esp at time of segmentation fault
- "jmp 29f\n"
- "21:cmp %%ebp, %%esi\n" // check if returning from user's handler
- "jnz 22f\n"
- "decl %%fs:0x1040-0x58\n" // decrement SEGV recursion counter
- "mov 0xC0(%%esp), %%esp\n" // %esp at time of segmentation fault
- "jmp 6b\n"
-
- // This was a genuine segmentation fault. Check Sandbox::sa_segv_ for
- // what we are supposed to do.
- "22:lea playground$sa_segv, %%eax\n"
+ // N.B. On i386, we don't have any guarantees that NX protection works.
+ // So, we don't even attempt to fake a correct restorer function. Some
+ // callers might be confused by this and will need fixing for running
+ // inside of the seccomp sandbox.
+ "20:lea playground$sa_segv, %%eax\n"
"cmp $0, 0(%%eax)\n" // SIG_DFL
- "jz 23f\n"
+ "jz 21f\n"
"cmp $1, 0(%%eax)\n" // SIG_IGN
- "jnz 24f\n" // can't really ignore synchronous signals
+ "jnz 22f\n" // can't really ignore synchronous signals
// 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.
- "23:orb $4, 0xFD(%%esp)\n" // signal mask at time of segmentation fault
+ "21:orb $4, 0xFD(%%esp)\n" // signal mask at time of segmentation fault
"jmp 5b\n"
// Check sa_flags:
@@ -568,27 +543,27 @@
//
// TODO(markus): If/when we add support for sigaltstack(), we have to
// handle SA_ONSTACK.
- "24:cmpl $0, %%fs:0x1040-0x58\n"// check if we failed inside of SEGV handler
- "jnz 23b\n" // if so, then terminate program
+ "22:cmpl $0, %%fs:0x1040-0x58\n"// check if we failed inside of SEGV handler
+ "jnz 21b\n" // if so, then terminate program
"mov 0(%%eax), %%ebx\n" // sa_segv_.sa_sigaction
"mov 4(%%eax), %%ecx\n" // sa_segv_.sa_flags
"btl $31, %%ecx\n" // SA_RESETHAND
- "jnc 25f\n"
+ "jnc 23f\n"
"movl $0, 0(%%eax)\n" // set handler to SIG_DFL
- "25:btl $30, %%ecx\n" // SA_NODEFER
- "jc 28f\n"
+ "23:btl $30, %%ecx\n" // SA_NODEFER
+ "jc 26f\n"
"btl $2, %%ecx\n" // SA_SIGINFO
- "jnc 26f\n"
- "mov %%edi, 0(%%esp)\n" // trigger a SEGV on return
+ "jnc 24f\n"
+ "movl $27f, 0(%%esp)\n" // trigger a SEGV on return (if NX enabled)
Mark Seaborn 2010/11/09 09:40:31 I don't understand the "(if NX enabled)" comment.
"incl %%fs:0x1040-0x58\n" // increment recursion counter
"jmp *%%ebx\n" // call user's signal handler
- "26:mov %%esi, 0(%%esp)\n"
+ "24:movl $28f, 0(%%esp)\n"
"incl %%fs:0x1040-0x58\n" // increment recursion counter
// We always register the signal handler to give us rt-style signal
// frames. But if the user asked for legacy signal frames, we must
// convert the signal frame prior to calling the user's signal handler.
- "27:sub $0x1C8, %%esp\n" // a legacy signal stack is much larger
+ "25:sub $0x1C8, %%esp\n" // a legacy signal stack is much larger
"mov 0x1CC(%%esp), %%eax\n" // push signal number
"push %%eax\n"
"mov 0x1CC(%%esp), %%eax\n" // push restorer function
@@ -600,32 +575,16 @@
"rep movsl\n"
"mov 0x2CC(%%esp), %%eax\n" // copy first half of signal mask
"mov %%eax, 0x58(%%esp)\n"
- "lea 31f, %%esi\n"
- "lea 0x2D4(%%esp), %%edi\n" // patch up retcode magic numbers
- "movb $2, %%cl\n"
- "rep movsl\n"
"jmp *%%ebx\n" // call user's signal handler
- "28:lea 6b, %%eax\n" // set appropriate restorer function
- "mov %%eax, 0(%%esp)\n"
+ "26:movl $7b, 0(%%esp)\n" // set appropriate restorer function
"btl $2, %%ecx\n" // SA_SIGINFO
- "jnc 27b\n"
- "lea 29f, %%eax\n"
- "mov %%eax, 0(%%esp)\n" // set appropriate restorer function
+ "jnc 25b\n"
+ "movl $6b, 0(%%esp)\n" // set appropriate restorer function
Mark Seaborn 2010/11/09 09:40:31 Indentation is 1 space off
"jmp *%%ebx\n" // call user's signal handler
- "29:pushl $30f\n" // emulate rt_sigreturn()
- "jmp 5b\n"
-
- // Non-executable versions of the restorer function. We use these to
- // trigger a SEGV upon returning from the user's signal handler, giving
- // us an ability to clean up prior to returning from the SEGV handler.
- ".pushsection .data\n" // move code into non-executable section
- "30:mov $173, %%eax\n" // NR_rt_sigreturn
- "int $0x80\n" // gdb looks for this signature when doing
- ".byte 0\n" // backtraces
- "31:pop %%eax\n"
- "mov $119, %%eax\n" // NR_sigreturn
- "int $0x80\n"
- ".popsection\n"
+ "27:decl %%fs:0x1040-0x58\n"
+ "jmp 6b\n"
+ "28:decl %%fs:0x1040-0x58\n"
+ "jmp 7b\n"
#else
#error Unsupported target platform
#endif
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698