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