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