This source file includes following definitions.
- load_elf_binary
- load_elf_library
1 #include <linux/fs.h>
2 #include <linux/sched.h>
3 #include <linux/mm.h>
4 #include <linux/mman.h>
5 #include <linux/a.out.h>
6 #include <linux/errno.h>
7 #include <linux/signal.h>
8 #include <linux/binfmts.h>
9 #include <asm/segment.h>
10 #include <linux/string.h>
11 #include <linux/fcntl.h>
12 #include <linux/ptrace.h>
13
14 asmlinkage int sys_exit(int exit_code);
15 asmlinkage int sys_close(unsigned fd);
16 asmlinkage int sys_open(const char *, int, int);
17
18
19
20
21
22
23 #include <linux/elf.h>
24
25 int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
26 {
27 struct elfhdr elf_ex;
28 struct file * file;
29 struct exec ex;
30 struct inode *interpreter_inode;
31 int i;
32 int old_fs;
33 int error;
34 struct elf_phdr * elf_ppnt, *elf_phdata;
35 int elf_exec_fileno;
36 unsigned int elf_bss, k, elf_brk;
37 int retval;
38 char * elf_interpreter;
39 unsigned int elf_entry;
40 int status;
41 unsigned int start_code, end_code, end_data;
42 unsigned int elf_stack;
43 char passed_fileno[6];
44
45 status = 0;
46 elf_ex = *((struct elfhdr *) bprm->buf);
47
48 if (elf_ex.e_ident[0] != 0x7f ||
49 strncmp(&elf_ex.e_ident[1], "ELF",3) != 0)
50 return -ENOEXEC;
51
52
53
54 if(elf_ex.e_type != ET_EXEC ||
55 (elf_ex.e_machine != EM_386 && elf_ex.e_machine != EM_486) ||
56 (!bprm->inode->i_op || !bprm->inode->i_op->default_file_ops ||
57 !bprm->inode->i_op->default_file_ops->mmap)){
58 return -ENOEXEC;
59 };
60
61
62
63 elf_phdata = (struct elf_phdr *) kmalloc(elf_ex.e_phentsize *
64 elf_ex.e_phnum, GFP_KERNEL);
65
66 old_fs = get_fs();
67 set_fs(get_ds());
68 retval = read_exec(bprm->inode, elf_ex.e_phoff, (char *) elf_phdata,
69 elf_ex.e_phentsize * elf_ex.e_phnum);
70 set_fs(old_fs);
71 if (retval < 0) {
72 kfree (elf_phdata);
73 return retval;
74 }
75
76 elf_ppnt = elf_phdata;
77
78 elf_bss = 0;
79 elf_brk = 0;
80
81 elf_exec_fileno = open_inode(bprm->inode, O_RDONLY);
82
83 if (elf_exec_fileno < 0) {
84 kfree (elf_phdata);
85 return elf_exec_fileno;
86 }
87
88 file = current->filp[elf_exec_fileno];
89
90 elf_stack = 0xffffffff;
91 elf_interpreter = NULL;
92 start_code = 0;
93 end_code = 0;
94 end_data = 0;
95
96 old_fs = get_fs();
97 set_fs(get_ds());
98
99 for(i=0;i < elf_ex.e_phnum; i++){
100 if(elf_ppnt->p_type == PT_INTERP) {
101
102
103
104 elf_interpreter = (char *) kmalloc(elf_ppnt->p_filesz,
105 GFP_KERNEL);
106
107 retval = read_exec(bprm->inode,elf_ppnt->p_offset,elf_interpreter,
108 elf_ppnt->p_filesz);
109 printk("Using ELF interpreter %s\n", elf_interpreter);
110 if(retval >= 0)
111 retval = namei(elf_interpreter, &interpreter_inode);
112 if(retval >= 0)
113 retval = read_exec(interpreter_inode,0,bprm->buf,128);
114
115 if(retval >= 0){
116 ex = *((struct exec *) bprm->buf);
117
118 #if 0
119 printk("Interpreter: %x %x %x\n",N_MAGIC(ex), ex.a_text,ex.a_data);
120 #endif
121 };
122 };
123 elf_ppnt++;
124 };
125
126 set_fs(old_fs);
127
128
129 if(elf_interpreter){
130 if(retval < 0) {
131 kfree(elf_interpreter);
132 kfree(elf_phdata);
133 return -ELIBACC;
134 };
135 if((N_MAGIC(ex) != OMAGIC) && (N_MAGIC(ex) != ZMAGIC)) {
136 kfree(elf_interpreter);
137 kfree(elf_phdata);
138 return -ELIBBAD;
139 };
140 }
141
142
143
144
145 if (!bprm->sh_bang) {
146 char * passed_p;
147
148 sprintf(passed_fileno, "%d", elf_exec_fileno);
149 passed_p = passed_fileno;
150
151 if(elf_interpreter) {
152 bprm->p = copy_strings(1,&passed_p,bprm->page,bprm->p,2);
153 bprm->argc++;
154 };
155 if (!bprm->p) {
156 if(elf_interpreter) {
157 kfree(elf_interpreter);
158 }
159 kfree (elf_phdata);
160 return -E2BIG;
161 }
162 }
163
164
165 flush_old_exec(bprm);
166
167 current->end_data = 0;
168 current->end_code = 0;
169 current->start_mmap = ELF_START_MMAP;
170 current->mmap = NULL;
171 elf_entry = (unsigned int) elf_ex.e_entry;
172
173
174
175 current->rss = 0;
176 bprm->p += change_ldt(0, bprm->page);
177 current->start_stack = bprm->p;
178
179
180
181
182
183
184 old_fs = get_fs();
185 set_fs(get_ds());
186
187 elf_ppnt = elf_phdata;
188 for(i=0;i < elf_ex.e_phnum; i++){
189
190 if(elf_ppnt->p_type == PT_INTERP) {
191
192 current->brk = ex.a_bss +
193 (current->end_data = ex.a_data +
194 (current->end_code = ex.a_text));
195 elf_entry = ex.a_entry;
196
197
198 set_fs(old_fs);
199
200 if (N_MAGIC(ex) == OMAGIC) {
201 retval = read_exec(interpreter_inode, 32, (char *) 0,
202 ex.a_text+ex.a_data);
203 iput(interpreter_inode);
204 } else if (N_MAGIC(ex) == ZMAGIC || N_MAGIC(ex) == QMAGIC) {
205 retval = read_exec(interpreter_inode,
206 N_TXTOFF(ex) ,
207 (char *) N_TXTADDR(ex),
208 ex.a_text+ex.a_data);
209 iput(interpreter_inode);
210 } else
211 retval = -1;
212
213 old_fs = get_fs();
214 set_fs(get_ds());
215
216 if(retval >= 0)
217 zeromap_page_range((ex.a_text + ex.a_data + 0xfff) &
218 0xfffff000, ex.a_bss, PAGE_COPY);
219 kfree(elf_interpreter);
220
221 if(retval < 0) {
222 kfree(elf_phdata);
223 send_sig(SIGSEGV, current, 0);
224 return 0;
225 };
226 };
227
228
229 if(elf_ppnt->p_type == PT_LOAD) {
230 error = do_mmap(file,
231 elf_ppnt->p_vaddr & 0xfffff000,
232 elf_ppnt->p_filesz + (elf_ppnt->p_vaddr & 0xfff),
233 PROT_READ | PROT_WRITE | PROT_EXEC,
234 MAP_FIXED | MAP_PRIVATE,
235 elf_ppnt->p_offset & 0xfffff000);
236
237 #ifdef LOW_ELF_STACK
238 if(elf_ppnt->p_vaddr & 0xfffff000 < elf_stack)
239 elf_stack = elf_ppnt->p_vaddr & 0xfffff000;
240 #endif
241
242 k = elf_ppnt->p_vaddr;
243 if(k > start_code) start_code = k;
244 k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
245 if(k > elf_bss) elf_bss = k;
246 if((elf_ppnt->p_flags | PROT_WRITE) && end_code < k)
247 end_code = k;
248 if(end_data < k) end_data = k;
249 k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz;
250 if(k > elf_brk) elf_brk = k;
251
252 if(status == 0xffffffff) {
253 set_fs(old_fs);
254 kfree(elf_phdata);
255 send_sig(SIGSEGV, current, 0);
256 return 0;
257 };
258 };
259 elf_ppnt++;
260 };
261 set_fs(old_fs);
262
263 kfree(elf_phdata);
264
265 if(!elf_interpreter) sys_close(elf_exec_fileno);
266 current->elf_executable = 1;
267 current->executable = bprm->inode;
268 bprm->inode->i_count++;
269 #ifdef LOW_ELF_STACK
270 current->start_stack = p = elf_stack - 4;
271 #endif
272 bprm->p -= MAX_ARG_PAGES*PAGE_SIZE;
273 bprm->p = (unsigned long) create_tables((char *)bprm->p,bprm->argc,bprm->envc);
274 if(elf_interpreter) current->arg_start += strlen(passed_fileno) + 1;
275 current->start_brk = current->brk = elf_brk;
276 current->end_code = end_code;
277 current->start_code = start_code;
278 current->start_stack = bprm->p;
279 current->suid = current->euid = bprm->e_uid;
280 current->sgid = current->egid = bprm->e_gid;
281 zeromap_page_range((elf_bss + 0xfff) & 0xfffff000, elf_brk - elf_bss,
282 PAGE_COPY);
283 regs->eip = elf_entry;
284 regs->esp = bprm->p;
285 if (current->flags & PF_PTRACED)
286 send_sig(SIGTRAP, current, 0);
287
288 return 0;
289 }
290
291
292 int load_elf_library(int fd){
293 struct file * file;
294 struct elfhdr elf_ex;
295 struct elf_phdr *elf_phdata = NULL;
296 struct inode * inode;
297 unsigned int len;
298 int old_fs, retval;
299 unsigned int bss;
300 int error;
301 int i,j;
302
303 len = 0;
304 file = current->filp[fd];
305 inode = file->f_inode;
306
307 set_fs(KERNEL_DS);
308 if (file->f_op->read(inode, file, (char *) &elf_ex, sizeof(elf_ex)) != sizeof(elf_ex)) {
309 sys_close(fd);
310 return -EACCES;
311 }
312 set_fs(USER_DS);
313
314 if (elf_ex.e_ident[0] != 0x7f ||
315 strncmp(&elf_ex.e_ident[1], "ELF",3) != 0)
316 return -ENOEXEC;
317
318
319 if(elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 ||
320 (elf_ex.e_machine != EM_386 && elf_ex.e_machine != EM_486) ||
321 (!inode->i_op || !inode->i_op->bmap ||
322 !inode->i_op->default_file_ops->mmap)){
323 return -ENOEXEC;
324 };
325
326
327
328 if(sizeof(struct elf_phdr) * elf_ex.e_phnum > PAGE_SIZE)
329 return -ENOEXEC;
330
331 elf_phdata = (struct elf_phdr *)
332 kmalloc(sizeof(struct elf_phdr) * elf_ex.e_phnum, GFP_KERNEL);
333
334 old_fs = get_fs();
335 set_fs(get_ds());
336 retval = read_exec(inode, elf_ex.e_phoff, (char *) elf_phdata,
337 sizeof(struct elf_phdr) * elf_ex.e_phnum);
338 set_fs(old_fs);
339
340 j = 0;
341 for(i=0; i<elf_ex.e_phnum; i++)
342 if((elf_phdata + i)->p_type == PT_LOAD) j++;
343
344 if(j != 1) {
345 kfree(elf_phdata);
346 return -ENOEXEC;
347 };
348
349 while(elf_phdata->p_type != PT_LOAD) elf_phdata++;
350
351
352 error = do_mmap(file,
353 elf_phdata->p_vaddr & 0xfffff000,
354 elf_phdata->p_filesz + (elf_phdata->p_vaddr & 0xfff),
355 PROT_READ | PROT_WRITE | PROT_EXEC,
356 MAP_FIXED | MAP_PRIVATE,
357 elf_phdata->p_offset & 0xfffff000);
358
359 sys_close(fd);
360 if (error != elf_phdata->p_vaddr & 0xfffff000) {
361 kfree(elf_phdata);
362 return error;
363 }
364 len = (elf_phdata->p_filesz + elf_phdata->p_vaddr+ 0xfff) & 0xfffff000;
365 bss = elf_phdata->p_memsz + elf_phdata->p_vaddr;
366 if (bss > len)
367 zeromap_page_range(len, bss-len, PAGE_COPY);
368 kfree(elf_phdata);
369 return 0;
370 }