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