| 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 "debug.h" | 5 #include "debug.h" |
| 2 #include "sandbox_impl.h" | 6 #include "sandbox_impl.h" |
| 3 #include "syscall_table.h" | 7 #include "syscall_table.h" |
| 4 | 8 |
| 5 namespace playground { | 9 namespace playground { |
| 6 | 10 |
| 7 // TODO(markus): change this into a function that returns the address of the ass
embly code. If that isn't possible for sandbox_clone, then move that function in
to a *.S file | 11 // TODO(markus): change this into a function that returns the address of the ass
embly code. If that isn't possible for sandbox_clone, then move that function in
to a *.S file |
| 8 asm( | 12 asm( |
| 9 ".pushsection .text, \"ax\", @progbits\n" | 13 ".pushsection .text, \"ax\", @progbits\n" |
| 10 | 14 |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 139 "push %ebp\n" | 143 "push %ebp\n" |
| 140 "push %edi\n" | 144 "push %edi\n" |
| 141 "push %esi\n" | 145 "push %esi\n" |
| 142 "push %edx\n" | 146 "push %edx\n" |
| 143 "push %ecx\n" | 147 "push %ecx\n" |
| 144 "push %ebx\n" | 148 "push %ebx\n" |
| 145 "push %eax\n" | 149 "push %eax\n" |
| 146 | 150 |
| 147 // Check range of system call | 151 // Check range of system call |
| 148 "cmp playground$maxSyscall, %eax\n" | 152 "cmp playground$maxSyscall, %eax\n" |
| 149 "ja 1f\n" | 153 "ja 5f\n" |
| 154 |
| 155 // We often have long sequences of calls to gettimeofday(). This is |
| 156 // needlessly expensive. Coalesce them into a single call. |
| 157 // |
| 158 // We keep track of state in TLS storage that we can access through |
| 159 // the %fs segment register. See trusted_thread.cc for the exact |
| 160 // memory layout. |
| 161 // |
| 162 // TODO(markus): maybe, we should proactively call gettimeofday() and |
| 163 // clock_gettime(), whenever we talk to the trusted thread? |
| 164 // or maybe, if we have recently seen requests to compute |
| 165 // the time. There might be a repeated pattern of those. |
| 166 "cmp $78, %eax\n" // __NR_gettimeofday |
| 167 "jnz 2f\n" |
| 168 "cmp %eax, %fs:0x102C-0x54\n" // last system call |
| 169 "jnz 0f\n" |
| 170 |
| 171 // This system call and the last system call prior to this one both are |
| 172 // calls to gettimeofday(). Try to avoid making the new call and just |
| 173 // return the same result as in the previous call. |
| 174 // Just in case the caller is spinning on the result from gettimeofday(), |
| 175 // every so often, call the actual system call. |
| 176 "decl %fs:0x1030-0x54\n" // countdown calls to gettimofday() |
| 177 "jz 0f\n" |
| 178 |
| 179 // Atomically read the 64bit word representing last-known timestamp and |
| 180 // return it to the caller. On x86-32 this is a little more complicated and |
| 181 // requires the use of the cmpxchg8b instruction. |
| 182 "mov %ebx, %eax\n" |
| 183 "mov %ecx, %edx\n" |
| 184 "lock; cmpxchg8b 100f\n" |
| 185 "mov %eax, 0(%ebx)\n" |
| 186 "mov %edx, 4(%ebx)\n" |
| 187 "xor %eax, %eax\n" |
| 188 "add $28, %esp\n" |
| 189 "jmp 4f\n" |
| 190 |
| 191 // This is a call to gettimeofday(), but we don't have a valid cached |
| 192 // result, yet. |
| 193 "0:mov %eax, %fs:0x102C-0x54\n" // remember syscall number |
| 194 "movl $500, %fs:0x1030-0x54\n" // make system call, each 500 invocations |
| 195 "call playground$defaultSystemCallHandler\n" |
| 196 |
| 197 // Returned from gettimeofday(). Remember return value, in case the |
| 198 // application calls us again right away. |
| 199 // Again, this has to happen atomically and requires cmpxchg8b. |
| 200 "mov 4(%ebx), %ecx\n" |
| 201 "mov 0(%ebx), %ebx\n" |
| 202 "mov 100f, %eax\n" |
| 203 "mov 101f, %edx\n" |
| 204 "1:lock; cmpxchg8b 100f\n" |
| 205 "jnz 1b\n" |
| 206 "xor %eax, %eax\n" |
| 207 "jmp 6f\n" |
| 208 |
| 209 // Remember the number of the last system call made. We deliberately do |
| 210 // not remember calls to gettid(), as we have often seen long sequences |
| 211 // of calls to just gettimeofday() and gettid(). In that situation, we |
| 212 // would still like to coalesce the gettimeofday() calls. |
| 213 "2:cmp $224, %eax\n" // __NR_gettid |
| 214 "jz 3f\n" |
| 215 "mov %eax, %fs:0x102C-0x54\n" // remember syscall number |
| 150 | 216 |
| 151 // Retrieve function call from system call table (c.f. syscall_table.c). | 217 // Retrieve function call from system call table (c.f. syscall_table.c). |
| 152 // We have three different types of entries; zero for denied system calls, | 218 // We have three different types of entries; zero for denied system calls, |
| 153 // that should be handled by the defaultSystemCallHandler(); minus one | 219 // that should be handled by the defaultSystemCallHandler(); minus one |
| 154 // for unrestricted system calls that need to be forwarded to the trusted | 220 // for unrestricted system calls that need to be forwarded to the trusted |
| 155 // thread; and function pointers to specific handler functions. | 221 // thread; and function pointers to specific handler functions. |
| 156 "shl $3, %eax\n" | 222 "3:shl $3, %eax\n" |
| 157 "lea playground$syscallTable, %ebx\n" | 223 "lea playground$syscallTable, %ebx\n" |
| 158 "add %ebx, %eax\n" | 224 "add %ebx, %eax\n" |
| 159 "mov 0(%eax), %eax\n" | 225 "mov 0(%eax), %eax\n" |
| 160 | 226 |
| 161 // Jump to function if non-null and not UNRESTRICTED_SYSCALL, otherwise | 227 // Jump to function if non-null and not UNRESTRICTED_SYSCALL, otherwise |
| 162 // jump to fallback handler. | 228 // jump to fallback handler. |
| 163 "cmp $1, %eax\n" | 229 "cmp $1, %eax\n" |
| 164 "jbe 1f\n" | 230 "jbe 5f\n" |
| 165 "add $4, %esp\n" | 231 "add $4, %esp\n" |
| 166 "call *%eax\n" | 232 "call *%eax\n" |
| 167 "add $24, %esp\n" | 233 "add $24, %esp\n" |
| 168 "0:" | |
| 169 | 234 |
| 170 // Restore CPU registers, except for %eax which was set by the system call. | 235 // Restore CPU registers, except for %eax which was set by the system call. |
| 171 "pop %ebp\n" | 236 "4:pop %ebp\n" |
| 172 "pop %edi\n" | 237 "pop %edi\n" |
| 173 "pop %esi\n" | 238 "pop %esi\n" |
| 174 "pop %edx\n" | 239 "pop %edx\n" |
| 175 "pop %ecx\n" | 240 "pop %ecx\n" |
| 176 "pop %ebx\n" | 241 "pop %ebx\n" |
| 177 | 242 |
| 178 // Return to caller | 243 // Return to caller |
| 179 "ret\n" | 244 "ret\n" |
| 180 | 245 |
| 181 "1:" | |
| 182 // Call default handler. | 246 // Call default handler. |
| 183 "push $2f\n" | 247 "5:call playground$defaultSystemCallHandler\n" |
| 184 "push $playground$defaultSystemCallHandler\n" | 248 "6:add $28, %esp\n" |
| 185 "ret\n" | 249 "jmp 4b\n" |
| 186 "2:add $28, %esp\n" | 250 |
| 187 "jmp 0b\n" | 251 ".pushsection \".bss\"\n" |
| 252 ".balign 8\n" |
| 253 "100:.byte 0, 0, 0, 0\n" |
| 254 "101:.byte 0, 0, 0, 0\n" |
| 255 ".popsection\n" |
| 188 | 256 |
| 189 #else | 257 #else |
| 190 #error Unsupported target platform | 258 #error Unsupported target platform |
| 191 #endif | 259 #endif |
| 192 ".size playground$syscallWrapper, .-playground$syscallWrapper\n" | 260 ".size playground$syscallWrapper, .-playground$syscallWrapper\n" |
| 193 ".popsection\n" | 261 ".popsection\n" |
| 194 ); | 262 ); |
| 195 | 263 |
| 196 | 264 |
| 197 void* Sandbox::defaultSystemCallHandler(int syscallNum, void* arg0, void* arg1, | 265 void* Sandbox::defaultSystemCallHandler(int syscallNum, void* arg0, void* arg1, |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 250 return (void *)-ENOSYS; | 318 return (void *)-ENOSYS; |
| 251 } | 319 } |
| 252 } | 320 } |
| 253 if (rc < 0) { | 321 if (rc < 0) { |
| 254 rc = -sys.my_errno; | 322 rc = -sys.my_errno; |
| 255 } | 323 } |
| 256 return (void *)rc; | 324 return (void *)rc; |
| 257 } | 325 } |
| 258 | 326 |
| 259 } // namespace | 327 } // namespace |
| OLD | NEW |