1
2
3
4
5
6
7
8
9
10
11
12#include <linux/module.h>
13
14#include <linux/fs.h>
15#include <linux/stat.h>
16#include <linux/sched.h>
17#include <linux/mm.h>
18#include <linux/mman.h>
19#include <linux/a.out.h>
20#include <linux/errno.h>
21#include <linux/signal.h>
22#include <linux/binfmts.h>
23#include <linux/string.h>
24#include <linux/file.h>
25#include <linux/fcntl.h>
26#include <linux/ptrace.h>
27#include <linux/slab.h>
28#include <linux/shm.h>
29#include <linux/personality.h>
30#include <linux/elfcore.h>
31#include <linux/init.h>
32#include <linux/highuid.h>
33#include <linux/smp_lock.h>
34#include <linux/compiler.h>
35#include <linux/highmem.h>
36
37#include <asm/uaccess.h>
38#include <asm/param.h>
39#include <asm/pgalloc.h>
40
41#define DLINFO_ITEMS 13
42
43#include <linux/elf.h>
44
45static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs);
46static int load_elf_library(struct file*);
47static unsigned long elf_map (struct file *, unsigned long, struct elf_phdr *, int, int);
48extern int dump_fpu (struct pt_regs *, elf_fpregset_t *);
49extern void dump_thread(struct pt_regs *, struct user *);
50
51#ifndef elf_addr_t
52#define elf_addr_t unsigned long
53#define elf_caddr_t char *
54#endif
55
56
57
58
59
60#ifdef USE_ELF_CORE_DUMP
61static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file);
62#else
63#define elf_core_dump NULL
64#endif
65
66#if ELF_EXEC_PAGESIZE > PAGE_SIZE
67# define ELF_MIN_ALIGN ELF_EXEC_PAGESIZE
68#else
69# define ELF_MIN_ALIGN PAGE_SIZE
70#endif
71
72#define ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(ELF_MIN_ALIGN-1))
73#define ELF_PAGEOFFSET(_v) ((_v) & (ELF_MIN_ALIGN-1))
74#define ELF_PAGEALIGN(_v) (((_v) + ELF_MIN_ALIGN - 1) & ~(ELF_MIN_ALIGN - 1))
75
76static struct linux_binfmt elf_format = {
77 NULL, THIS_MODULE, load_elf_binary, load_elf_library, elf_core_dump, ELF_EXEC_PAGESIZE
78};
79
80#define BAD_ADDR(x) ((unsigned long)(x) > TASK_SIZE)
81
82static void set_brk(unsigned long start, unsigned long end)
83{
84 start = ELF_PAGEALIGN(start);
85 end = ELF_PAGEALIGN(end);
86 if (end <= start)
87 return;
88 do_brk(start, end - start);
89}
90
91
92
93
94
95
96
97
98static void padzero(unsigned long elf_bss)
99{
100 unsigned long nbyte;
101
102 nbyte = ELF_PAGEOFFSET(elf_bss);
103 if (nbyte) {
104 nbyte = ELF_MIN_ALIGN - nbyte;
105 clear_user((void *) elf_bss, nbyte);
106 }
107}
108
109static elf_addr_t *
110create_elf_tables(char *p, int argc, int envc,
111 struct elfhdr * exec,
112 unsigned long load_addr,
113 unsigned long load_bias,
114 unsigned long interp_load_addr, int ibcs)
115{
116 elf_caddr_t *argv;
117 elf_caddr_t *envp;
118 elf_addr_t *sp, *csp;
119 char *k_platform, *u_platform;
120 long hwcap;
121 size_t platform_len = 0;
122 size_t len;
123
124
125
126
127
128
129
130
131 hwcap = ELF_HWCAP;
132 k_platform = ELF_PLATFORM;
133
134 if (k_platform) {
135 platform_len = strlen(k_platform) + 1;
136 u_platform = p - platform_len;
137 __copy_to_user(u_platform, k_platform, platform_len);
138 } else
139 u_platform = p;
140
141#if defined(__i386__) && defined(CONFIG_SMP)
142
143
144
145
146
147
148
149
150
151
152
153 if(smp_num_siblings > 1)
154 u_platform = u_platform - ((current->pid % 64) << 7);
155#endif
156
157
158
159
160 sp = (elf_addr_t *)(~15UL & (unsigned long)(u_platform));
161 csp = sp;
162 csp -= (1+DLINFO_ITEMS)*2 + (k_platform ? 2 : 0);
163#ifdef DLINFO_ARCH_ITEMS
164 csp -= DLINFO_ARCH_ITEMS*2;
165#endif
166 csp -= envc+1;
167 csp -= argc+1;
168 csp -= (!ibcs ? 3 : 1);
169 if ((unsigned long)csp & 15UL)
170 sp -= ((unsigned long)csp & 15UL) / sizeof(*sp);
171
172
173
174
175#define NEW_AUX_ENT(nr, id, val) \
176 __put_user ((id), sp+(nr*2)); \
177 __put_user ((val), sp+(nr*2+1)); \
178
179 sp -= 2;
180 NEW_AUX_ENT(0, AT_NULL, 0);
181 if (k_platform) {
182 sp -= 2;
183 NEW_AUX_ENT(0, AT_PLATFORM, (elf_addr_t)(unsigned long) u_platform);
184 }
185 sp -= DLINFO_ITEMS*2;
186 NEW_AUX_ENT( 0, AT_HWCAP, hwcap);
187 NEW_AUX_ENT( 1, AT_PAGESZ, ELF_EXEC_PAGESIZE);
188 NEW_AUX_ENT( 2, AT_CLKTCK, CLOCKS_PER_SEC);
189 NEW_AUX_ENT( 3, AT_PHDR, load_addr + exec->e_phoff);
190 NEW_AUX_ENT( 4, AT_PHENT, sizeof (struct elf_phdr));
191 NEW_AUX_ENT( 5, AT_PHNUM, exec->e_phnum);
192 NEW_AUX_ENT( 6, AT_BASE, interp_load_addr);
193 NEW_AUX_ENT( 7, AT_FLAGS, 0);
194 NEW_AUX_ENT( 8, AT_ENTRY, load_bias + exec->e_entry);
195 NEW_AUX_ENT( 9, AT_UID, (elf_addr_t) current->uid);
196 NEW_AUX_ENT(10, AT_EUID, (elf_addr_t) current->euid);
197 NEW_AUX_ENT(11, AT_GID, (elf_addr_t) current->gid);
198 NEW_AUX_ENT(12, AT_EGID, (elf_addr_t) current->egid);
199#ifdef ARCH_DLINFO
200
201
202
203
204 ARCH_DLINFO;
205#endif
206#undef NEW_AUX_ENT
207
208 sp -= envc+1;
209 envp = (elf_caddr_t *) sp;
210 sp -= argc+1;
211 argv = (elf_caddr_t *) sp;
212 if (!ibcs) {
213 __put_user((elf_addr_t)(unsigned long) envp,--sp);
214 __put_user((elf_addr_t)(unsigned long) argv,--sp);
215 }
216
217 __put_user((elf_addr_t)argc,--sp);
218 current->mm->arg_start = (unsigned long) p;
219 while (argc-->0) {
220 __put_user((elf_caddr_t)(unsigned long)p,argv++);
221 len = strnlen_user(p, PAGE_SIZE*MAX_ARG_PAGES);
222 if (!len || len > PAGE_SIZE*MAX_ARG_PAGES)
223 return NULL;
224 p += len;
225 }
226 __put_user(NULL, argv);
227 current->mm->arg_end = current->mm->env_start = (unsigned long) p;
228 while (envc-->0) {
229 __put_user((elf_caddr_t)(unsigned long)p,envp++);
230 len = strnlen_user(p, PAGE_SIZE*MAX_ARG_PAGES);
231 if (!len || len > PAGE_SIZE*MAX_ARG_PAGES)
232 return NULL;
233 p += len;
234 }
235 __put_user(NULL, envp);
236 current->mm->env_end = (unsigned long) p;
237 return sp;
238}
239
240#ifndef elf_map
241
242static inline unsigned long
243elf_map (struct file *filep, unsigned long addr, struct elf_phdr *eppnt, int prot, int type)
244{
245 unsigned long map_addr;
246
247 down_write(¤t->mm->mmap_sem);
248 map_addr = do_mmap(filep, ELF_PAGESTART(addr),
249 eppnt->p_filesz + ELF_PAGEOFFSET(eppnt->p_vaddr), prot, type,
250 eppnt->p_offset - ELF_PAGEOFFSET(eppnt->p_vaddr));
251 up_write(¤t->mm->mmap_sem);
252 return(map_addr);
253}
254
255#endif
256
257
258
259
260
261
262static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex,
263 struct file * interpreter,
264 unsigned long *interp_load_addr)
265{
266 struct elf_phdr *elf_phdata;
267 struct elf_phdr *eppnt;
268 unsigned long load_addr = 0;
269 int load_addr_set = 0;
270 unsigned long last_bss = 0, elf_bss = 0;
271 unsigned long error = ~0UL;
272 int retval, i, size;
273
274
275 if (interp_elf_ex->e_type != ET_EXEC &&
276 interp_elf_ex->e_type != ET_DYN)
277 goto out;
278 if (!elf_check_arch(interp_elf_ex))
279 goto out;
280 if (!interpreter->f_op || !interpreter->f_op->mmap)
281 goto out;
282
283
284
285
286
287 if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr))
288 goto out;
289 if (interp_elf_ex->e_phnum > 65536U / sizeof(struct elf_phdr))
290 goto out;
291
292
293
294 size = sizeof(struct elf_phdr) * interp_elf_ex->e_phnum;
295 if (size > ELF_MIN_ALIGN)
296 goto out;
297 elf_phdata = (struct elf_phdr *) kmalloc(size, GFP_KERNEL);
298 if (!elf_phdata)
299 goto out;
300
301 retval = kernel_read(interpreter,interp_elf_ex->e_phoff,(char *)elf_phdata,size);
302 error = retval;
303 if (retval < 0)
304 goto out_close;
305
306 eppnt = elf_phdata;
307 for (i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) {
308 if (eppnt->p_type == PT_LOAD) {
309 int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
310 int elf_prot = 0;
311 unsigned long vaddr = 0;
312 unsigned long k, map_addr;
313
314 if (eppnt->p_flags & PF_R) elf_prot = PROT_READ;
315 if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
316 if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
317 vaddr = eppnt->p_vaddr;
318 if (interp_elf_ex->e_type == ET_EXEC || load_addr_set)
319 elf_type |= MAP_FIXED;
320
321 map_addr = elf_map(interpreter, load_addr + vaddr, eppnt, elf_prot, elf_type);
322 if (BAD_ADDR(map_addr))
323 goto out_close;
324
325 if (!load_addr_set && interp_elf_ex->e_type == ET_DYN) {
326 load_addr = map_addr - ELF_PAGESTART(vaddr);
327 load_addr_set = 1;
328 }
329
330
331
332
333
334 k = load_addr + eppnt->p_vaddr + eppnt->p_filesz;
335 if (k > elf_bss)
336 elf_bss = k;
337
338
339
340
341
342 k = load_addr + eppnt->p_memsz + eppnt->p_vaddr;
343 if (k > last_bss)
344 last_bss = k;
345 }
346 }
347
348
349
350
351
352
353
354
355
356 padzero(elf_bss);
357 elf_bss = ELF_PAGESTART(elf_bss + ELF_MIN_ALIGN - 1);
358
359
360 if (last_bss > elf_bss)
361 do_brk(elf_bss, last_bss - elf_bss);
362
363 *interp_load_addr = load_addr;
364 error = ((unsigned long) interp_elf_ex->e_entry) + load_addr;
365
366out_close:
367 kfree(elf_phdata);
368out:
369 return error;
370}
371
372static unsigned long load_aout_interp(struct exec * interp_ex,
373 struct file * interpreter)
374{
375 unsigned long text_data, elf_entry = ~0UL;
376 char * addr;
377 loff_t offset;
378 int retval;
379
380 current->mm->end_code = interp_ex->a_text;
381 text_data = interp_ex->a_text + interp_ex->a_data;
382 current->mm->end_data = text_data;
383 current->mm->brk = interp_ex->a_bss + text_data;
384
385 switch (N_MAGIC(*interp_ex)) {
386 case OMAGIC:
387 offset = 32;
388 addr = (char *) 0;
389 break;
390 case ZMAGIC:
391 case QMAGIC:
392 offset = N_TXTOFF(*interp_ex);
393 addr = (char *) N_TXTADDR(*interp_ex);
394 break;
395 default:
396 goto out;
397 }
398
399 do_brk(0, text_data);
400 retval = -ENOEXEC;
401 if (!interpreter->f_op || !interpreter->f_op->read)
402 goto out;
403 retval = interpreter->f_op->read(interpreter, addr, text_data, &offset);
404 if (retval < 0)
405 goto out;
406 flush_icache_range((unsigned long)addr,
407 (unsigned long)addr + text_data);
408
409 do_brk(ELF_PAGESTART(text_data + ELF_MIN_ALIGN - 1),
410 interp_ex->a_bss);
411 elf_entry = interp_ex->a_entry;
412
413out:
414 return elf_entry;
415}
416
417
418
419
420
421
422#define INTERPRETER_NONE 0
423#define INTERPRETER_AOUT 1
424#define INTERPRETER_ELF 2
425
426
427static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
428{
429 struct file *interpreter = NULL;
430 unsigned long load_addr = 0, load_bias = 0;
431 int load_addr_set = 0;
432 char * elf_interpreter = NULL;
433 unsigned int interpreter_type = INTERPRETER_NONE;
434 unsigned char ibcs2_interpreter = 0;
435 unsigned long error;
436 struct elf_phdr * elf_ppnt, *elf_phdata;
437 unsigned long elf_bss, k, elf_brk;
438 int elf_exec_fileno;
439 int retval, i;
440 unsigned int size;
441 unsigned long elf_entry, interp_load_addr = 0;
442 unsigned long start_code, end_code, start_data, end_data;
443 struct elfhdr elf_ex;
444 struct elfhdr interp_elf_ex;
445 struct exec interp_ex;
446 char passed_fileno[6];
447
448
449 elf_ex = *((struct elfhdr *) bprm->buf);
450
451 retval = -ENOEXEC;
452
453 if (memcmp(elf_ex.e_ident, ELFMAG, SELFMAG) != 0)
454 goto out;
455
456 if (elf_ex.e_type != ET_EXEC && elf_ex.e_type != ET_DYN)
457 goto out;
458 if (!elf_check_arch(&elf_ex))
459 goto out;
460 if (!bprm->file->f_op||!bprm->file->f_op->mmap)
461 goto out;
462
463
464
465 retval = -ENOMEM;
466 if (elf_ex.e_phentsize != sizeof(struct elf_phdr))
467 goto out;
468 if (elf_ex.e_phnum > 65536U / sizeof(struct elf_phdr))
469 goto out;
470 size = elf_ex.e_phnum * sizeof(struct elf_phdr);
471 elf_phdata = (struct elf_phdr *) kmalloc(size, GFP_KERNEL);
472 if (!elf_phdata)
473 goto out;
474
475 retval = kernel_read(bprm->file, elf_ex.e_phoff, (char *) elf_phdata, size);
476 if (retval < 0)
477 goto out_free_ph;
478
479 retval = get_unused_fd();
480 if (retval < 0)
481 goto out_free_ph;
482 get_file(bprm->file);
483 fd_install(elf_exec_fileno = retval, bprm->file);
484
485 elf_ppnt = elf_phdata;
486 elf_bss = 0;
487 elf_brk = 0;
488
489 start_code = ~0UL;
490 end_code = 0;
491 start_data = 0;
492 end_data = 0;
493
494 for (i = 0; i < elf_ex.e_phnum; i++) {
495 if (elf_ppnt->p_type == PT_INTERP) {
496
497
498
499
500
501 retval = -ENOMEM;
502 if (elf_ppnt->p_filesz > PATH_MAX)
503 goto out_free_file;
504 elf_interpreter = (char *) kmalloc(elf_ppnt->p_filesz,
505 GFP_KERNEL);
506 if (!elf_interpreter)
507 goto out_free_file;
508
509 retval = kernel_read(bprm->file, elf_ppnt->p_offset,
510 elf_interpreter,
511 elf_ppnt->p_filesz);
512 if (retval < 0)
513 goto out_free_interp;
514
515
516
517
518 if (strcmp(elf_interpreter,"/usr/lib/libc.so.1") == 0 ||
519 strcmp(elf_interpreter,"/usr/lib/ld.so.1") == 0)
520 ibcs2_interpreter = 1;
521#if 0
522 printk("Using ELF interpreter %s\n", elf_interpreter);
523#endif
524
525 SET_PERSONALITY(elf_ex, ibcs2_interpreter);
526
527 interpreter = open_exec(elf_interpreter);
528 retval = PTR_ERR(interpreter);
529 if (IS_ERR(interpreter))
530 goto out_free_interp;
531 retval = kernel_read(interpreter, 0, bprm->buf, BINPRM_BUF_SIZE);
532 if (retval < 0)
533 goto out_free_dentry;
534
535
536 interp_ex = *((struct exec *) bprm->buf);
537 interp_elf_ex = *((struct elfhdr *) bprm->buf);
538 break;
539 }
540 elf_ppnt++;
541 }
542
543
544 if (elf_interpreter) {
545 interpreter_type = INTERPRETER_ELF | INTERPRETER_AOUT;
546
547
548 if ((N_MAGIC(interp_ex) != OMAGIC) &&
549 (N_MAGIC(interp_ex) != ZMAGIC) &&
550 (N_MAGIC(interp_ex) != QMAGIC))
551 interpreter_type = INTERPRETER_ELF;
552
553 if (memcmp(interp_elf_ex.e_ident, ELFMAG, SELFMAG) != 0)
554 interpreter_type &= ~INTERPRETER_ELF;
555
556 retval = -ELIBBAD;
557 if (!interpreter_type)
558 goto out_free_dentry;
559
560
561 if ((interpreter_type & INTERPRETER_ELF) &&
562 interpreter_type != INTERPRETER_ELF) {
563
564
565 interpreter_type = INTERPRETER_ELF;
566 }
567 } else {
568
569 SET_PERSONALITY(elf_ex, ibcs2_interpreter);
570 }
571
572
573
574
575 if (!bprm->sh_bang) {
576 char * passed_p;
577
578 if (interpreter_type == INTERPRETER_AOUT) {
579 sprintf(passed_fileno, "%d", elf_exec_fileno);
580 passed_p = passed_fileno;
581
582 if (elf_interpreter) {
583 retval = copy_strings_kernel(1,&passed_p,bprm);
584 if (retval)
585 goto out_free_dentry;
586 bprm->argc++;
587 }
588 }
589 }
590
591
592 retval = flush_old_exec(bprm);
593 if (retval)
594 goto out_free_dentry;
595
596
597 current->mm->start_data = 0;
598 current->mm->end_data = 0;
599 current->mm->end_code = 0;
600 current->mm->mmap = NULL;
601 current->flags &= ~PF_FORKNOEXEC;
602 elf_entry = (unsigned long) elf_ex.e_entry;
603
604
605
606 current->mm->rss = 0;
607 retval = setup_arg_pages(bprm);
608 if (retval < 0) {
609 send_sig(SIGKILL, current, 0);
610 return retval;
611 }
612
613 current->mm->start_stack = bprm->p;
614
615
616
617
618
619
620 for(i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) {
621 int elf_prot = 0, elf_flags;
622 unsigned long vaddr;
623
624 if (elf_ppnt->p_type != PT_LOAD)
625 continue;
626
627 if (unlikely (elf_brk > elf_bss)) {
628 unsigned long nbyte;
629
630
631
632
633 set_brk (elf_bss + load_bias, elf_brk + load_bias);
634 nbyte = ELF_PAGEOFFSET(elf_bss);
635 if (nbyte) {
636 nbyte = ELF_MIN_ALIGN - nbyte;
637 if (nbyte > elf_brk - elf_bss)
638 nbyte = elf_brk - elf_bss;
639 clear_user((void *) elf_bss + load_bias, nbyte);
640 }
641 }
642
643 if (elf_ppnt->p_flags & PF_R) elf_prot |= PROT_READ;
644 if (elf_ppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
645 if (elf_ppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
646
647 elf_flags = MAP_PRIVATE|MAP_DENYWRITE|MAP_EXECUTABLE;
648
649 vaddr = elf_ppnt->p_vaddr;
650 if (elf_ex.e_type == ET_EXEC || load_addr_set) {
651 elf_flags |= MAP_FIXED;
652 } else if (elf_ex.e_type == ET_DYN) {
653
654
655
656 load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr);
657 }
658
659 error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt, elf_prot, elf_flags);
660 if (BAD_ADDR(error))
661 continue;
662
663 if (!load_addr_set) {
664 load_addr_set = 1;
665 load_addr = (elf_ppnt->p_vaddr - elf_ppnt->p_offset);
666 if (elf_ex.e_type == ET_DYN) {
667 load_bias += error -
668 ELF_PAGESTART(load_bias + vaddr);
669 load_addr += load_bias;
670 }
671 }
672 k = elf_ppnt->p_vaddr;
673 if (k < start_code) start_code = k;
674 if (start_data < k) start_data = k;
675
676 k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
677
678 if (k > elf_bss)
679 elf_bss = k;
680 if ((elf_ppnt->p_flags & PF_X) && end_code < k)
681 end_code = k;
682 if (end_data < k)
683 end_data = k;
684 k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz;
685 if (k > elf_brk)
686 elf_brk = k;
687 }
688
689 elf_entry += load_bias;
690 elf_bss += load_bias;
691 elf_brk += load_bias;
692 start_code += load_bias;
693 end_code += load_bias;
694 start_data += load_bias;
695 end_data += load_bias;
696
697 if (elf_interpreter) {
698 if (interpreter_type == INTERPRETER_AOUT)
699 elf_entry = load_aout_interp(&interp_ex,
700 interpreter);
701 else
702 elf_entry = load_elf_interp(&interp_elf_ex,
703 interpreter,
704 &interp_load_addr);
705
706 allow_write_access(interpreter);
707 fput(interpreter);
708 kfree(elf_interpreter);
709
710 if (BAD_ADDR(elf_entry)) {
711 printk(KERN_ERR "Unable to load interpreter\n");
712 kfree(elf_phdata);
713 send_sig(SIGSEGV, current, 0);
714 return 0;
715 }
716 }
717
718 kfree(elf_phdata);
719
720 if (interpreter_type != INTERPRETER_AOUT)
721 sys_close(elf_exec_fileno);
722
723 set_binfmt(&elf_format);
724
725 compute_creds(bprm);
726 current->flags &= ~PF_FORKNOEXEC;
727 bprm->p = (unsigned long)
728 create_elf_tables((char *)bprm->p,
729 bprm->argc,
730 bprm->envc,
731 &elf_ex,
732 load_addr, load_bias,
733 interp_load_addr,
734 (interpreter_type == INTERPRETER_AOUT ? 0 : 1));
735
736 if (interpreter_type == INTERPRETER_AOUT)
737 current->mm->arg_start += strlen(passed_fileno) + 1;
738 current->mm->start_brk = current->mm->brk = elf_brk;
739 current->mm->end_code = end_code;
740 current->mm->start_code = start_code;
741 current->mm->start_data = start_data;
742 current->mm->end_data = end_data;
743 current->mm->start_stack = bprm->p;
744
745
746
747
748 set_brk(elf_bss, elf_brk);
749
750 padzero(elf_bss);
751
752#if 0
753 printk("(start_brk) %lx\n" , (long) current->mm->start_brk);
754 printk("(end_code) %lx\n" , (long) current->mm->end_code);
755 printk("(start_code) %lx\n" , (long) current->mm->start_code);
756 printk("(start_data) %lx\n" , (long) current->mm->start_data);
757 printk("(end_data) %lx\n" , (long) current->mm->end_data);
758 printk("(start_stack) %lx\n" , (long) current->mm->start_stack);
759 printk("(brk) %lx\n" , (long) current->mm->brk);
760#endif
761
762 if (current->personality & MMAP_PAGE_ZERO) {
763
764
765
766
767
768 down_write(¤t->mm->mmap_sem);
769 error = do_mmap(NULL, 0, 4096, PROT_READ | PROT_EXEC,
770 MAP_FIXED | MAP_PRIVATE, 0);
771 up_write(¤t->mm->mmap_sem);
772 }
773
774#ifdef ELF_PLAT_INIT
775
776
777
778
779
780
781 ELF_PLAT_INIT(regs);
782#endif
783
784 start_thread(regs, elf_entry, bprm->p);
785 if (current->ptrace & PT_PTRACED)
786 send_sig(SIGTRAP, current, 0);
787 retval = 0;
788out:
789 return retval;
790
791
792out_free_dentry:
793 allow_write_access(interpreter);
794 fput(interpreter);
795out_free_interp:
796 if (elf_interpreter)
797 kfree(elf_interpreter);
798out_free_file:
799 sys_close(elf_exec_fileno);
800out_free_ph:
801 kfree(elf_phdata);
802 goto out;
803}
804
805
806
807
808static int load_elf_library(struct file *file)
809{
810 struct elf_phdr *elf_phdata;
811 unsigned long elf_bss, bss, len;
812 int retval, error, i, j;
813 struct elfhdr elf_ex;
814
815 error = -ENOEXEC;
816 retval = kernel_read(file, 0, (char *) &elf_ex, sizeof(elf_ex));
817 if (retval != sizeof(elf_ex))
818 goto out;
819
820 if (memcmp(elf_ex.e_ident, ELFMAG, SELFMAG) != 0)
821 goto out;
822
823
824 if (elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 ||
825 !elf_check_arch(&elf_ex) || !file->f_op || !file->f_op->mmap)
826 goto out;
827
828
829
830 j = sizeof(struct elf_phdr) * elf_ex.e_phnum;
831
832
833 error = -ENOMEM;
834 elf_phdata = (struct elf_phdr *) kmalloc(j, GFP_KERNEL);
835 if (!elf_phdata)
836 goto out;
837
838 error = -ENOEXEC;
839 retval = kernel_read(file, elf_ex.e_phoff, (char *) elf_phdata, j);
840 if (retval != j)
841 goto out_free_ph;
842
843 for (j = 0, i = 0; i<elf_ex.e_phnum; i++)
844 if ((elf_phdata + i)->p_type == PT_LOAD) j++;
845 if (j != 1)
846 goto out_free_ph;
847
848 while (elf_phdata->p_type != PT_LOAD) elf_phdata++;
849
850
851 down_write(¤t->mm->mmap_sem);
852 error = do_mmap(file,
853 ELF_PAGESTART(elf_phdata->p_vaddr),
854 (elf_phdata->p_filesz +
855 ELF_PAGEOFFSET(elf_phdata->p_vaddr)),
856 PROT_READ | PROT_WRITE | PROT_EXEC,
857 MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
858 (elf_phdata->p_offset -
859 ELF_PAGEOFFSET(elf_phdata->p_vaddr)));
860 up_write(¤t->mm->mmap_sem);
861 if (error != ELF_PAGESTART(elf_phdata->p_vaddr))
862 goto out_free_ph;
863
864 elf_bss = elf_phdata->p_vaddr + elf_phdata->p_filesz;
865 padzero(elf_bss);
866
867 len = ELF_PAGESTART(elf_phdata->p_filesz + elf_phdata->p_vaddr + ELF_MIN_ALIGN - 1);
868 bss = elf_phdata->p_memsz + elf_phdata->p_vaddr;
869 if (bss > len)
870 do_brk(len, bss - len);
871 error = 0;
872
873out_free_ph:
874 kfree(elf_phdata);
875out:
876 return error;
877}
878
879
880
881
882
883#ifdef USE_ELF_CORE_DUMP
884
885
886
887
888
889
890
891
892
893
894
895static int dump_write(struct file *file, const void *addr, int nr)
896{
897 return file->f_op->write(file, addr, nr, &file->f_pos) == nr;
898}
899
900static int dump_seek(struct file *file, off_t off)
901{
902 if (file->f_op->llseek) {
903 if (file->f_op->llseek(file, off, 0) != off)
904 return 0;
905 } else
906 file->f_pos = off;
907 return 1;
908}
909
910
911
912
913
914
915
916
917static inline int maydump(struct vm_area_struct *vma)
918{
919
920
921
922
923 if (!(vma->vm_flags & VM_READ))
924 return 0;
925
926
927 if (vma->vm_flags & VM_IO)
928 return 0;
929#if 1
930 if (vma->vm_flags & (VM_WRITE|VM_GROWSUP|VM_GROWSDOWN))
931 return 1;
932 if (vma->vm_flags & (VM_READ|VM_EXEC|VM_EXECUTABLE|VM_SHARED))
933 return 0;
934#endif
935 return 1;
936}
937
938#define roundup(x, y) ((((x)+((y)-1))/(y))*(y))
939
940
941struct memelfnote
942{
943 const char *name;
944 int type;
945 unsigned int datasz;
946 void *data;
947};
948
949static int notesize(struct memelfnote *en)
950{
951 int sz;
952
953 sz = sizeof(struct elf_note);
954 sz += roundup(strlen(en->name), 4);
955 sz += roundup(en->datasz, 4);
956
957 return sz;
958}
959
960
961
962#ifdef DEBUG
963static void dump_regs(const char *str, elf_greg_t *r)
964{
965 int i;
966 static const char *regs[] = { "ebx", "ecx", "edx", "esi", "edi", "ebp",
967 "eax", "ds", "es", "fs", "gs",
968 "orig_eax", "eip", "cs",
969 "efl", "uesp", "ss"};
970 printk("Registers: %s\n", str);
971
972 for(i = 0; i < ELF_NGREG; i++)
973 {
974 unsigned long val = r[i];
975 printk(" %-2d %-5s=%08lx %lu\n", i, regs[i], val, val);
976 }
977}
978#endif
979
980#define DUMP_WRITE(addr, nr) \
981 do { if (!dump_write(file, (addr), (nr))) return 0; } while(0)
982#define DUMP_SEEK(off) \
983 do { if (!dump_seek(file, (off))) return 0; } while(0)
984
985static int writenote(struct memelfnote *men, struct file *file)
986{
987 struct elf_note en;
988
989 en.n_namesz = strlen(men->name);
990 en.n_descsz = men->datasz;
991 en.n_type = men->type;
992
993 DUMP_WRITE(&en, sizeof(en));
994 DUMP_WRITE(men->name, en.n_namesz);
995
996 DUMP_SEEK(roundup((unsigned long)file->f_pos, 4));
997 DUMP_WRITE(men->data, men->datasz);
998 DUMP_SEEK(roundup((unsigned long)file->f_pos, 4));
999
1000 return 1;
1001}
1002#undef DUMP_WRITE
1003#undef DUMP_SEEK
1004
1005#define DUMP_WRITE(addr, nr) \
1006 if ((size += (nr)) > limit || !dump_write(file, (addr), (nr))) \
1007 goto end_coredump;
1008#define DUMP_SEEK(off) \
1009 if (!dump_seek(file, (off))) \
1010 goto end_coredump;
1011
1012
1013
1014
1015
1016
1017
1018static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file)
1019{
1020 int has_dumped = 0;
1021 mm_segment_t fs;
1022 int segs;
1023 size_t size = 0;
1024 int i;
1025 struct vm_area_struct *vma;
1026 struct elfhdr elf;
1027 off_t offset = 0, dataoff;
1028 unsigned long limit = current->rlim[RLIMIT_CORE].rlim_cur;
1029 int numnote = 4;
1030 struct memelfnote notes[4];
1031 struct elf_prstatus prstatus;
1032 elf_fpregset_t fpu;
1033 struct elf_prpsinfo psinfo;
1034
1035
1036 memset(&psinfo, 0, sizeof(psinfo));
1037 {
1038 int i, len;
1039
1040 len = current->mm->arg_end - current->mm->arg_start;
1041 if (len >= ELF_PRARGSZ)
1042 len = ELF_PRARGSZ-1;
1043 copy_from_user(&psinfo.pr_psargs,
1044 (const char *)current->mm->arg_start, len);
1045 for(i = 0; i < len; i++)
1046 if (psinfo.pr_psargs[i] == 0)
1047 psinfo.pr_psargs[i] = ' ';
1048 psinfo.pr_psargs[len] = 0;
1049
1050 }
1051
1052 memset(&prstatus, 0, sizeof(prstatus));
1053
1054
1055
1056
1057#ifdef ELF_CORE_COPY_REGS
1058 ELF_CORE_COPY_REGS(prstatus.pr_reg, regs)
1059#else
1060 if (sizeof(elf_gregset_t) != sizeof(struct pt_regs))
1061 {
1062 printk("sizeof(elf_gregset_t) (%ld) != sizeof(struct pt_regs) (%ld)\n",
1063 (long)sizeof(elf_gregset_t), (long)sizeof(struct pt_regs));
1064 }
1065 else
1066 *(struct pt_regs *)&prstatus.pr_reg = *regs;
1067#endif
1068
1069
1070 down_write(¤t->mm->mmap_sem);
1071 segs = current->mm->map_count;
1072
1073#ifdef DEBUG
1074 printk("elf_core_dump: %d segs %lu limit\n", segs, limit);
1075#endif
1076
1077
1078 memcpy(elf.e_ident, ELFMAG, SELFMAG);
1079 elf.e_ident[EI_CLASS] = ELF_CLASS;
1080 elf.e_ident[EI_DATA] = ELF_DATA;
1081 elf.e_ident[EI_VERSION] = EV_CURRENT;
1082 memset(elf.e_ident+EI_PAD, 0, EI_NIDENT-EI_PAD);
1083
1084 elf.e_type = ET_CORE;
1085 elf.e_machine = ELF_ARCH;
1086 elf.e_version = EV_CURRENT;
1087 elf.e_entry = 0;
1088 elf.e_phoff = sizeof(elf);
1089 elf.e_shoff = 0;
1090 elf.e_flags = 0;
1091 elf.e_ehsize = sizeof(elf);
1092 elf.e_phentsize = sizeof(struct elf_phdr);
1093 elf.e_phnum = segs+1;
1094 elf.e_shentsize = 0;
1095 elf.e_shnum = 0;
1096 elf.e_shstrndx = 0;
1097
1098 fs = get_fs();
1099 set_fs(KERNEL_DS);
1100
1101 has_dumped = 1;
1102 current->flags |= PF_DUMPCORE;
1103
1104 DUMP_WRITE(&elf, sizeof(elf));
1105 offset += sizeof(elf);
1106 offset += (segs+1) * sizeof(struct elf_phdr);
1107
1108
1109
1110
1111
1112
1113 notes[0].name = "CORE";
1114 notes[0].type = NT_PRSTATUS;
1115 notes[0].datasz = sizeof(prstatus);
1116 notes[0].data = &prstatus;
1117 prstatus.pr_info.si_signo = prstatus.pr_cursig = signr;
1118 prstatus.pr_sigpend = current->pending.signal.sig[0];
1119 prstatus.pr_sighold = current->blocked.sig[0];
1120 psinfo.pr_pid = prstatus.pr_pid = current->pid;
1121 psinfo.pr_ppid = prstatus.pr_ppid = current->p_pptr->pid;
1122 psinfo.pr_pgrp = prstatus.pr_pgrp = current->pgrp;
1123 psinfo.pr_sid = prstatus.pr_sid = current->session;
1124 prstatus.pr_utime.tv_sec = CT_TO_SECS(current->times.tms_utime);
1125 prstatus.pr_utime.tv_usec = CT_TO_USECS(current->times.tms_utime);
1126 prstatus.pr_stime.tv_sec = CT_TO_SECS(current->times.tms_stime);
1127 prstatus.pr_stime.tv_usec = CT_TO_USECS(current->times.tms_stime);
1128 prstatus.pr_cutime.tv_sec = CT_TO_SECS(current->times.tms_cutime);
1129 prstatus.pr_cutime.tv_usec = CT_TO_USECS(current->times.tms_cutime);
1130 prstatus.pr_cstime.tv_sec = CT_TO_SECS(current->times.tms_cstime);
1131 prstatus.pr_cstime.tv_usec = CT_TO_USECS(current->times.tms_cstime);
1132
1133#ifdef DEBUG
1134 dump_regs("Passed in regs", (elf_greg_t *)regs);
1135 dump_regs("prstatus regs", (elf_greg_t *)&prstatus.pr_reg);
1136#endif
1137
1138 notes[1].name = "CORE";
1139 notes[1].type = NT_PRPSINFO;
1140 notes[1].datasz = sizeof(psinfo);
1141 notes[1].data = &psinfo;
1142 i = current->state ? ffz(~current->state) + 1 : 0;
1143 psinfo.pr_state = i;
1144 psinfo.pr_sname = (i < 0 || i > 5) ? '.' : "RSDZTD"[i];
1145 psinfo.pr_zomb = psinfo.pr_sname == 'Z';
1146 psinfo.pr_nice = current->nice;
1147 psinfo.pr_flag = current->flags;
1148 psinfo.pr_uid = NEW_TO_OLD_UID(current->uid);
1149 psinfo.pr_gid = NEW_TO_OLD_GID(current->gid);
1150 strncpy(psinfo.pr_fname, current->comm, sizeof(psinfo.pr_fname));
1151
1152 notes[2].name = "CORE";
1153 notes[2].type = NT_TASKSTRUCT;
1154 notes[2].datasz = sizeof(*current);
1155 notes[2].data = current;
1156
1157
1158 prstatus.pr_fpvalid = dump_fpu (regs, &fpu);
1159 if (!prstatus.pr_fpvalid)
1160 {
1161 numnote--;
1162 }
1163 else
1164 {
1165 notes[3].name = "CORE";
1166 notes[3].type = NT_PRFPREG;
1167 notes[3].datasz = sizeof(fpu);
1168 notes[3].data = &fpu;
1169 }
1170
1171
1172 {
1173 struct elf_phdr phdr;
1174 int sz = 0;
1175
1176 for(i = 0; i < numnote; i++)
1177 sz += notesize(¬es[i]);
1178
1179 phdr.p_type = PT_NOTE;
1180 phdr.p_offset = offset;
1181 phdr.p_vaddr = 0;
1182 phdr.p_paddr = 0;
1183 phdr.p_filesz = sz;
1184 phdr.p_memsz = 0;
1185 phdr.p_flags = 0;
1186 phdr.p_align = 0;
1187
1188 offset += phdr.p_filesz;
1189 DUMP_WRITE(&phdr, sizeof(phdr));
1190 }
1191
1192
1193 dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE);
1194
1195
1196 for(vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) {
1197 struct elf_phdr phdr;
1198 size_t sz;
1199
1200 sz = vma->vm_end - vma->vm_start;
1201
1202 phdr.p_type = PT_LOAD;
1203 phdr.p_offset = offset;
1204 phdr.p_vaddr = vma->vm_start;
1205 phdr.p_paddr = 0;
1206 phdr.p_filesz = maydump(vma) ? sz : 0;
1207 phdr.p_memsz = sz;
1208 offset += phdr.p_filesz;
1209 phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0;
1210 if (vma->vm_flags & VM_WRITE) phdr.p_flags |= PF_W;
1211 if (vma->vm_flags & VM_EXEC) phdr.p_flags |= PF_X;
1212 phdr.p_align = ELF_EXEC_PAGESIZE;
1213
1214 DUMP_WRITE(&phdr, sizeof(phdr));
1215 }
1216
1217 for(i = 0; i < numnote; i++)
1218 if (!writenote(¬es[i], file))
1219 goto end_coredump;
1220
1221 DUMP_SEEK(dataoff);
1222
1223 for(vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) {
1224 unsigned long addr;
1225
1226 if (!maydump(vma))
1227 continue;
1228
1229#ifdef DEBUG
1230 printk("elf_core_dump: writing %08lx-%08lx\n", vma->vm_start, vma->vm_end);
1231#endif
1232
1233 for (addr = vma->vm_start;
1234 addr < vma->vm_end;
1235 addr += PAGE_SIZE) {
1236 struct page* page;
1237 struct vm_area_struct *vma;
1238
1239 if (get_user_pages(current, current->mm, addr, 1, 0, 1,
1240 &page, &vma) <= 0) {
1241 DUMP_SEEK (file->f_pos + PAGE_SIZE);
1242 } else {
1243 if (page == ZERO_PAGE(addr)) {
1244 DUMP_SEEK (file->f_pos + PAGE_SIZE);
1245 } else {
1246 void *kaddr;
1247 flush_cache_page(vma, addr);
1248 kaddr = kmap(page);
1249 DUMP_WRITE(kaddr, PAGE_SIZE);
1250 flush_page_to_ram(page);
1251 kunmap(page);
1252 }
1253 put_page(page);
1254 }
1255 }
1256 }
1257
1258 if ((off_t) file->f_pos != offset) {
1259
1260 printk("elf_core_dump: file->f_pos (%ld) != offset (%ld)\n",
1261 (off_t) file->f_pos, offset);
1262 }
1263
1264 end_coredump:
1265 set_fs(fs);
1266 up_write(¤t->mm->mmap_sem);
1267 return has_dumped;
1268}
1269#endif
1270
1271static int __init init_elf_binfmt(void)
1272{
1273 return register_binfmt(&elf_format);
1274}
1275
1276static void __exit exit_elf_binfmt(void)
1277{
1278
1279 unregister_binfmt(&elf_format);
1280}
1281
1282module_init(init_elf_binfmt)
1283module_exit(exit_elf_binfmt)
1284MODULE_LICENSE("GPL");
1285