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

Side by Side Diff: syscall_entrypoint.cc

Issue 8036047: In 32bit mode, removed all assembly addressing modes that are incompatible with (Closed) Base URL: http://seccompsandbox.googlecode.com/svn/trunk/
Patch Set: Created 9 years, 2 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « sigaction.cc ('k') | test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
OLDNEW
« no previous file with comments | « sigaction.cc ('k') | test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698