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

Unified Diff: library.cc

Issue 8605003: Add logic for patching calls to the x86-64 vsyscall page (Closed) Base URL: https://seccompsandbox.googlecode.com/svn/trunk
Patch Set: Created 9 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 | tests/test_patching.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: library.cc
diff --git a/library.cc b/library.cc
index 58459435b13315c515ef46ec86fdafc892c60b67..07a41ccd2377d790a2846c704496bbede2dae6ce 100644
--- a/library.cc
+++ b/library.cc
@@ -364,6 +364,54 @@ char* Library::getScratchSpace(const Maps* maps, char* near, int needed,
Sandbox::die("Insufficient space to intercept system call");
}
+#if defined(__x86_64__)
+static bool isCallToVsyscallPage(char* code) {
+ // Look for these instructions, which are a call to the x86-64
+ // vsyscall page, which the kernel puts at a fixed address:
+ //
+ // 48 c7 c0 00 XX 60 ff mov $0xffffffffff60XX00,%rax
+ // ff d0 callq *%rax
+ //
+ // This will not catch all calls to the vsyscall page, but it
+ // handles the important cases that glibc contains. The vsyscall
+ // page is deprecated, so it is unlikely that new instruction
+ // sequences for calling it will be introduced.
+ return (code[0] == '\x48' &&
+ code[1] == '\xc7' &&
+ code[2] == '\xc0' &&
+ code[3] == '\x00' &&
+ (code[4] == '\x00' || code[4] == '\x04' || code[4] == '\x08') &&
+ code[5] == '\x60' &&
+ code[6] == '\xff' &&
+ code[7] == '\xff' &&
+ code[8] == '\xd0');
+}
+
+static void patchCallToVsyscallPage(char* code) {
+ // We replace the mov+callq with these instructions:
+ //
+ // b8 XX XX XX XX mov $X, %eax // where X is the syscall number
+ // 0f 05 syscall
+ // 90 nop
+ // 90 nop
+ //
+ // The syscall instruction will later be patched by the general case.
+ if (code[4] == '\x00') {
+ // Use __NR_gettimeofday == 96 == 0x60.
+ const char replacement[] = "\xb8\x60\x00\x00\x00\x0f\x05\x90\x90";
+ memcpy(code, replacement, sizeof(replacement) - 1);
+ } else if (code[4] == '\x04') {
+ // Use __NR_time == 201 == 0xc9.
+ const char replacement[] = "\xb8\xc9\x00\x00\x00\x0f\x05\x90\x90";
+ memcpy(code, replacement, sizeof(replacement) - 1);
+ } else if (code[4] == '\x08') {
+ // Use __NR_getcpu == 309 == 0x135.
+ const char replacement[] = "\xb8\x35\x01\x00\x00\x0f\x05\x90\x90";
+ memcpy(code, replacement, sizeof(replacement) - 1);
+ }
+}
+#endif
+
void Library::patchSystemCallsInFunction(const Maps* maps, int vsys_offset,
char* start, char* end,
char** extraSpace, int* extraLength) {
@@ -392,6 +440,11 @@ void Library::patchSystemCallsInFunction(const Maps* maps, int vsys_offset,
int codeIdx = 0;
char* ptr = start;
while (ptr < end) {
+ #if defined(__x86_64__)
+ if (isCallToVsyscallPage(ptr)) {
+ patchCallToVsyscallPage(ptr);
+ }
+ #endif
// Keep a ring-buffer of the last few instruction in order to find the
// correct place to patch the code.
char *mod_rm;
@@ -1031,7 +1084,8 @@ void Library::patchSystemCallsInRange(char* start, char* stop,
for (char *ptr = start; ptr < stop; ptr++) {
#if defined(__x86_64__)
if ((*ptr == '\x0F' && ptr[1] == '\x05' /* SYSCALL */) ||
- (isVDSO_ && *ptr == '\xFF')) {
+ (isVDSO_ && *ptr == '\xFF') ||
+ isCallToVsyscallPage(ptr)) {
#elif defined(__i386__)
if ((*ptr == '\xCD' && ptr[1] == '\x80' /* INT $0x80 */) ||
(*ptr == '\x65' && ptr[1] == '\xFF' &&
« no previous file with comments | « no previous file | tests/test_patching.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698