aboutsummaryrefslogtreecommitdiffstats
path: root/fs/binfmt_flat.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2017-05-02 19:52:17 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2017-07-03 18:44:02 -0400
commit468138d78510688fb5476f98d23f11ac6a63229a (patch)
tree5f235bc85343bf3f314201a1d281881625d67abe /fs/binfmt_flat.c
parent2ea659a9ef488125eb46da6eb571de5eae5c43f6 (diff)
binfmt_flat: flat_{get,put}_addr_from_rp() should be able to fail
on MMU targets EFAULT is possible here. Make both return 0 or error, passing what used to be the return value of flat_get_addr_from_rp() by reference. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/binfmt_flat.c')
-rw-r--r--fs/binfmt_flat.c39
1 files changed, 22 insertions, 17 deletions
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c
index 2edcefc0a294..69ec23daa25e 100644
--- a/fs/binfmt_flat.c
+++ b/fs/binfmt_flat.c
@@ -422,9 +422,9 @@ static int load_flat_file(struct linux_binprm *bprm,
422{ 422{
423 struct flat_hdr *hdr; 423 struct flat_hdr *hdr;
424 unsigned long textpos, datapos, realdatastart; 424 unsigned long textpos, datapos, realdatastart;
425 unsigned long text_len, data_len, bss_len, stack_len, full_data, flags; 425 u32 text_len, data_len, bss_len, stack_len, full_data, flags;
426 unsigned long len, memp, memp_size, extra, rlim; 426 unsigned long len, memp, memp_size, extra, rlim;
427 unsigned long __user *reloc, *rp; 427 u32 __user *reloc, *rp;
428 struct inode *inode; 428 struct inode *inode;
429 int i, rev, relocs; 429 int i, rev, relocs;
430 loff_t fpos; 430 loff_t fpos;
@@ -596,13 +596,13 @@ static int load_flat_file(struct linux_binprm *bprm,
596 goto err; 596 goto err;
597 } 597 }
598 598
599 reloc = (unsigned long __user *) 599 reloc = (u32 __user *)
600 (datapos + (ntohl(hdr->reloc_start) - text_len)); 600 (datapos + (ntohl(hdr->reloc_start) - text_len));
601 memp = realdatastart; 601 memp = realdatastart;
602 memp_size = len; 602 memp_size = len;
603 } else { 603 } else {
604 604
605 len = text_len + data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long); 605 len = text_len + data_len + extra + MAX_SHARED_LIBS * sizeof(u32);
606 len = PAGE_ALIGN(len); 606 len = PAGE_ALIGN(len);
607 textpos = vm_mmap(NULL, 0, len, 607 textpos = vm_mmap(NULL, 0, len,
608 PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE, 0); 608 PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE, 0);
@@ -618,10 +618,10 @@ static int load_flat_file(struct linux_binprm *bprm,
618 618
619 realdatastart = textpos + ntohl(hdr->data_start); 619 realdatastart = textpos + ntohl(hdr->data_start);
620 datapos = ALIGN(realdatastart + 620 datapos = ALIGN(realdatastart +
621 MAX_SHARED_LIBS * sizeof(unsigned long), 621 MAX_SHARED_LIBS * sizeof(u32),
622 FLAT_DATA_ALIGN); 622 FLAT_DATA_ALIGN);
623 623
624 reloc = (unsigned long __user *) 624 reloc = (u32 __user *)
625 (datapos + (ntohl(hdr->reloc_start) - text_len)); 625 (datapos + (ntohl(hdr->reloc_start) - text_len));
626 memp = textpos; 626 memp = textpos;
627 memp_size = len; 627 memp_size = len;
@@ -694,7 +694,7 @@ static int load_flat_file(struct linux_binprm *bprm,
694 ret = result; 694 ret = result;
695 pr_err("Unable to read code+data+bss, errno %d\n", ret); 695 pr_err("Unable to read code+data+bss, errno %d\n", ret);
696 vm_munmap(textpos, text_len + data_len + extra + 696 vm_munmap(textpos, text_len + data_len + extra +
697 MAX_SHARED_LIBS * sizeof(unsigned long)); 697 MAX_SHARED_LIBS * sizeof(u32));
698 goto err; 698 goto err;
699 } 699 }
700 } 700 }
@@ -754,8 +754,8 @@ static int load_flat_file(struct linux_binprm *bprm,
754 * image. 754 * image.
755 */ 755 */
756 if (flags & FLAT_FLAG_GOTPIC) { 756 if (flags & FLAT_FLAG_GOTPIC) {
757 for (rp = (unsigned long __user *)datapos; ; rp++) { 757 for (rp = (u32 __user *)datapos; ; rp++) {
758 unsigned long addr, rp_val; 758 u32 addr, rp_val;
759 if (get_user(rp_val, rp)) 759 if (get_user(rp_val, rp))
760 return -EFAULT; 760 return -EFAULT;
761 if (rp_val == 0xffffffff) 761 if (rp_val == 0xffffffff)
@@ -784,9 +784,9 @@ static int load_flat_file(struct linux_binprm *bprm,
784 * __start to address 4 so that is okay). 784 * __start to address 4 so that is okay).
785 */ 785 */
786 if (rev > OLD_FLAT_VERSION) { 786 if (rev > OLD_FLAT_VERSION) {
787 unsigned long __maybe_unused persistent = 0; 787 u32 __maybe_unused persistent = 0;
788 for (i = 0; i < relocs; i++) { 788 for (i = 0; i < relocs; i++) {
789 unsigned long addr, relval; 789 u32 addr, relval;
790 790
791 /* 791 /*
792 * Get the address of the pointer to be 792 * Get the address of the pointer to be
@@ -799,15 +799,18 @@ static int load_flat_file(struct linux_binprm *bprm,
799 if (flat_set_persistent(relval, &persistent)) 799 if (flat_set_persistent(relval, &persistent))
800 continue; 800 continue;
801 addr = flat_get_relocate_addr(relval); 801 addr = flat_get_relocate_addr(relval);
802 rp = (unsigned long __user *)calc_reloc(addr, libinfo, id, 1); 802 rp = (u32 __user *)calc_reloc(addr, libinfo, id, 1);
803 if (rp == (unsigned long __user *)RELOC_FAILED) { 803 if (rp == (u32 __user *)RELOC_FAILED) {
804 ret = -ENOEXEC; 804 ret = -ENOEXEC;
805 goto err; 805 goto err;
806 } 806 }
807 807
808 /* Get the pointer's value. */ 808 /* Get the pointer's value. */
809 addr = flat_get_addr_from_rp(rp, relval, flags, 809 ret = flat_get_addr_from_rp(rp, relval, flags,
810 &persistent); 810 &addr, &persistent);
811 if (unlikely(ret))
812 goto err;
813
811 if (addr != 0) { 814 if (addr != 0) {
812 /* 815 /*
813 * Do the relocation. PIC relocs in the data section are 816 * Do the relocation. PIC relocs in the data section are
@@ -822,12 +825,14 @@ static int load_flat_file(struct linux_binprm *bprm,
822 } 825 }
823 826
824 /* Write back the relocated pointer. */ 827 /* Write back the relocated pointer. */
825 flat_put_addr_at_rp(rp, addr, relval); 828 ret = flat_put_addr_at_rp(rp, addr, relval);
829 if (unlikely(ret))
830 goto err;
826 } 831 }
827 } 832 }
828 } else { 833 } else {
829 for (i = 0; i < relocs; i++) { 834 for (i = 0; i < relocs; i++) {
830 unsigned long relval; 835 u32 relval;
831 if (get_user(relval, reloc + i)) 836 if (get_user(relval, reloc + i))
832 return -EFAULT; 837 return -EFAULT;
833 relval = ntohl(relval); 838 relval = ntohl(relval);