diff options
Diffstat (limited to 'fs/binfmt_flat.c')
-rw-r--r-- | fs/binfmt_flat.c | 73 |
1 files changed, 54 insertions, 19 deletions
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c index 108d56bbd0d0..69f44dcdb0b4 100644 --- a/fs/binfmt_flat.c +++ b/fs/binfmt_flat.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/personality.h> | 36 | #include <linux/personality.h> |
37 | #include <linux/init.h> | 37 | #include <linux/init.h> |
38 | #include <linux/flat.h> | 38 | #include <linux/flat.h> |
39 | #include <linux/syscalls.h> | ||
39 | 40 | ||
40 | #include <asm/byteorder.h> | 41 | #include <asm/byteorder.h> |
41 | #include <asm/system.h> | 42 | #include <asm/system.h> |
@@ -426,6 +427,8 @@ static int load_flat_file(struct linux_binprm * bprm, | |||
426 | int i, rev, relocs = 0; | 427 | int i, rev, relocs = 0; |
427 | loff_t fpos; | 428 | loff_t fpos; |
428 | unsigned long start_code, end_code; | 429 | unsigned long start_code, end_code; |
430 | int ret; | ||
431 | int exec_fileno; | ||
429 | 432 | ||
430 | hdr = ((struct flat_hdr *) bprm->buf); /* exec-header */ | 433 | hdr = ((struct flat_hdr *) bprm->buf); /* exec-header */ |
431 | inode = bprm->file->f_dentry->d_inode; | 434 | inode = bprm->file->f_dentry->d_inode; |
@@ -450,7 +453,8 @@ static int load_flat_file(struct linux_binprm * bprm, | |||
450 | */ | 453 | */ |
451 | if (strncmp(hdr->magic, "#!", 2)) | 454 | if (strncmp(hdr->magic, "#!", 2)) |
452 | printk("BINFMT_FLAT: bad header magic\n"); | 455 | printk("BINFMT_FLAT: bad header magic\n"); |
453 | return -ENOEXEC; | 456 | ret = -ENOEXEC; |
457 | goto err; | ||
454 | } | 458 | } |
455 | 459 | ||
456 | if (flags & FLAT_FLAG_KTRACE) | 460 | if (flags & FLAT_FLAG_KTRACE) |
@@ -458,14 +462,16 @@ static int load_flat_file(struct linux_binprm * bprm, | |||
458 | 462 | ||
459 | if (rev != FLAT_VERSION && rev != OLD_FLAT_VERSION) { | 463 | if (rev != FLAT_VERSION && rev != OLD_FLAT_VERSION) { |
460 | printk("BINFMT_FLAT: bad flat file version 0x%x (supported 0x%x and 0x%x)\n", rev, FLAT_VERSION, OLD_FLAT_VERSION); | 464 | printk("BINFMT_FLAT: bad flat file version 0x%x (supported 0x%x and 0x%x)\n", rev, FLAT_VERSION, OLD_FLAT_VERSION); |
461 | return -ENOEXEC; | 465 | ret = -ENOEXEC; |
466 | goto err; | ||
462 | } | 467 | } |
463 | 468 | ||
464 | /* Don't allow old format executables to use shared libraries */ | 469 | /* Don't allow old format executables to use shared libraries */ |
465 | if (rev == OLD_FLAT_VERSION && id != 0) { | 470 | if (rev == OLD_FLAT_VERSION && id != 0) { |
466 | printk("BINFMT_FLAT: shared libraries are not available before rev 0x%x\n", | 471 | printk("BINFMT_FLAT: shared libraries are not available before rev 0x%x\n", |
467 | (int) FLAT_VERSION); | 472 | (int) FLAT_VERSION); |
468 | return -ENOEXEC; | 473 | ret = -ENOEXEC; |
474 | goto err; | ||
469 | } | 475 | } |
470 | 476 | ||
471 | /* | 477 | /* |
@@ -478,7 +484,8 @@ static int load_flat_file(struct linux_binprm * bprm, | |||
478 | #ifndef CONFIG_BINFMT_ZFLAT | 484 | #ifndef CONFIG_BINFMT_ZFLAT |
479 | if (flags & (FLAT_FLAG_GZIP|FLAT_FLAG_GZDATA)) { | 485 | if (flags & (FLAT_FLAG_GZIP|FLAT_FLAG_GZDATA)) { |
480 | printk("Support for ZFLAT executables is not enabled.\n"); | 486 | printk("Support for ZFLAT executables is not enabled.\n"); |
481 | return -ENOEXEC; | 487 | ret = -ENOEXEC; |
488 | goto err; | ||
482 | } | 489 | } |
483 | #endif | 490 | #endif |
484 | 491 | ||
@@ -490,14 +497,27 @@ static int load_flat_file(struct linux_binprm * bprm, | |||
490 | rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur; | 497 | rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur; |
491 | if (rlim >= RLIM_INFINITY) | 498 | if (rlim >= RLIM_INFINITY) |
492 | rlim = ~0; | 499 | rlim = ~0; |
493 | if (data_len + bss_len > rlim) | 500 | if (data_len + bss_len > rlim) { |
494 | return -ENOMEM; | 501 | ret = -ENOMEM; |
502 | goto err; | ||
503 | } | ||
504 | |||
505 | /* check file descriptor */ | ||
506 | exec_fileno = get_unused_fd(); | ||
507 | if (exec_fileno < 0) { | ||
508 | ret = -EMFILE; | ||
509 | goto err; | ||
510 | } | ||
511 | get_file(bprm->file); | ||
512 | fd_install(exec_fileno, bprm->file); | ||
495 | 513 | ||
496 | /* Flush all traces of the currently running executable */ | 514 | /* Flush all traces of the currently running executable */ |
497 | if (id == 0) { | 515 | if (id == 0) { |
498 | result = flush_old_exec(bprm); | 516 | result = flush_old_exec(bprm); |
499 | if (result) | 517 | if (result) { |
500 | return result; | 518 | ret = result; |
519 | goto err_close; | ||
520 | } | ||
501 | 521 | ||
502 | /* OK, This is the point of no return */ | 522 | /* OK, This is the point of no return */ |
503 | set_personality(PER_LINUX); | 523 | set_personality(PER_LINUX); |
@@ -527,7 +547,8 @@ static int load_flat_file(struct linux_binprm * bprm, | |||
527 | if (!textpos) | 547 | if (!textpos) |
528 | textpos = (unsigned long) -ENOMEM; | 548 | textpos = (unsigned long) -ENOMEM; |
529 | printk("Unable to mmap process text, errno %d\n", (int)-textpos); | 549 | printk("Unable to mmap process text, errno %d\n", (int)-textpos); |
530 | return(textpos); | 550 | ret = textpos; |
551 | goto err_close; | ||
531 | } | 552 | } |
532 | 553 | ||
533 | down_write(¤t->mm->mmap_sem); | 554 | down_write(¤t->mm->mmap_sem); |
@@ -542,7 +563,8 @@ static int load_flat_file(struct linux_binprm * bprm, | |||
542 | printk("Unable to allocate RAM for process data, errno %d\n", | 563 | printk("Unable to allocate RAM for process data, errno %d\n", |
543 | (int)-datapos); | 564 | (int)-datapos); |
544 | do_munmap(current->mm, textpos, text_len); | 565 | do_munmap(current->mm, textpos, text_len); |
545 | return realdatastart; | 566 | ret = realdatastart; |
567 | goto err_close; | ||
546 | } | 568 | } |
547 | datapos = realdatastart + MAX_SHARED_LIBS * sizeof(unsigned long); | 569 | datapos = realdatastart + MAX_SHARED_LIBS * sizeof(unsigned long); |
548 | 570 | ||
@@ -564,7 +586,8 @@ static int load_flat_file(struct linux_binprm * bprm, | |||
564 | printk("Unable to read data+bss, errno %d\n", (int)-result); | 586 | printk("Unable to read data+bss, errno %d\n", (int)-result); |
565 | do_munmap(current->mm, textpos, text_len); | 587 | do_munmap(current->mm, textpos, text_len); |
566 | do_munmap(current->mm, realdatastart, data_len + extra); | 588 | do_munmap(current->mm, realdatastart, data_len + extra); |
567 | return result; | 589 | ret = result; |
590 | goto err_close; | ||
568 | } | 591 | } |
569 | 592 | ||
570 | reloc = (unsigned long *) (datapos+(ntohl(hdr->reloc_start)-text_len)); | 593 | reloc = (unsigned long *) (datapos+(ntohl(hdr->reloc_start)-text_len)); |
@@ -582,7 +605,8 @@ static int load_flat_file(struct linux_binprm * bprm, | |||
582 | textpos = (unsigned long) -ENOMEM; | 605 | textpos = (unsigned long) -ENOMEM; |
583 | printk("Unable to allocate RAM for process text/data, errno %d\n", | 606 | printk("Unable to allocate RAM for process text/data, errno %d\n", |
584 | (int)-textpos); | 607 | (int)-textpos); |
585 | return(textpos); | 608 | ret = textpos; |
609 | goto err_close; | ||
586 | } | 610 | } |
587 | 611 | ||
588 | realdatastart = textpos + ntohl(hdr->data_start); | 612 | realdatastart = textpos + ntohl(hdr->data_start); |
@@ -627,7 +651,8 @@ static int load_flat_file(struct linux_binprm * bprm, | |||
627 | printk("Unable to read code+data+bss, errno %d\n",(int)-result); | 651 | printk("Unable to read code+data+bss, errno %d\n",(int)-result); |
628 | do_munmap(current->mm, textpos, text_len + data_len + extra + | 652 | do_munmap(current->mm, textpos, text_len + data_len + extra + |
629 | MAX_SHARED_LIBS * sizeof(unsigned long)); | 653 | MAX_SHARED_LIBS * sizeof(unsigned long)); |
630 | return result; | 654 | ret = result; |
655 | goto err_close; | ||
631 | } | 656 | } |
632 | } | 657 | } |
633 | 658 | ||
@@ -690,8 +715,10 @@ static int load_flat_file(struct linux_binprm * bprm, | |||
690 | unsigned long addr; | 715 | unsigned long addr; |
691 | if (*rp) { | 716 | if (*rp) { |
692 | addr = calc_reloc(*rp, libinfo, id, 0); | 717 | addr = calc_reloc(*rp, libinfo, id, 0); |
693 | if (addr == RELOC_FAILED) | 718 | if (addr == RELOC_FAILED) { |
694 | return -ENOEXEC; | 719 | ret = -ENOEXEC; |
720 | goto err_close; | ||
721 | } | ||
695 | *rp = addr; | 722 | *rp = addr; |
696 | } | 723 | } |
697 | } | 724 | } |
@@ -718,8 +745,10 @@ static int load_flat_file(struct linux_binprm * bprm, | |||
718 | relval = ntohl(reloc[i]); | 745 | relval = ntohl(reloc[i]); |
719 | addr = flat_get_relocate_addr(relval); | 746 | addr = flat_get_relocate_addr(relval); |
720 | rp = (unsigned long *) calc_reloc(addr, libinfo, id, 1); | 747 | rp = (unsigned long *) calc_reloc(addr, libinfo, id, 1); |
721 | if (rp == (unsigned long *)RELOC_FAILED) | 748 | if (rp == (unsigned long *)RELOC_FAILED) { |
722 | return -ENOEXEC; | 749 | ret = -ENOEXEC; |
750 | goto err_close; | ||
751 | } | ||
723 | 752 | ||
724 | /* Get the pointer's value. */ | 753 | /* Get the pointer's value. */ |
725 | addr = flat_get_addr_from_rp(rp, relval, flags); | 754 | addr = flat_get_addr_from_rp(rp, relval, flags); |
@@ -731,8 +760,10 @@ static int load_flat_file(struct linux_binprm * bprm, | |||
731 | if ((flags & FLAT_FLAG_GOTPIC) == 0) | 760 | if ((flags & FLAT_FLAG_GOTPIC) == 0) |
732 | addr = ntohl(addr); | 761 | addr = ntohl(addr); |
733 | addr = calc_reloc(addr, libinfo, id, 0); | 762 | addr = calc_reloc(addr, libinfo, id, 0); |
734 | if (addr == RELOC_FAILED) | 763 | if (addr == RELOC_FAILED) { |
735 | return -ENOEXEC; | 764 | ret = -ENOEXEC; |
765 | goto err_close; | ||
766 | } | ||
736 | 767 | ||
737 | /* Write back the relocated pointer. */ | 768 | /* Write back the relocated pointer. */ |
738 | flat_put_addr_at_rp(rp, addr, relval); | 769 | flat_put_addr_at_rp(rp, addr, relval); |
@@ -752,6 +783,10 @@ static int load_flat_file(struct linux_binprm * bprm, | |||
752 | stack_len); | 783 | stack_len); |
753 | 784 | ||
754 | return 0; | 785 | return 0; |
786 | err_close: | ||
787 | sys_close(exec_fileno); | ||
788 | err: | ||
789 | return ret; | ||
755 | } | 790 | } |
756 | 791 | ||
757 | 792 | ||