summaryrefslogtreecommitdiffstats
path: root/fs/binfmt_flat.c
diff options
context:
space:
mode:
authorNicolas Pitre <nicolas.pitre@linaro.org>2016-07-24 11:30:21 -0400
committerGreg Ungerer <gerg@linux-m68k.org>2016-07-25 02:52:06 -0400
commit6e572ffe3feb8a02ed0044987654e07670aeffc2 (patch)
tree66198e5622e32f4ed2eba4c932cae58a515c3cc9 /fs/binfmt_flat.c
parenta97d157d00cd0ccbcfde3da7bbf34ab7c68cf4eb (diff)
binfmt_flat: use proper user space accessors with relocs processing code
Relocs are fixed up in place in user space memory. The appropriate accessors are required for this code to work with an active MMU. The architecture specific handlers flat_get_addr_from_rp() and flat_put_addr_at_rp() for ARM and M68K are adjusted with separate patches. SuperH and Xtensa are left out as they doesn't implement __get_user_unaligned() and __put_user_unaligned() yet. The other architectures that use BFLT don't have any MMU. Signed-off-by: Nicolas Pitre <nico@linaro.org> Reviewed-by: Greg Ungerer <gerg@linux-m68k.org> Signed-off-by: Greg Ungerer <gerg@linux-m68k.org>
Diffstat (limited to 'fs/binfmt_flat.c')
-rw-r--r--fs/binfmt_flat.c31
1 files changed, 19 insertions, 12 deletions
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c
index 5dc7968a424f..9deafb282db5 100644
--- a/fs/binfmt_flat.c
+++ b/fs/binfmt_flat.c
@@ -419,7 +419,7 @@ static int load_flat_file(struct linux_binprm *bprm,
419 unsigned long textpos, datapos, realdatastart; 419 unsigned long textpos, datapos, realdatastart;
420 unsigned long text_len, data_len, bss_len, stack_len, full_data, flags; 420 unsigned long text_len, data_len, bss_len, stack_len, full_data, flags;
421 unsigned long len, memp, memp_size, extra, rlim; 421 unsigned long len, memp, memp_size, extra, rlim;
422 unsigned long *reloc, *rp; 422 unsigned long __user *reloc, *rp;
423 struct inode *inode; 423 struct inode *inode;
424 int i, rev, relocs; 424 int i, rev, relocs;
425 loff_t fpos; 425 loff_t fpos;
@@ -591,7 +591,7 @@ static int load_flat_file(struct linux_binprm *bprm,
591 goto err; 591 goto err;
592 } 592 }
593 593
594 reloc = (unsigned long *) 594 reloc = (unsigned long __user *)
595 (datapos + (ntohl(hdr->reloc_start) - text_len)); 595 (datapos + (ntohl(hdr->reloc_start) - text_len));
596 memp = realdatastart; 596 memp = realdatastart;
597 memp_size = len; 597 memp_size = len;
@@ -616,7 +616,7 @@ static int load_flat_file(struct linux_binprm *bprm,
616 MAX_SHARED_LIBS * sizeof(unsigned long), 616 MAX_SHARED_LIBS * sizeof(unsigned long),
617 FLAT_DATA_ALIGN); 617 FLAT_DATA_ALIGN);
618 618
619 reloc = (unsigned long *) 619 reloc = (unsigned long __user *)
620 (datapos + (ntohl(hdr->reloc_start) - text_len)); 620 (datapos + (ntohl(hdr->reloc_start) - text_len));
621 memp = textpos; 621 memp = textpos;
622 memp_size = len; 622 memp_size = len;
@@ -708,15 +708,20 @@ static int load_flat_file(struct linux_binprm *bprm,
708 * image. 708 * image.
709 */ 709 */
710 if (flags & FLAT_FLAG_GOTPIC) { 710 if (flags & FLAT_FLAG_GOTPIC) {
711 for (rp = (unsigned long *)datapos; *rp != 0xffffffff; rp++) { 711 for (rp = (unsigned long __user *)datapos; ; rp++) {
712 unsigned long addr; 712 unsigned long addr, rp_val;
713 if (*rp) { 713 if (get_user(rp_val, rp))
714 addr = calc_reloc(*rp, libinfo, id, 0); 714 return -EFAULT;
715 if (rp_val == 0xffffffff)
716 break;
717 if (rp_val) {
718 addr = calc_reloc(rp_val, libinfo, id, 0);
715 if (addr == RELOC_FAILED) { 719 if (addr == RELOC_FAILED) {
716 ret = -ENOEXEC; 720 ret = -ENOEXEC;
717 goto err; 721 goto err;
718 } 722 }
719 *rp = addr; 723 if (put_user(addr, rp))
724 return -EFAULT;
720 } 725 }
721 } 726 }
722 } 727 }
@@ -733,7 +738,7 @@ static int load_flat_file(struct linux_binprm *bprm,
733 * __start to address 4 so that is okay). 738 * __start to address 4 so that is okay).
734 */ 739 */
735 if (rev > OLD_FLAT_VERSION) { 740 if (rev > OLD_FLAT_VERSION) {
736 unsigned long persistent = 0; 741 unsigned long __maybe_unused persistent = 0;
737 for (i = 0; i < relocs; i++) { 742 for (i = 0; i < relocs; i++) {
738 unsigned long addr, relval; 743 unsigned long addr, relval;
739 744
@@ -742,12 +747,14 @@ static int load_flat_file(struct linux_binprm *bprm,
742 * relocated (of course, the address has to be 747 * relocated (of course, the address has to be
743 * relocated first). 748 * relocated first).
744 */ 749 */
745 relval = ntohl(reloc[i]); 750 if (get_user(relval, reloc + i))
751 return -EFAULT;
752 relval = ntohl(relval);
746 if (flat_set_persistent(relval, &persistent)) 753 if (flat_set_persistent(relval, &persistent))
747 continue; 754 continue;
748 addr = flat_get_relocate_addr(relval); 755 addr = flat_get_relocate_addr(relval);
749 rp = (unsigned long *) calc_reloc(addr, libinfo, id, 1); 756 rp = (unsigned long __user *)calc_reloc(addr, libinfo, id, 1);
750 if (rp == (unsigned long *)RELOC_FAILED) { 757 if (rp == (unsigned long __user *)RELOC_FAILED) {
751 ret = -ENOEXEC; 758 ret = -ENOEXEC;
752 goto err; 759 goto err;
753 } 760 }