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

Side by Side Diff: patch_offline.cc

Issue 8589027: Add a tool for patching ELF libraries/executables offline (Closed) Base URL: https://seccompsandbox.googlecode.com/svn/trunk
Patch Set: Add to 'clean' target 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « makefile ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2011 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
5 #include <assert.h>
6 #include <elf.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10
11 #include "x86_decode.h"
12
13 // This tool patches ELF libraries and executables so that they can be
14 // used with elf_loader.cc. It rewrites system call instructions so
15 // that they will work inside the sandbox.
Markus (顧孟勤) 2011/11/17 22:15:19 I suspect, in the long run, you probably want a to
16
17
18 static void CheckBounds(char *data, size_t data_size,
19 void *ptr, size_t inside_size) {
20 assert(data <= (char *) ptr);
21 assert((char *) ptr + inside_size <= data + data_size);
22 }
23
24 static int FixUpSection(bool is64bit, char *code, size_t code_size) {
25 int patch_count = 0;
26 char *pos = code;
27 char *end = code + code_size;
28 while (pos < end) {
29 const char *ip = pos;
30 playground::next_inst(&ip, is64bit);
31 if (is64bit
32 ? (pos[0] == '\x0f' && pos[1] == '\x05') /* syscall */
33 : (pos[0] == '\xcd' && pos[1] == '\x80') /* int $0x80 */) {
34 // Replace the instruction with "int $0". This is the simplest
35 // thing to do since it does not involve moving any instructions
36 // around or extending the code segment. However, executing
37 // system calls via "int $0" is not very fast at run time.
38 pos[0] = '\xcd';
39 pos[1] = '\x00';
40 patch_count++;
41 }
42 pos = (char *) ip;
43 }
44 return patch_count;
45 }
46
47 struct Elf32 {
48 typedef Elf32_Ehdr Ehdr;
49 typedef Elf32_Shdr Shdr;
50 };
51
52 struct Elf64 {
53 typedef Elf64_Ehdr Ehdr;
54 typedef Elf64_Shdr Shdr;
55 };
56
57 template <class Elf>
58 static void FixUpElf(char *data, size_t data_size) {
59 typename Elf::Ehdr *header = (typename Elf::Ehdr *) data;
60 CheckBounds(data, data_size, header, sizeof(*header));
61 assert(memcmp(header->e_ident, ELFMAG, strlen(ELFMAG)) == 0);
62
63 int patch_count = 0;
64 for (int index = 0; index < header->e_shnum; index++) {
65 typename Elf::Shdr *section =
66 (typename Elf::Shdr *) (data + header->e_shoff +
67 header->e_shentsize * index);
68 CheckBounds(data, data_size, section, sizeof(*section));
69
70 if ((section->sh_flags & SHF_EXECINSTR) != 0) {
71 CheckBounds(data, data_size,
72 data + section->sh_offset, section->sh_size);
73 patch_count += FixUpSection(header->e_machine == EM_X86_64,
74 data + section->sh_offset, section->sh_size);
75 }
76 }
77 printf("patched %i syscall instructions\n", patch_count);
78 }
79
80 static void FixUpElfFile(const char *input_file, const char *output_file) {
81 FILE *fp;
82 size_t file_size;
83 char *data;
84 size_t got;
85 size_t written;
86
87 // Read whole ELF file and write it back with modifications.
88 fp = fopen(input_file, "rb");
89 if (fp == NULL) {
90 fprintf(stderr, "Failed to open input file: %s\n", input_file);
91 exit(1);
92 }
93 // Find the file size.
94 fseek(fp, 0, SEEK_END);
95 file_size = ftell(fp);
96 data = (char *) malloc(file_size);
97 assert(data != NULL);
98 fseek(fp, 0, SEEK_SET);
99 got = fread(data, 1, file_size, fp);
100 assert(got == file_size);
101 fclose(fp);
102
103 switch (data[EI_CLASS]) {
104 case ELFCLASS64:
105 FixUpElf<Elf64>(data, file_size);
106 break;
107 case ELFCLASS32:
108 FixUpElf<Elf32>(data, file_size);
109 break;
110 default:
111 fprintf(stderr, "Unknown ELF class\n");
112 exit(1);
113 }
114
115 fp = fopen(output_file, "wb");
116 if (fp == NULL) {
117 fprintf(stderr, "Failed to open output file: %s\n", output_file);
118 exit(1);
119 }
120 written = fwrite(data, 1, file_size, fp);
121 assert(written == file_size);
122 fclose(fp);
123 free(data);
124 }
125
126 int main(int argc, char **argv) {
127 if (argc != 4 || strcmp(argv[2], "-o") != 0) {
128 fprintf(stderr, "Usage: %s <input-file> -o <output-file>\n\n", argv[0]);
129 fprintf(stderr,
130 "This tool rewrites ELF objects to patch system call instructions\n"
131 "to be redirected via the seccomp-sandbox's handler.\n");
132 return 1;
133 }
134 FixUpElfFile(argv[1], argv[3]);
135 return 0;
136 }
OLDNEW
« no previous file with comments | « makefile ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698