This source file includes following definitions.
- padzero
- create_elf_tables
- load_elf_interp
- load_aout_interp
- load_elf_binary
- load_elf_library
1
2
3
4 #include <linux/fs.h>
5 #include <linux/sched.h>
6 #include <linux/mm.h>
7 #include <linux/mman.h>
8 #include <linux/a.out.h>
9 #include <linux/errno.h>
10 #include <linux/signal.h>
11 #include <linux/binfmts.h>
12 #include <linux/string.h>
13 #include <linux/fcntl.h>
14 #include <linux/ptrace.h>
15 #include <linux/malloc.h>
16 #include <linux/shm.h>
17
18 #include <asm/segment.h>
19
20 asmlinkage int sys_exit(int exit_code);
21 asmlinkage int sys_close(unsigned fd);
22 asmlinkage int sys_open(const char *, int, int);
23 asmlinkage int sys_brk(unsigned long);
24
25 #define DLINFO_ITEMS 8
26
27 #include <linux/elf.h>
28
29
30
31
32
33
34 static void padzero(int elf_bss){
35 unsigned int fpnt, nbyte;
36
37 if(elf_bss & 0xfff) {
38
39 nbyte = (PAGE_SIZE - (elf_bss & 0xfff)) & 0xfff;
40 if(nbyte){
41 verify_area(VERIFY_WRITE, (void *) elf_bss, nbyte);
42
43 fpnt = elf_bss;
44 while(fpnt & 0xfff) put_fs_byte(0, fpnt++);
45 };
46 };
47 }
48
49 unsigned long * create_elf_tables(char * p,int argc,int envc,struct elfhdr * exec, unsigned int load_addr, int ibcs)
50 {
51 unsigned long *argv,*envp, *dlinfo;
52 unsigned long * sp;
53 struct vm_area_struct *mpnt;
54
55 mpnt = (struct vm_area_struct *)kmalloc(sizeof(*mpnt), GFP_KERNEL);
56 if (mpnt) {
57 mpnt->vm_task = current;
58 mpnt->vm_start = PAGE_MASK & (unsigned long) p;
59 mpnt->vm_end = TASK_SIZE;
60 mpnt->vm_page_prot = PAGE_PRIVATE|PAGE_DIRTY;
61 mpnt->vm_share = NULL;
62 mpnt->vm_inode = NULL;
63 mpnt->vm_offset = 0;
64 mpnt->vm_ops = NULL;
65 insert_vm_struct(current, mpnt);
66 current->mm->stk_vma = mpnt;
67 }
68 sp = (unsigned long *) (0xfffffffc & (unsigned long) p);
69 if(exec) sp -= DLINFO_ITEMS*2;
70 dlinfo = sp;
71 sp -= envc+1;
72 envp = sp;
73 sp -= argc+1;
74 argv = sp;
75 if (!ibcs) {
76 put_fs_long((unsigned long)envp,--sp);
77 put_fs_long((unsigned long)argv,--sp);
78 }
79
80
81
82
83 if(exec) {
84 struct elf_phdr * eppnt;
85 eppnt = (struct elf_phdr *) exec->e_phoff;
86 put_fs_long(3,dlinfo++); put_fs_long(load_addr + exec->e_phoff,dlinfo++);
87 put_fs_long(4,dlinfo++); put_fs_long(sizeof(struct elf_phdr),dlinfo++);
88 put_fs_long(5,dlinfo++); put_fs_long(exec->e_phnum,dlinfo++);
89 put_fs_long(9,dlinfo++); put_fs_long((unsigned long) exec->e_entry,dlinfo++);
90 put_fs_long(7,dlinfo++); put_fs_long(SHM_RANGE_START,dlinfo++);
91 put_fs_long(8,dlinfo++); put_fs_long(0,dlinfo++);
92 put_fs_long(6,dlinfo++); put_fs_long(PAGE_SIZE,dlinfo++);
93 put_fs_long(0,dlinfo++); put_fs_long(0,dlinfo++);
94 };
95
96 put_fs_long((unsigned long)argc,--sp);
97 current->mm->arg_start = (unsigned long) p;
98 while (argc-->0) {
99 put_fs_long((unsigned long) p,argv++);
100 while (get_fs_byte(p++)) ;
101 }
102 put_fs_long(0,argv);
103 current->mm->arg_end = current->mm->env_start = (unsigned long) p;
104 while (envc-->0) {
105 put_fs_long((unsigned long) p,envp++);
106 while (get_fs_byte(p++)) ;
107 }
108 put_fs_long(0,envp);
109 current->mm->env_end = (unsigned long) p;
110 return sp;
111 }
112
113
114
115
116
117
118
119 static unsigned int load_elf_interp(struct elfhdr * interp_elf_ex,
120 struct inode * interpreter_inode)
121 {
122 struct file * file;
123 struct elf_phdr *elf_phdata = NULL;
124 struct elf_phdr *eppnt;
125 unsigned int len;
126 unsigned int load_addr;
127 int elf_exec_fileno;
128 int elf_bss;
129 int old_fs, retval;
130 unsigned int last_bss;
131 int error;
132 int i, k;
133
134 elf_bss = 0;
135 last_bss = 0;
136 error = load_addr = 0;
137
138
139 if((interp_elf_ex->e_type != ET_EXEC &&
140 interp_elf_ex->e_type != ET_DYN) ||
141 (interp_elf_ex->e_machine != EM_386 && interp_elf_ex->e_machine != EM_486) ||
142 (!interpreter_inode->i_op || !interpreter_inode->i_op->bmap ||
143 !interpreter_inode->i_op->default_file_ops->mmap)){
144 return 0xffffffff;
145 };
146
147
148
149 if(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > PAGE_SIZE)
150 return 0xffffffff;
151
152 elf_phdata = (struct elf_phdr *)
153 kmalloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum, GFP_KERNEL);
154 if(!elf_phdata) return 0xffffffff;
155
156 old_fs = get_fs();
157 set_fs(get_ds());
158 retval = read_exec(interpreter_inode, interp_elf_ex->e_phoff, (char *) elf_phdata,
159 sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
160 set_fs(old_fs);
161
162 elf_exec_fileno = open_inode(interpreter_inode, O_RDONLY);
163 if (elf_exec_fileno < 0) return 0xffffffff;
164 file = current->files->fd[elf_exec_fileno];
165
166 eppnt = elf_phdata;
167 for(i=0; i<interp_elf_ex->e_phnum; i++, eppnt++)
168 if(eppnt->p_type == PT_LOAD) {
169 error = do_mmap(file,
170 eppnt->p_vaddr & 0xfffff000,
171 eppnt->p_filesz + (eppnt->p_vaddr & 0xfff),
172 PROT_READ | PROT_WRITE | PROT_EXEC,
173 MAP_PRIVATE | (interp_elf_ex->e_type == ET_EXEC ? MAP_FIXED : 0),
174 eppnt->p_offset & 0xfffff000);
175
176 if(!load_addr && interp_elf_ex->e_type == ET_DYN)
177 load_addr = error;
178 k = load_addr + eppnt->p_vaddr + eppnt->p_filesz;
179 if(k > elf_bss) elf_bss = k;
180 if(error < 0 && error > -1024) break;
181 k = load_addr + eppnt->p_memsz + eppnt->p_vaddr;
182 if(k > last_bss) last_bss = k;
183 }
184
185
186
187
188 sys_close(elf_exec_fileno);
189 if(error < 0 && error > -1024) {
190 kfree(elf_phdata);
191 return 0xffffffff;
192 }
193
194 padzero(elf_bss);
195 len = (elf_bss + 0xfff) & 0xfffff000;
196
197
198 if (last_bss > len)
199 do_mmap(NULL, len, last_bss-len,
200 PROT_READ|PROT_WRITE|PROT_EXEC,
201 MAP_FIXED|MAP_PRIVATE, 0);
202 kfree(elf_phdata);
203
204 return ((unsigned int) interp_elf_ex->e_entry) + load_addr;
205 }
206
207 static unsigned int load_aout_interp(struct exec * interp_ex,
208 struct inode * interpreter_inode)
209 {
210 int retval;
211 unsigned int elf_entry;
212
213 current->mm->brk = interp_ex->a_bss +
214 (current->mm->end_data = interp_ex->a_data +
215 (current->mm->end_code = interp_ex->a_text));
216 elf_entry = interp_ex->a_entry;
217
218
219 if (N_MAGIC(*interp_ex) == OMAGIC) {
220 do_mmap(NULL, 0, interp_ex->a_text+interp_ex->a_data,
221 PROT_READ|PROT_WRITE|PROT_EXEC,
222 MAP_FIXED|MAP_PRIVATE, 0);
223 retval = read_exec(interpreter_inode, 32, (char *) 0,
224 interp_ex->a_text+interp_ex->a_data);
225 } else if (N_MAGIC(*interp_ex) == ZMAGIC || N_MAGIC(*interp_ex) == QMAGIC) {
226 do_mmap(NULL, 0, interp_ex->a_text+interp_ex->a_data,
227 PROT_READ|PROT_WRITE|PROT_EXEC,
228 MAP_FIXED|MAP_PRIVATE, 0);
229 retval = read_exec(interpreter_inode,
230 N_TXTOFF(*interp_ex) ,
231 (char *) N_TXTADDR(*interp_ex),
232 interp_ex->a_text+interp_ex->a_data);
233 } else
234 retval = -1;
235
236 if(retval >= 0)
237 do_mmap(NULL, (interp_ex->a_text + interp_ex->a_data + 0xfff) &
238 0xfffff000, interp_ex->a_bss,
239 PROT_READ|PROT_WRITE|PROT_EXEC,
240 MAP_FIXED|MAP_PRIVATE, 0);
241 if(retval < 0) return 0xffffffff;
242 return elf_entry;
243 }
244
245
246
247
248
249
250 #define INTERPRETER_NONE 0
251 #define INTERPRETER_AOUT 1
252 #define INTERPRETER_ELF 2
253
254 int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
255 {
256 struct elfhdr elf_ex;
257 struct elfhdr interp_elf_ex;
258 struct file * file;
259 struct exec interp_ex;
260 struct inode *interpreter_inode;
261 unsigned int load_addr;
262 unsigned int interpreter_type = INTERPRETER_NONE;
263 int i;
264 int old_fs;
265 int error;
266 struct elf_phdr * elf_ppnt, *elf_phdata;
267 int elf_exec_fileno;
268 unsigned int elf_bss, k, elf_brk;
269 int retval;
270 char * elf_interpreter;
271 unsigned int elf_entry;
272 int status;
273 unsigned int start_code, end_code, end_data;
274 unsigned int elf_stack;
275 char passed_fileno[6];
276
277 status = 0;
278 load_addr = 0;
279 elf_ex = *((struct elfhdr *) bprm->buf);
280
281 if (elf_ex.e_ident[0] != 0x7f ||
282 strncmp(&elf_ex.e_ident[1], "ELF",3) != 0)
283 return -ENOEXEC;
284
285
286
287 if(elf_ex.e_type != ET_EXEC ||
288 (elf_ex.e_machine != EM_386 && elf_ex.e_machine != EM_486) ||
289 (!bprm->inode->i_op || !bprm->inode->i_op->default_file_ops ||
290 !bprm->inode->i_op->default_file_ops->mmap)){
291 return -ENOEXEC;
292 };
293
294
295
296 elf_phdata = (struct elf_phdr *) kmalloc(elf_ex.e_phentsize *
297 elf_ex.e_phnum, GFP_KERNEL);
298
299 old_fs = get_fs();
300 set_fs(get_ds());
301 retval = read_exec(bprm->inode, elf_ex.e_phoff, (char *) elf_phdata,
302 elf_ex.e_phentsize * elf_ex.e_phnum);
303 set_fs(old_fs);
304 if (retval < 0) {
305 kfree (elf_phdata);
306 return retval;
307 }
308
309 elf_ppnt = elf_phdata;
310
311 elf_bss = 0;
312 elf_brk = 0;
313
314 elf_exec_fileno = open_inode(bprm->inode, O_RDONLY);
315
316 if (elf_exec_fileno < 0) {
317 kfree (elf_phdata);
318 return elf_exec_fileno;
319 }
320
321 file = current->files->fd[elf_exec_fileno];
322
323 elf_stack = 0xffffffff;
324 elf_interpreter = NULL;
325 start_code = 0;
326 end_code = 0;
327 end_data = 0;
328
329 old_fs = get_fs();
330 set_fs(get_ds());
331
332 for(i=0;i < elf_ex.e_phnum; i++){
333 if(elf_ppnt->p_type == PT_INTERP) {
334
335
336
337 elf_interpreter = (char *) kmalloc(elf_ppnt->p_filesz,
338 GFP_KERNEL);
339
340 retval = read_exec(bprm->inode,elf_ppnt->p_offset,elf_interpreter,
341 elf_ppnt->p_filesz);
342 #if 0
343 printk("Using ELF interpreter %s\n", elf_interpreter);
344 #endif
345 if(retval >= 0)
346 retval = namei(elf_interpreter, &interpreter_inode);
347 if(retval >= 0)
348 retval = read_exec(interpreter_inode,0,bprm->buf,128);
349
350 if(retval >= 0){
351 interp_ex = *((struct exec *) bprm->buf);
352 interp_elf_ex = *((struct elfhdr *) bprm->buf);
353
354 };
355 if(retval < 0) {
356 kfree (elf_phdata);
357 kfree(elf_interpreter);
358 return retval;
359 };
360 };
361 elf_ppnt++;
362 };
363
364 set_fs(old_fs);
365
366
367 if(elf_interpreter){
368 interpreter_type = INTERPRETER_ELF | INTERPRETER_AOUT;
369 if(retval < 0) {
370 kfree(elf_interpreter);
371 kfree(elf_phdata);
372 return -ELIBACC;
373 };
374
375 if((N_MAGIC(interp_ex) != OMAGIC) &&
376 (N_MAGIC(interp_ex) != ZMAGIC) &&
377 (N_MAGIC(interp_ex) != QMAGIC))
378 interpreter_type = INTERPRETER_ELF;
379
380 if (interp_elf_ex.e_ident[0] != 0x7f ||
381 strncmp(&interp_elf_ex.e_ident[1], "ELF",3) != 0)
382 interpreter_type &= ~INTERPRETER_ELF;
383
384 if(!interpreter_type)
385 {
386 kfree(elf_interpreter);
387 kfree(elf_phdata);
388 return -ELIBBAD;
389 };
390 }
391
392
393
394
395 if (!bprm->sh_bang) {
396 char * passed_p;
397
398 if(interpreter_type == INTERPRETER_AOUT) {
399 sprintf(passed_fileno, "%d", elf_exec_fileno);
400 passed_p = passed_fileno;
401
402 if(elf_interpreter) {
403 bprm->p = copy_strings(1,&passed_p,bprm->page,bprm->p,2);
404 bprm->argc++;
405 };
406 };
407 if (!bprm->p) {
408 if(elf_interpreter) {
409 kfree(elf_interpreter);
410 }
411 kfree (elf_phdata);
412 return -E2BIG;
413 }
414 }
415
416
417 flush_old_exec(bprm);
418
419 current->mm->end_data = 0;
420 current->mm->end_code = 0;
421 current->mm->start_mmap = ELF_START_MMAP;
422 current->mm->mmap = NULL;
423 elf_entry = (unsigned int) elf_ex.e_entry;
424
425
426
427 current->mm->rss = 0;
428 bprm->p += change_ldt(0, bprm->page);
429 current->mm->start_stack = bprm->p;
430
431
432
433
434
435
436 old_fs = get_fs();
437 set_fs(get_ds());
438
439 elf_ppnt = elf_phdata;
440 for(i=0;i < elf_ex.e_phnum; i++){
441
442 if(elf_ppnt->p_type == PT_INTERP) {
443
444
445 set_fs(old_fs);
446
447 if(interpreter_type & 1) elf_entry =
448 load_aout_interp(&interp_ex, interpreter_inode);
449
450 if(interpreter_type & 2) elf_entry =
451 load_elf_interp(&interp_elf_ex, interpreter_inode);
452
453 old_fs = get_fs();
454 set_fs(get_ds());
455
456 iput(interpreter_inode);
457 kfree(elf_interpreter);
458
459 if(elf_entry == 0xffffffff) {
460 printk("Unable to load interpreter\n");
461 kfree(elf_phdata);
462 send_sig(SIGSEGV, current, 0);
463 return 0;
464 };
465 };
466
467
468 if(elf_ppnt->p_type == PT_LOAD) {
469 error = do_mmap(file,
470 elf_ppnt->p_vaddr & 0xfffff000,
471 elf_ppnt->p_filesz + (elf_ppnt->p_vaddr & 0xfff),
472 PROT_READ | PROT_WRITE | PROT_EXEC,
473 MAP_FIXED | MAP_PRIVATE,
474 elf_ppnt->p_offset & 0xfffff000);
475
476 #ifdef LOW_ELF_STACK
477 if(elf_ppnt->p_vaddr & 0xfffff000 < elf_stack)
478 elf_stack = elf_ppnt->p_vaddr & 0xfffff000;
479 #endif
480
481 if(!load_addr)
482 load_addr = elf_ppnt->p_vaddr - elf_ppnt->p_offset;
483 k = elf_ppnt->p_vaddr;
484 if(k > start_code) start_code = k;
485 k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
486 if(k > elf_bss) elf_bss = k;
487 if((elf_ppnt->p_flags | PROT_WRITE) && end_code < k)
488 end_code = k;
489 if(end_data < k) end_data = k;
490 k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz;
491 if(k > elf_brk) elf_brk = k;
492 };
493 elf_ppnt++;
494 };
495 set_fs(old_fs);
496
497 kfree(elf_phdata);
498
499 if(!elf_interpreter) sys_close(elf_exec_fileno);
500 current->elf_executable = 1;
501 current->executable = bprm->inode;
502 bprm->inode->i_count++;
503 #ifdef LOW_ELF_STACK
504 current->start_stack = p = elf_stack - 4;
505 #endif
506 bprm->p -= MAX_ARG_PAGES*PAGE_SIZE;
507 bprm->p = (unsigned long)
508 create_elf_tables((char *)bprm->p,
509 bprm->argc,
510 bprm->envc,
511 (interpreter_type == INTERPRETER_ELF ? &elf_ex : NULL),
512 load_addr,
513 (interpreter_type == INTERPRETER_AOUT ? 0 : 1));
514 if(interpreter_type == INTERPRETER_AOUT)
515 current->mm->arg_start += strlen(passed_fileno) + 1;
516 current->mm->start_brk = current->mm->brk = elf_brk;
517 current->mm->end_code = end_code;
518 current->mm->start_code = start_code;
519 current->mm->end_data = end_data;
520 current->mm->start_stack = bprm->p;
521 current->suid = current->euid = bprm->e_uid;
522 current->sgid = current->egid = bprm->e_gid;
523
524
525
526 current->mm->brk = (elf_bss + 0xfff) & 0xfffff000;
527 sys_brk((elf_brk + 0xfff) & 0xfffff000);
528
529 padzero(elf_bss);
530
531
532
533
534
535 error = do_mmap(NULL, 0, 4096, PROT_READ | PROT_EXEC,
536 MAP_FIXED | MAP_PRIVATE, 0);
537
538 regs->eip = elf_entry;
539 regs->esp = bprm->p;
540 if (current->flags & PF_PTRACED)
541 send_sig(SIGTRAP, current, 0);
542 return 0;
543 }
544
545
546
547
548 int load_elf_library(int fd){
549 struct file * file;
550 struct elfhdr elf_ex;
551 struct elf_phdr *elf_phdata = NULL;
552 struct inode * inode;
553 unsigned int len;
554 int elf_bss;
555 int old_fs, retval;
556 unsigned int bss;
557 int error;
558 int i,j, k;
559
560 len = 0;
561 file = current->files->fd[fd];
562 inode = file->f_inode;
563 elf_bss = 0;
564
565 set_fs(KERNEL_DS);
566 if (file->f_op->read(inode, file, (char *) &elf_ex, sizeof(elf_ex)) != sizeof(elf_ex)) {
567 sys_close(fd);
568 return -EACCES;
569 }
570 set_fs(USER_DS);
571
572 if (elf_ex.e_ident[0] != 0x7f ||
573 strncmp(&elf_ex.e_ident[1], "ELF",3) != 0)
574 return -ENOEXEC;
575
576
577 if(elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 ||
578 (elf_ex.e_machine != EM_386 && elf_ex.e_machine != EM_486) ||
579 (!inode->i_op || !inode->i_op->bmap ||
580 !inode->i_op->default_file_ops->mmap)){
581 return -ENOEXEC;
582 };
583
584
585
586 if(sizeof(struct elf_phdr) * elf_ex.e_phnum > PAGE_SIZE)
587 return -ENOEXEC;
588
589 elf_phdata = (struct elf_phdr *)
590 kmalloc(sizeof(struct elf_phdr) * elf_ex.e_phnum, GFP_KERNEL);
591
592 old_fs = get_fs();
593 set_fs(get_ds());
594 retval = read_exec(inode, elf_ex.e_phoff, (char *) elf_phdata,
595 sizeof(struct elf_phdr) * elf_ex.e_phnum);
596 set_fs(old_fs);
597
598 j = 0;
599 for(i=0; i<elf_ex.e_phnum; i++)
600 if((elf_phdata + i)->p_type == PT_LOAD) j++;
601
602 if(j != 1) {
603 kfree(elf_phdata);
604 return -ENOEXEC;
605 };
606
607 while(elf_phdata->p_type != PT_LOAD) elf_phdata++;
608
609
610 error = do_mmap(file,
611 elf_phdata->p_vaddr & 0xfffff000,
612 elf_phdata->p_filesz + (elf_phdata->p_vaddr & 0xfff),
613 PROT_READ | PROT_WRITE | PROT_EXEC,
614 MAP_FIXED | MAP_PRIVATE,
615 elf_phdata->p_offset & 0xfffff000);
616
617 k = elf_phdata->p_vaddr + elf_phdata->p_filesz;
618 if(k > elf_bss) elf_bss = k;
619
620 sys_close(fd);
621 if (error != elf_phdata->p_vaddr & 0xfffff000) {
622 kfree(elf_phdata);
623 return error;
624 }
625
626 padzero(elf_bss);
627
628 len = (elf_phdata->p_filesz + elf_phdata->p_vaddr+ 0xfff) & 0xfffff000;
629 bss = elf_phdata->p_memsz + elf_phdata->p_vaddr;
630 if (bss > len)
631 do_mmap(NULL, len, bss-len,
632 PROT_READ|PROT_WRITE|PROT_EXEC,
633 MAP_FIXED|MAP_PRIVATE, 0);
634 kfree(elf_phdata);
635 return 0;
636 }