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