diff options
Diffstat (limited to 'arch/mips/kernel/irixelf.c')
-rw-r--r-- | arch/mips/kernel/irixelf.c | 226 |
1 files changed, 123 insertions, 103 deletions
diff --git a/arch/mips/kernel/irixelf.c b/arch/mips/kernel/irixelf.c index 4af20cd91f9f..881f125eecb4 100644 --- a/arch/mips/kernel/irixelf.c +++ b/arch/mips/kernel/irixelf.c | |||
@@ -8,7 +8,7 @@ | |||
8 | * | 8 | * |
9 | * Copyright (C) 1993 - 1994 Eric Youngdale <ericy@cais.com> | 9 | * Copyright (C) 1993 - 1994 Eric Youngdale <ericy@cais.com> |
10 | * Copyright (C) 1996 - 2004 David S. Miller <dm@engr.sgi.com> | 10 | * Copyright (C) 1996 - 2004 David S. Miller <dm@engr.sgi.com> |
11 | * Copyright (C) 2004 Steven J. Hill <sjhill@realitydiluted.com> | 11 | * Copyright (C) 2004 - 2005 Steven J. Hill <sjhill@realitydiluted.com> |
12 | */ | 12 | */ |
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/fs.h> | 14 | #include <linux/fs.h> |
@@ -31,15 +31,16 @@ | |||
31 | #include <linux/elfcore.h> | 31 | #include <linux/elfcore.h> |
32 | #include <linux/smp_lock.h> | 32 | #include <linux/smp_lock.h> |
33 | 33 | ||
34 | #include <asm/uaccess.h> | ||
35 | #include <asm/mipsregs.h> | 34 | #include <asm/mipsregs.h> |
35 | #include <asm/namei.h> | ||
36 | #include <asm/prctl.h> | 36 | #include <asm/prctl.h> |
37 | #include <asm/uaccess.h> | ||
37 | 38 | ||
38 | #define DLINFO_ITEMS 12 | 39 | #define DLINFO_ITEMS 12 |
39 | 40 | ||
40 | #include <linux/elf.h> | 41 | #include <linux/elf.h> |
41 | 42 | ||
42 | #undef DEBUG_ELF | 43 | #undef DEBUG |
43 | 44 | ||
44 | static int load_irix_binary(struct linux_binprm * bprm, struct pt_regs * regs); | 45 | static int load_irix_binary(struct linux_binprm * bprm, struct pt_regs * regs); |
45 | static int load_irix_library(struct file *); | 46 | static int load_irix_library(struct file *); |
@@ -55,7 +56,7 @@ static struct linux_binfmt irix_format = { | |||
55 | #define elf_addr_t unsigned long | 56 | #define elf_addr_t unsigned long |
56 | #endif | 57 | #endif |
57 | 58 | ||
58 | #ifdef DEBUG_ELF | 59 | #ifdef DEBUG |
59 | /* Debugging routines. */ | 60 | /* Debugging routines. */ |
60 | static char *get_elf_p_type(Elf32_Word p_type) | 61 | static char *get_elf_p_type(Elf32_Word p_type) |
61 | { | 62 | { |
@@ -120,7 +121,7 @@ static void dump_phdrs(struct elf_phdr *ep, int pnum) | |||
120 | print_phdr(i, ep); | 121 | print_phdr(i, ep); |
121 | } | 122 | } |
122 | } | 123 | } |
123 | #endif /* (DEBUG_ELF) */ | 124 | #endif /* DEBUG */ |
124 | 125 | ||
125 | static void set_brk(unsigned long start, unsigned long end) | 126 | static void set_brk(unsigned long start, unsigned long end) |
126 | { | 127 | { |
@@ -150,16 +151,16 @@ static void padzero(unsigned long elf_bss) | |||
150 | } | 151 | } |
151 | } | 152 | } |
152 | 153 | ||
153 | unsigned long * create_irix_tables(char * p, int argc, int envc, | 154 | static unsigned long * create_irix_tables(char * p, int argc, int envc, |
154 | struct elfhdr * exec, unsigned int load_addr, | 155 | struct elfhdr * exec, unsigned int load_addr, |
155 | unsigned int interp_load_addr, | 156 | unsigned int interp_load_addr, struct pt_regs *regs, |
156 | struct pt_regs *regs, struct elf_phdr *ephdr) | 157 | struct elf_phdr *ephdr) |
157 | { | 158 | { |
158 | elf_addr_t *argv; | 159 | elf_addr_t *argv; |
159 | elf_addr_t *envp; | 160 | elf_addr_t *envp; |
160 | elf_addr_t *sp, *csp; | 161 | elf_addr_t *sp, *csp; |
161 | 162 | ||
162 | #ifdef DEBUG_ELF | 163 | #ifdef DEBUG |
163 | printk("create_irix_tables: p[%p] argc[%d] envc[%d] " | 164 | printk("create_irix_tables: p[%p] argc[%d] envc[%d] " |
164 | "load_addr[%08x] interp_load_addr[%08x]\n", | 165 | "load_addr[%08x] interp_load_addr[%08x]\n", |
165 | p, argc, envc, load_addr, interp_load_addr); | 166 | p, argc, envc, load_addr, interp_load_addr); |
@@ -248,14 +249,13 @@ static unsigned int load_irix_interp(struct elfhdr * interp_elf_ex, | |||
248 | last_bss = 0; | 249 | last_bss = 0; |
249 | error = load_addr = 0; | 250 | error = load_addr = 0; |
250 | 251 | ||
251 | #ifdef DEBUG_ELF | 252 | #ifdef DEBUG |
252 | print_elfhdr(interp_elf_ex); | 253 | print_elfhdr(interp_elf_ex); |
253 | #endif | 254 | #endif |
254 | 255 | ||
255 | /* First of all, some simple consistency checks */ | 256 | /* First of all, some simple consistency checks */ |
256 | if ((interp_elf_ex->e_type != ET_EXEC && | 257 | if ((interp_elf_ex->e_type != ET_EXEC && |
257 | interp_elf_ex->e_type != ET_DYN) || | 258 | interp_elf_ex->e_type != ET_DYN) || |
258 | !irix_elf_check_arch(interp_elf_ex) || | ||
259 | !interpreter->f_op->mmap) { | 259 | !interpreter->f_op->mmap) { |
260 | printk("IRIX interp has bad e_type %d\n", interp_elf_ex->e_type); | 260 | printk("IRIX interp has bad e_type %d\n", interp_elf_ex->e_type); |
261 | return 0xffffffff; | 261 | return 0xffffffff; |
@@ -290,7 +290,7 @@ static unsigned int load_irix_interp(struct elfhdr * interp_elf_ex, | |||
290 | (char *) elf_phdata, | 290 | (char *) elf_phdata, |
291 | sizeof(struct elf_phdr) * interp_elf_ex->e_phnum); | 291 | sizeof(struct elf_phdr) * interp_elf_ex->e_phnum); |
292 | 292 | ||
293 | #ifdef DEBUG_ELF | 293 | #ifdef DEBUG |
294 | dump_phdrs(elf_phdata, interp_elf_ex->e_phnum); | 294 | dump_phdrs(elf_phdata, interp_elf_ex->e_phnum); |
295 | #endif | 295 | #endif |
296 | 296 | ||
@@ -306,13 +306,11 @@ static unsigned int load_irix_interp(struct elfhdr * interp_elf_ex, | |||
306 | elf_type |= MAP_FIXED; | 306 | elf_type |= MAP_FIXED; |
307 | vaddr = eppnt->p_vaddr; | 307 | vaddr = eppnt->p_vaddr; |
308 | 308 | ||
309 | #ifdef DEBUG_ELF | 309 | pr_debug("INTERP do_mmap(%p, %08lx, %08lx, %08lx, %08lx, %08lx) ", |
310 | printk("INTERP do_mmap(%p, %08lx, %08lx, %08lx, %08lx, %08lx) ", | ||
311 | interpreter, vaddr, | 310 | interpreter, vaddr, |
312 | (unsigned long) (eppnt->p_filesz + (eppnt->p_vaddr & 0xfff)), | 311 | (unsigned long) (eppnt->p_filesz + (eppnt->p_vaddr & 0xfff)), |
313 | (unsigned long) elf_prot, (unsigned long) elf_type, | 312 | (unsigned long) elf_prot, (unsigned long) elf_type, |
314 | (unsigned long) (eppnt->p_offset & 0xfffff000)); | 313 | (unsigned long) (eppnt->p_offset & 0xfffff000)); |
315 | #endif | ||
316 | down_write(¤t->mm->mmap_sem); | 314 | down_write(¤t->mm->mmap_sem); |
317 | error = do_mmap(interpreter, vaddr, | 315 | error = do_mmap(interpreter, vaddr, |
318 | eppnt->p_filesz + (eppnt->p_vaddr & 0xfff), | 316 | eppnt->p_filesz + (eppnt->p_vaddr & 0xfff), |
@@ -324,14 +322,10 @@ static unsigned int load_irix_interp(struct elfhdr * interp_elf_ex, | |||
324 | printk("Aieee IRIX interp mmap error=%d\n", error); | 322 | printk("Aieee IRIX interp mmap error=%d\n", error); |
325 | break; /* Real error */ | 323 | break; /* Real error */ |
326 | } | 324 | } |
327 | #ifdef DEBUG_ELF | 325 | pr_debug("error=%08lx ", (unsigned long) error); |
328 | printk("error=%08lx ", (unsigned long) error); | ||
329 | #endif | ||
330 | if(!load_addr && interp_elf_ex->e_type == ET_DYN) { | 326 | if(!load_addr && interp_elf_ex->e_type == ET_DYN) { |
331 | load_addr = error; | 327 | load_addr = error; |
332 | #ifdef DEBUG_ELF | 328 | pr_debug("load_addr = error "); |
333 | printk("load_addr = error "); | ||
334 | #endif | ||
335 | } | 329 | } |
336 | 330 | ||
337 | /* Find the end of the file mapping for this phdr, and keep | 331 | /* Find the end of the file mapping for this phdr, and keep |
@@ -345,17 +339,13 @@ static unsigned int load_irix_interp(struct elfhdr * interp_elf_ex, | |||
345 | */ | 339 | */ |
346 | k = eppnt->p_memsz + eppnt->p_vaddr; | 340 | k = eppnt->p_memsz + eppnt->p_vaddr; |
347 | if(k > last_bss) last_bss = k; | 341 | if(k > last_bss) last_bss = k; |
348 | #ifdef DEBUG_ELF | 342 | pr_debug("\n"); |
349 | printk("\n"); | ||
350 | #endif | ||
351 | } | 343 | } |
352 | } | 344 | } |
353 | 345 | ||
354 | /* Now use mmap to map the library into memory. */ | 346 | /* Now use mmap to map the library into memory. */ |
355 | if(error < 0 && error > -1024) { | 347 | if(error < 0 && error > -1024) { |
356 | #ifdef DEBUG_ELF | 348 | pr_debug("got error %d\n", error); |
357 | printk("got error %d\n", error); | ||
358 | #endif | ||
359 | kfree(elf_phdata); | 349 | kfree(elf_phdata); |
360 | return 0xffffffff; | 350 | return 0xffffffff; |
361 | } | 351 | } |
@@ -365,16 +355,12 @@ static unsigned int load_irix_interp(struct elfhdr * interp_elf_ex, | |||
365 | * that there are zero-mapped pages up to and including the | 355 | * that there are zero-mapped pages up to and including the |
366 | * last bss page. | 356 | * last bss page. |
367 | */ | 357 | */ |
368 | #ifdef DEBUG_ELF | 358 | pr_debug("padzero(%08lx) ", (unsigned long) (elf_bss)); |
369 | printk("padzero(%08lx) ", (unsigned long) (elf_bss)); | ||
370 | #endif | ||
371 | padzero(elf_bss); | 359 | padzero(elf_bss); |
372 | len = (elf_bss + 0xfff) & 0xfffff000; /* What we have mapped so far */ | 360 | len = (elf_bss + 0xfff) & 0xfffff000; /* What we have mapped so far */ |
373 | 361 | ||
374 | #ifdef DEBUG_ELF | 362 | pr_debug("last_bss[%08lx] len[%08lx]\n", (unsigned long) last_bss, |
375 | printk("last_bss[%08lx] len[%08lx]\n", (unsigned long) last_bss, | 363 | (unsigned long) len); |
376 | (unsigned long) len); | ||
377 | #endif | ||
378 | 364 | ||
379 | /* Map the last of the bss segment */ | 365 | /* Map the last of the bss segment */ |
380 | if (last_bss > len) { | 366 | if (last_bss > len) { |
@@ -396,12 +382,7 @@ static int verify_binary(struct elfhdr *ehp, struct linux_binprm *bprm) | |||
396 | 382 | ||
397 | /* First of all, some simple consistency checks */ | 383 | /* First of all, some simple consistency checks */ |
398 | if((ehp->e_type != ET_EXEC && ehp->e_type != ET_DYN) || | 384 | if((ehp->e_type != ET_EXEC && ehp->e_type != ET_DYN) || |
399 | !irix_elf_check_arch(ehp) || !bprm->file->f_op->mmap) { | 385 | !bprm->file->f_op->mmap) { |
400 | return -ENOEXEC; | ||
401 | } | ||
402 | |||
403 | /* Only support MIPS ARCH2 or greater IRIX binaries for now. */ | ||
404 | if(!(ehp->e_flags & EF_MIPS_ARCH) && !(ehp->e_flags & 0x04)) { | ||
405 | return -ENOEXEC; | 386 | return -ENOEXEC; |
406 | } | 387 | } |
407 | 388 | ||
@@ -411,16 +392,17 @@ static int verify_binary(struct elfhdr *ehp, struct linux_binprm *bprm) | |||
411 | * XXX all registers as 64bits on cpu's capable of this at | 392 | * XXX all registers as 64bits on cpu's capable of this at |
412 | * XXX exception time plus frob the XTLB exception vector. | 393 | * XXX exception time plus frob the XTLB exception vector. |
413 | */ | 394 | */ |
414 | if((ehp->e_flags & 0x20)) { | 395 | if((ehp->e_flags & EF_MIPS_ABI2)) |
415 | return -ENOEXEC; | 396 | return -ENOEXEC; |
416 | } | ||
417 | 397 | ||
418 | return 0; /* It's ok. */ | 398 | return 0; |
419 | } | 399 | } |
420 | 400 | ||
421 | #define IRIX_INTERP_PREFIX "/usr/gnemul/irix" | 401 | /* |
422 | 402 | * This is where the detailed check is performed. Irix binaries | |
423 | /* Look for an IRIX ELF interpreter. */ | 403 | * use interpreters with 'libc.so' in the name, so this function |
404 | * can differentiate between Linux and Irix binaries. | ||
405 | */ | ||
424 | static inline int look_for_irix_interpreter(char **name, | 406 | static inline int look_for_irix_interpreter(char **name, |
425 | struct file **interpreter, | 407 | struct file **interpreter, |
426 | struct elfhdr *interp_elf_ex, | 408 | struct elfhdr *interp_elf_ex, |
@@ -440,12 +422,13 @@ static inline int look_for_irix_interpreter(char **name, | |||
440 | if (*name != NULL) | 422 | if (*name != NULL) |
441 | goto out; | 423 | goto out; |
442 | 424 | ||
443 | *name = kmalloc((epp->p_filesz + strlen(IRIX_INTERP_PREFIX)), | 425 | *name = (char *) kmalloc((epp->p_filesz + |
444 | GFP_KERNEL); | 426 | strlen(IRIX_EMUL)), |
427 | GFP_KERNEL); | ||
445 | if (!*name) | 428 | if (!*name) |
446 | return -ENOMEM; | 429 | return -ENOMEM; |
447 | 430 | ||
448 | strcpy(*name, IRIX_INTERP_PREFIX); | 431 | strcpy(*name, IRIX_EMUL); |
449 | retval = kernel_read(bprm->file, epp->p_offset, (*name + 16), | 432 | retval = kernel_read(bprm->file, epp->p_offset, (*name + 16), |
450 | epp->p_filesz); | 433 | epp->p_filesz); |
451 | if (retval < 0) | 434 | if (retval < 0) |
@@ -562,7 +545,7 @@ static inline int map_interpreter(struct elf_phdr *epp, struct elfhdr *ihp, | |||
562 | * process and the system, here we map the page and fill the | 545 | * process and the system, here we map the page and fill the |
563 | * structure | 546 | * structure |
564 | */ | 547 | */ |
565 | void irix_map_prda_page (void) | 548 | static void irix_map_prda_page(void) |
566 | { | 549 | { |
567 | unsigned long v; | 550 | unsigned long v; |
568 | struct prda *pp; | 551 | struct prda *pp; |
@@ -601,14 +584,33 @@ static int load_irix_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
601 | 584 | ||
602 | load_addr = 0; | 585 | load_addr = 0; |
603 | has_interp = has_ephdr = 0; | 586 | has_interp = has_ephdr = 0; |
604 | elf_ihdr = elf_ephdr = 0; | 587 | elf_ihdr = elf_ephdr = NULL; |
605 | elf_ex = *((struct elfhdr *) bprm->buf); | 588 | elf_ex = *((struct elfhdr *) bprm->buf); |
606 | retval = -ENOEXEC; | 589 | retval = -ENOEXEC; |
607 | 590 | ||
608 | if (verify_binary(&elf_ex, bprm)) | 591 | if (verify_binary(&elf_ex, bprm)) |
609 | goto out; | 592 | goto out; |
610 | 593 | ||
611 | #ifdef DEBUG_ELF | 594 | /* |
595 | * Telling -o32 static binaries from Linux and Irix apart from each | ||
596 | * other is difficult. There are 2 differences to be noted for static | ||
597 | * binaries from the 2 operating systems: | ||
598 | * | ||
599 | * 1) Irix binaries have their .text section before their .init | ||
600 | * section. Linux binaries are just the opposite. | ||
601 | * | ||
602 | * 2) Irix binaries usually have <= 12 sections and Linux | ||
603 | * binaries have > 20. | ||
604 | * | ||
605 | * We will use Method #2 since Method #1 would require us to read in | ||
606 | * the section headers which is way too much overhead. This appears | ||
607 | * to work for everything we have ran into so far. If anyone has a | ||
608 | * better method to tell the binaries apart, I'm listening. | ||
609 | */ | ||
610 | if (elf_ex.e_shnum > 20) | ||
611 | goto out; | ||
612 | |||
613 | #ifdef DEBUG | ||
612 | print_elfhdr(&elf_ex); | 614 | print_elfhdr(&elf_ex); |
613 | #endif | 615 | #endif |
614 | 616 | ||
@@ -623,11 +625,10 @@ static int load_irix_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
623 | } | 625 | } |
624 | 626 | ||
625 | retval = kernel_read(bprm->file, elf_ex.e_phoff, (char *)elf_phdata, size); | 627 | retval = kernel_read(bprm->file, elf_ex.e_phoff, (char *)elf_phdata, size); |
626 | |||
627 | if (retval < 0) | 628 | if (retval < 0) |
628 | goto out_free_ph; | 629 | goto out_free_ph; |
629 | 630 | ||
630 | #ifdef DEBUG_ELF | 631 | #ifdef DEBUG |
631 | dump_phdrs(elf_phdata, elf_ex.e_phnum); | 632 | dump_phdrs(elf_phdata, elf_ex.e_phnum); |
632 | #endif | 633 | #endif |
633 | 634 | ||
@@ -644,9 +645,8 @@ static int load_irix_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
644 | break; | 645 | break; |
645 | }; | 646 | }; |
646 | } | 647 | } |
647 | #ifdef DEBUG_ELF | 648 | |
648 | printk("\n"); | 649 | pr_debug("\n"); |
649 | #endif | ||
650 | 650 | ||
651 | elf_bss = 0; | 651 | elf_bss = 0; |
652 | elf_brk = 0; | 652 | elf_brk = 0; |
@@ -657,12 +657,19 @@ static int load_irix_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
657 | end_code = 0; | 657 | end_code = 0; |
658 | end_data = 0; | 658 | end_data = 0; |
659 | 659 | ||
660 | retval = look_for_irix_interpreter(&elf_interpreter, | 660 | /* |
661 | &interpreter, | 661 | * If we get a return value, we change the value to be ENOEXEC |
662 | * so that we can exit gracefully and the main binary format | ||
663 | * search loop in 'fs/exec.c' will move onto the next handler | ||
664 | * which should be the normal ELF binary handler. | ||
665 | */ | ||
666 | retval = look_for_irix_interpreter(&elf_interpreter, &interpreter, | ||
662 | &interp_elf_ex, elf_phdata, bprm, | 667 | &interp_elf_ex, elf_phdata, bprm, |
663 | elf_ex.e_phnum); | 668 | elf_ex.e_phnum); |
664 | if (retval) | 669 | if (retval) { |
670 | retval = -ENOEXEC; | ||
665 | goto out_free_file; | 671 | goto out_free_file; |
672 | } | ||
666 | 673 | ||
667 | if (elf_interpreter) { | 674 | if (elf_interpreter) { |
668 | retval = verify_irix_interpreter(&interp_elf_ex); | 675 | retval = verify_irix_interpreter(&interp_elf_ex); |
@@ -746,18 +753,16 @@ static int load_irix_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
746 | * IRIX maps a page at 0x200000 which holds some system | 753 | * IRIX maps a page at 0x200000 which holds some system |
747 | * information. Programs depend on this. | 754 | * information. Programs depend on this. |
748 | */ | 755 | */ |
749 | irix_map_prda_page (); | 756 | irix_map_prda_page(); |
750 | 757 | ||
751 | padzero(elf_bss); | 758 | padzero(elf_bss); |
752 | 759 | ||
753 | #ifdef DEBUG_ELF | 760 | pr_debug("(start_brk) %lx\n" , (long) current->mm->start_brk); |
754 | printk("(start_brk) %lx\n" , (long) current->mm->start_brk); | 761 | pr_debug("(end_code) %lx\n" , (long) current->mm->end_code); |
755 | printk("(end_code) %lx\n" , (long) current->mm->end_code); | 762 | pr_debug("(start_code) %lx\n" , (long) current->mm->start_code); |
756 | printk("(start_code) %lx\n" , (long) current->mm->start_code); | 763 | pr_debug("(end_data) %lx\n" , (long) current->mm->end_data); |
757 | printk("(end_data) %lx\n" , (long) current->mm->end_data); | 764 | pr_debug("(start_stack) %lx\n" , (long) current->mm->start_stack); |
758 | printk("(start_stack) %lx\n" , (long) current->mm->start_stack); | 765 | pr_debug("(brk) %lx\n" , (long) current->mm->brk); |
759 | printk("(brk) %lx\n" , (long) current->mm->brk); | ||
760 | #endif | ||
761 | 766 | ||
762 | #if 0 /* XXX No fucking way dude... */ | 767 | #if 0 /* XXX No fucking way dude... */ |
763 | /* Why this, you ask??? Well SVr4 maps page 0 as read-only, | 768 | /* Why this, you ask??? Well SVr4 maps page 0 as read-only, |
@@ -782,8 +787,7 @@ out_free_dentry: | |||
782 | allow_write_access(interpreter); | 787 | allow_write_access(interpreter); |
783 | fput(interpreter); | 788 | fput(interpreter); |
784 | out_free_interp: | 789 | out_free_interp: |
785 | if (elf_interpreter) | 790 | kfree(elf_interpreter); |
786 | kfree(elf_interpreter); | ||
787 | out_free_file: | 791 | out_free_file: |
788 | out_free_ph: | 792 | out_free_ph: |
789 | kfree (elf_phdata); | 793 | kfree (elf_phdata); |
@@ -813,7 +817,7 @@ static int load_irix_library(struct file *file) | |||
813 | 817 | ||
814 | /* First of all, some simple consistency checks. */ | 818 | /* First of all, some simple consistency checks. */ |
815 | if(elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 || | 819 | if(elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 || |
816 | !irix_elf_check_arch(&elf_ex) || !file->f_op->mmap) | 820 | !file->f_op->mmap) |
817 | return -ENOEXEC; | 821 | return -ENOEXEC; |
818 | 822 | ||
819 | /* Now read in all of the header information. */ | 823 | /* Now read in all of the header information. */ |
@@ -876,33 +880,34 @@ static int load_irix_library(struct file *file) | |||
876 | */ | 880 | */ |
877 | unsigned long irix_mapelf(int fd, struct elf_phdr *user_phdrp, int cnt) | 881 | unsigned long irix_mapelf(int fd, struct elf_phdr *user_phdrp, int cnt) |
878 | { | 882 | { |
883 | unsigned long type, vaddr, filesz, offset, flags; | ||
879 | struct elf_phdr *hp; | 884 | struct elf_phdr *hp; |
880 | struct file *filp; | 885 | struct file *filp; |
881 | int i, retval; | 886 | int i, retval; |
882 | 887 | ||
883 | #ifdef DEBUG_ELF | 888 | pr_debug("irix_mapelf: fd[%d] user_phdrp[%p] cnt[%d]\n", |
884 | printk("irix_mapelf: fd[%d] user_phdrp[%p] cnt[%d]\n", | 889 | fd, user_phdrp, cnt); |
885 | fd, user_phdrp, cnt); | ||
886 | #endif | ||
887 | 890 | ||
888 | /* First get the verification out of the way. */ | 891 | /* First get the verification out of the way. */ |
889 | hp = user_phdrp; | 892 | hp = user_phdrp; |
890 | if (!access_ok(VERIFY_READ, hp, (sizeof(struct elf_phdr) * cnt))) { | 893 | if (!access_ok(VERIFY_READ, hp, (sizeof(struct elf_phdr) * cnt))) { |
891 | #ifdef DEBUG_ELF | 894 | pr_debug("irix_mapelf: bad pointer to ELF PHDR!\n"); |
892 | printk("irix_mapelf: access_ok fails!\n"); | 895 | |
893 | #endif | ||
894 | return -EFAULT; | 896 | return -EFAULT; |
895 | } | 897 | } |
896 | 898 | ||
897 | #ifdef DEBUG_ELF | 899 | #ifdef DEBUG |
898 | dump_phdrs(user_phdrp, cnt); | 900 | dump_phdrs(user_phdrp, cnt); |
899 | #endif | 901 | #endif |
900 | 902 | ||
901 | for(i = 0; i < cnt; i++, hp++) | 903 | for (i = 0; i < cnt; i++, hp++) { |
902 | if(hp->p_type != PT_LOAD) { | 904 | if (__get_user(type, &hp->p_type)) |
905 | return -EFAULT; | ||
906 | if (type != PT_LOAD) { | ||
903 | printk("irix_mapelf: One section is not PT_LOAD!\n"); | 907 | printk("irix_mapelf: One section is not PT_LOAD!\n"); |
904 | return -ENOEXEC; | 908 | return -ENOEXEC; |
905 | } | 909 | } |
910 | } | ||
906 | 911 | ||
907 | filp = fget(fd); | 912 | filp = fget(fd); |
908 | if (!filp) | 913 | if (!filp) |
@@ -917,29 +922,40 @@ unsigned long irix_mapelf(int fd, struct elf_phdr *user_phdrp, int cnt) | |||
917 | for(i = 0; i < cnt; i++, hp++) { | 922 | for(i = 0; i < cnt; i++, hp++) { |
918 | int prot; | 923 | int prot; |
919 | 924 | ||
920 | prot = (hp->p_flags & PF_R) ? PROT_READ : 0; | 925 | retval = __get_user(vaddr, &hp->p_vaddr); |
921 | prot |= (hp->p_flags & PF_W) ? PROT_WRITE : 0; | 926 | retval |= __get_user(filesz, &hp->p_filesz); |
922 | prot |= (hp->p_flags & PF_X) ? PROT_EXEC : 0; | 927 | retval |= __get_user(offset, &hp->p_offset); |
928 | retval |= __get_user(flags, &hp->p_flags); | ||
929 | if (retval) | ||
930 | return retval; | ||
931 | |||
932 | prot = (flags & PF_R) ? PROT_READ : 0; | ||
933 | prot |= (flags & PF_W) ? PROT_WRITE : 0; | ||
934 | prot |= (flags & PF_X) ? PROT_EXEC : 0; | ||
935 | |||
923 | down_write(¤t->mm->mmap_sem); | 936 | down_write(¤t->mm->mmap_sem); |
924 | retval = do_mmap(filp, (hp->p_vaddr & 0xfffff000), | 937 | retval = do_mmap(filp, (vaddr & 0xfffff000), |
925 | (hp->p_filesz + (hp->p_vaddr & 0xfff)), | 938 | (filesz + (vaddr & 0xfff)), |
926 | prot, (MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE), | 939 | prot, (MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE), |
927 | (hp->p_offset & 0xfffff000)); | 940 | (offset & 0xfffff000)); |
928 | up_write(¤t->mm->mmap_sem); | 941 | up_write(¤t->mm->mmap_sem); |
929 | 942 | ||
930 | if(retval != (hp->p_vaddr & 0xfffff000)) { | 943 | if (retval != (vaddr & 0xfffff000)) { |
931 | printk("irix_mapelf: do_mmap fails with %d!\n", retval); | 944 | printk("irix_mapelf: do_mmap fails with %d!\n", retval); |
932 | fput(filp); | 945 | fput(filp); |
933 | return retval; | 946 | return retval; |
934 | } | 947 | } |
935 | } | 948 | } |
936 | 949 | ||
937 | #ifdef DEBUG_ELF | 950 | pr_debug("irix_mapelf: Success, returning %08lx\n", |
938 | printk("irix_mapelf: Success, returning %08lx\n", | 951 | (unsigned long) user_phdrp->p_vaddr); |
939 | (unsigned long) user_phdrp->p_vaddr); | 952 | |
940 | #endif | ||
941 | fput(filp); | 953 | fput(filp); |
942 | return user_phdrp->p_vaddr; | 954 | |
955 | if (__get_user(vaddr, &user_phdrp->p_vaddr)) | ||
956 | return -EFAULT; | ||
957 | |||
958 | return vaddr; | ||
943 | } | 959 | } |
944 | 960 | ||
945 | /* | 961 | /* |
@@ -954,7 +970,7 @@ unsigned long irix_mapelf(int fd, struct elf_phdr *user_phdrp, int cnt) | |||
954 | */ | 970 | */ |
955 | static int dump_write(struct file *file, const void *addr, int nr) | 971 | static int dump_write(struct file *file, const void *addr, int nr) |
956 | { | 972 | { |
957 | return file->f_op->write(file, addr, nr, &file->f_pos) == nr; | 973 | return file->f_op->write(file, (const char *) addr, nr, &file->f_pos) == nr; |
958 | } | 974 | } |
959 | 975 | ||
960 | static int dump_seek(struct file *file, off_t off) | 976 | static int dump_seek(struct file *file, off_t off) |
@@ -1073,7 +1089,7 @@ static int irix_core_dump(long signr, struct pt_regs * regs, struct file *file) | |||
1073 | /* Count what's needed to dump, up to the limit of coredump size. */ | 1089 | /* Count what's needed to dump, up to the limit of coredump size. */ |
1074 | segs = 0; | 1090 | segs = 0; |
1075 | size = 0; | 1091 | size = 0; |
1076 | for(vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) { | 1092 | for (vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) { |
1077 | if (maydump(vma)) | 1093 | if (maydump(vma)) |
1078 | { | 1094 | { |
1079 | int sz = vma->vm_end-vma->vm_start; | 1095 | int sz = vma->vm_end-vma->vm_start; |
@@ -1187,9 +1203,9 @@ static int irix_core_dump(long signr, struct pt_regs * regs, struct file *file) | |||
1187 | 1203 | ||
1188 | len = current->mm->arg_end - current->mm->arg_start; | 1204 | len = current->mm->arg_end - current->mm->arg_start; |
1189 | len = len >= ELF_PRARGSZ ? ELF_PRARGSZ : len; | 1205 | len = len >= ELF_PRARGSZ ? ELF_PRARGSZ : len; |
1190 | copy_from_user(&psinfo.pr_psargs, | 1206 | (void *) copy_from_user(&psinfo.pr_psargs, |
1191 | (const char *)current->mm->arg_start, len); | 1207 | (const char *)current->mm->arg_start, len); |
1192 | for(i = 0; i < len; i++) | 1208 | for (i = 0; i < len; i++) |
1193 | if (psinfo.pr_psargs[i] == 0) | 1209 | if (psinfo.pr_psargs[i] == 0) |
1194 | psinfo.pr_psargs[i] = ' '; | 1210 | psinfo.pr_psargs[i] = ' '; |
1195 | psinfo.pr_psargs[len] = 0; | 1211 | psinfo.pr_psargs[len] = 0; |
@@ -1256,8 +1272,10 @@ static int irix_core_dump(long signr, struct pt_regs * regs, struct file *file) | |||
1256 | phdr.p_memsz = sz; | 1272 | phdr.p_memsz = sz; |
1257 | offset += phdr.p_filesz; | 1273 | offset += phdr.p_filesz; |
1258 | phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0; | 1274 | phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0; |
1259 | if (vma->vm_flags & VM_WRITE) phdr.p_flags |= PF_W; | 1275 | if (vma->vm_flags & VM_WRITE) |
1260 | if (vma->vm_flags & VM_EXEC) phdr.p_flags |= PF_X; | 1276 | phdr.p_flags |= PF_W; |
1277 | if (vma->vm_flags & VM_EXEC) | ||
1278 | phdr.p_flags |= PF_X; | ||
1261 | phdr.p_align = PAGE_SIZE; | 1279 | phdr.p_align = PAGE_SIZE; |
1262 | 1280 | ||
1263 | DUMP_WRITE(&phdr, sizeof(phdr)); | 1281 | DUMP_WRITE(&phdr, sizeof(phdr)); |
@@ -1299,7 +1317,7 @@ end_coredump: | |||
1299 | 1317 | ||
1300 | static int __init init_irix_binfmt(void) | 1318 | static int __init init_irix_binfmt(void) |
1301 | { | 1319 | { |
1302 | int init_inventory(void); | 1320 | extern int init_inventory(void); |
1303 | extern asmlinkage unsigned long sys_call_table; | 1321 | extern asmlinkage unsigned long sys_call_table; |
1304 | extern asmlinkage unsigned long sys_call_table_irix5; | 1322 | extern asmlinkage unsigned long sys_call_table_irix5; |
1305 | 1323 | ||
@@ -1318,7 +1336,9 @@ static int __init init_irix_binfmt(void) | |||
1318 | 1336 | ||
1319 | static void __exit exit_irix_binfmt(void) | 1337 | static void __exit exit_irix_binfmt(void) |
1320 | { | 1338 | { |
1321 | /* Remove the IRIX ELF loaders. */ | 1339 | /* |
1340 | * Remove the Irix ELF loader. | ||
1341 | */ | ||
1322 | unregister_binfmt(&irix_format); | 1342 | unregister_binfmt(&irix_format); |
1323 | } | 1343 | } |
1324 | 1344 | ||