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