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