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