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