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