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