OLD | NEW |
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 #define XOPEN_SOURCE 500 | 5 #define XOPEN_SOURCE 500 |
6 | 6 |
7 #include "library.h" | 7 #include "library.h" |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
10 #include <elf.h> | 10 #include <elf.h> |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
52 typedef Elf32_Sxword Elf_Sxword; | 52 typedef Elf32_Sxword Elf_Sxword; |
53 typedef Elf32_Off Elf_Off; | 53 typedef Elf32_Off Elf_Off; |
54 typedef Elf32_Section Elf_Section; | 54 typedef Elf32_Section Elf_Section; |
55 typedef Elf32_Versym Elf_Versym; | 55 typedef Elf32_Versym Elf_Versym; |
56 #else | 56 #else |
57 #error Unsupported target platform | 57 #error Unsupported target platform |
58 #endif | 58 #endif |
59 | 59 |
60 namespace playground { | 60 namespace playground { |
61 | 61 |
62 Maps* Library::maps_; | |
63 char* Library::__kernel_vsyscall; | 62 char* Library::__kernel_vsyscall; |
64 char* Library::__kernel_sigreturn; | 63 char* Library::__kernel_sigreturn; |
65 char* Library::__kernel_rt_sigreturn; | 64 char* Library::__kernel_rt_sigreturn; |
66 | 65 |
67 Library::Library() : | 66 Library::Library() : |
68 valid_(false), | 67 valid_(false), |
69 isVDSO_(false), | 68 isVDSO_(false), |
70 asr_offset_(0), | 69 asr_offset_(0), |
71 vsys_offset_(0), | 70 vsys_offset_(0), |
72 image_(0), | 71 image_(0), |
73 image_size_(0) { | 72 image_size_(0), |
| 73 maps_(NULL) { |
74 } | 74 } |
75 | 75 |
76 Library::~Library() { | 76 Library::~Library() { |
77 if (image_size_) { | 77 if (image_size_) { |
78 // We no longer need access to a full mapping of the underlying library | 78 // We no longer need access to a full mapping of the underlying library |
79 // file. Move the temporarily extended mapping back to where we originally | 79 // file. Move the temporarily extended mapping back to where we originally |
80 // found. Make sure to preserve any changes that we might have made since. | 80 // found. Make sure to preserve any changes that we might have made since. |
81 Sandbox::SysCalls sys; | 81 Sandbox::SysCalls sys; |
82 sys.mprotect(image_, 4096, PROT_READ | PROT_WRITE | PROT_EXEC); | 82 sys.mprotect(image_, 4096, PROT_READ | PROT_WRITE | PROT_EXEC); |
83 if (memcmp(image_, memory_ranges_.rbegin()->second.start, 4096)) { | 83 if (memcmp(image_, memory_ranges_.rbegin()->second.start, 4096)) { |
(...skipping 923 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1007 return; | 1007 return; |
1008 #endif | 1008 #endif |
1009 } | 1009 } |
1010 SectionTable::const_iterator iter; | 1010 SectionTable::const_iterator iter; |
1011 if ((iter = section_table_.find(".text")) == section_table_.end()) { | 1011 if ((iter = section_table_.find(".text")) == section_table_.end()) { |
1012 return; | 1012 return; |
1013 } | 1013 } |
1014 const Elf_Shdr& shdr = iter->second.second; | 1014 const Elf_Shdr& shdr = iter->second.second; |
1015 char* start = reinterpret_cast<char *>(shdr.sh_addr + asr_offset_); | 1015 char* start = reinterpret_cast<char *>(shdr.sh_addr + asr_offset_); |
1016 char* stop = start + shdr.sh_size; | 1016 char* stop = start + shdr.sh_size; |
| 1017 patchSystemCallsInRange(start, stop, &extraSpace, &extraLength); |
| 1018 |
| 1019 // Mark our scratch space as write-protected and executable. |
| 1020 if (extraSpace) { |
| 1021 Sandbox::SysCalls sys; |
| 1022 sys.mprotect(extraSpace, 4096, PROT_READ|PROT_EXEC); |
| 1023 } |
| 1024 } |
| 1025 |
| 1026 void Library::patchSystemCallsInRange(char* start, char* stop, |
| 1027 char** extraSpace, int* extraLength) { |
1017 char* func = start; | 1028 char* func = start; |
1018 int nopcount = 0; | 1029 int nopcount = 0; |
1019 bool has_syscall = false; | 1030 bool has_syscall = false; |
1020 for (char *ptr = start; ptr < stop; ptr++) { | 1031 for (char *ptr = start; ptr < stop; ptr++) { |
1021 #if defined(__x86_64__) | 1032 #if defined(__x86_64__) |
1022 if ((*ptr == '\x0F' && ptr[1] == '\x05' /* SYSCALL */) || | 1033 if ((*ptr == '\x0F' && ptr[1] == '\x05' /* SYSCALL */) || |
1023 (isVDSO_ && *ptr == '\xFF')) { | 1034 (isVDSO_ && *ptr == '\xFF')) { |
1024 #elif defined(__i386__) | 1035 #elif defined(__i386__) |
1025 if ((*ptr == '\xCD' && ptr[1] == '\x80' /* INT $0x80 */) || | 1036 if ((*ptr == '\xCD' && ptr[1] == '\x80' /* INT $0x80 */) || |
1026 (*ptr == '\x65' && ptr[1] == '\xFF' && | 1037 (*ptr == '\x65' && ptr[1] == '\xFF' && |
(...skipping 13 matching lines...) Expand all Loading... |
1040 // padded out with NOPs. | 1051 // padded out with NOPs. |
1041 // | 1052 // |
1042 // For performance reasons, we quickly scan the entire text segment | 1053 // For performance reasons, we quickly scan the entire text segment |
1043 // for potential SYSCALLs, and then patch the code in increments of | 1054 // for potential SYSCALLs, and then patch the code in increments of |
1044 // individual functions. | 1055 // individual functions. |
1045 if (has_syscall) { | 1056 if (has_syscall) { |
1046 has_syscall = false; | 1057 has_syscall = false; |
1047 // Our quick scan of the function found a potential system call. | 1058 // Our quick scan of the function found a potential system call. |
1048 // Do a more thorough scan, now. | 1059 // Do a more thorough scan, now. |
1049 patchSystemCallsInFunction(maps_, isVDSO_ ? vsys_offset_ : 0, func, | 1060 patchSystemCallsInFunction(maps_, isVDSO_ ? vsys_offset_ : 0, func, |
1050 ptr, &extraSpace, &extraLength); | 1061 ptr, extraSpace, extraLength); |
1051 } | 1062 } |
1052 func = ptr; | 1063 func = ptr; |
1053 } | 1064 } |
1054 nopcount = 0; | 1065 nopcount = 0; |
1055 } else { | 1066 } else { |
1056 nopcount = 0; | 1067 nopcount = 0; |
1057 } | 1068 } |
1058 } | 1069 } |
1059 if (has_syscall) { | 1070 if (has_syscall) { |
1060 // Patch any remaining system calls that were in the last function before | 1071 // Patch any remaining system calls that were in the last function before |
1061 // the loop terminated. | 1072 // the loop terminated. |
1062 patchSystemCallsInFunction(maps_, isVDSO_ ? vsys_offset_ : 0, func, stop, | 1073 patchSystemCallsInFunction(maps_, isVDSO_ ? vsys_offset_ : 0, func, stop, |
1063 &extraSpace, &extraLength); | 1074 extraSpace, extraLength); |
1064 } | |
1065 | |
1066 // Mark our scratch space as write-protected and executable. | |
1067 if (extraSpace) { | |
1068 Sandbox::SysCalls sys; | |
1069 sys.mprotect(extraSpace, 4096, PROT_READ|PROT_EXEC); | |
1070 } | 1075 } |
1071 } | 1076 } |
1072 | 1077 |
1073 bool Library::parseElf() { | 1078 bool Library::parseElf() { |
1074 valid_ = true; | 1079 valid_ = true; |
1075 | 1080 |
1076 // Verify ELF header | 1081 // Verify ELF header |
1077 Elf_Shdr str_shdr; | 1082 Elf_Shdr str_shdr; |
1078 if (!getOriginal(0, &ehdr_) || | 1083 if (!getOriginal(0, &ehdr_) || |
1079 ehdr_.e_ehsize < sizeof(Elf_Ehdr) || | 1084 ehdr_.e_ehsize < sizeof(Elf_Ehdr) || |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1182 } | 1187 } |
1183 iter = symbols_.find("__kernel_rt_sigreturn"); | 1188 iter = symbols_.find("__kernel_rt_sigreturn"); |
1184 if (iter != symbols_.end() && iter->second.st_value) { | 1189 if (iter != symbols_.end() && iter->second.st_value) { |
1185 __kernel_rt_sigreturn = asr_offset_ + iter->second.st_value; | 1190 __kernel_rt_sigreturn = asr_offset_ + iter->second.st_value; |
1186 } | 1191 } |
1187 | 1192 |
1188 return true; | 1193 return true; |
1189 } | 1194 } |
1190 | 1195 |
1191 } // namespace | 1196 } // namespace |
OLD | NEW |