From patchwork Wed Jul 20 04:20:19 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicolas Pitre X-Patchwork-Id: 72398 Delivered-To: patch@linaro.org Received: by 10.140.29.52 with SMTP id a49csp429999qga; Tue, 19 Jul 2016 21:24:12 -0700 (PDT) X-Received: by 10.66.77.194 with SMTP id u2mr71108036paw.90.1468988652695; Tue, 19 Jul 2016 21:24:12 -0700 (PDT) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id o90si1067096pfj.222.2016.07.19.21.24.12; Tue, 19 Jul 2016 21:24:12 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753116AbcGTEXG (ORCPT + 29 others); Wed, 20 Jul 2016 00:23:06 -0400 Received: from alt22.smtp-out.videotron.ca ([70.80.0.73]:38472 "EHLO alt22.smtp-out.videotron.ca" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751453AbcGTEUt (ORCPT ); Wed, 20 Jul 2016 00:20:49 -0400 Received: from yoda.home ([96.23.157.65]) by Videotron with SMTP id Pj03bxEE4zCgpPj04baLVG; Wed, 20 Jul 2016 00:20:48 -0400 X-Authority-Analysis: v=2.1 cv=QfzGxpvv c=1 sm=1 tr=0 a=keA3yYpnlypCNW5BNWqu+w==:117 a=keA3yYpnlypCNW5BNWqu+w==:17 a=L9H7d07YOLsA:10 a=9cW_t1CCXrUA:10 a=s5jvgZ67dGcA:10 a=cAmyUtKerLwA:10 a=KKAkSRfTAAAA:8 a=tBb2bbeoAAAA:8 a=hS0c0Ahk9r2mtBNNZc4A:9 a=fL3dA-5jcTtH-hmY:21 a=aTsD8eXF_iZgZIsW:21 a=cvBusfyB2V15izCimMoJ:22 a=Oj-tNtZlA1e06AYgeCfH:22 Received: from xanadu.home (xanadu.home [192.168.2.2]) by yoda.home (Postfix) with ESMTP id 465482DA0697; Wed, 20 Jul 2016 00:20:46 -0400 (EDT) From: Nicolas Pitre To: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Alexander Viro , David Howells , Greg Ungerer Subject: [PATCH v3 07/12] binfmt_flat: use proper user space accessors with relocs processing code Date: Wed, 20 Jul 2016 00:20:19 -0400 Message-Id: <1468988424-32671-8-git-send-email-nicolas.pitre@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1468988424-32671-1-git-send-email-nicolas.pitre@linaro.org> References: <1468988424-32671-1-git-send-email-nicolas.pitre@linaro.org> X-CMAE-Envelope: MS4wfG7kbdrIlHZzcSJWZAKTz6cjzxn7dw0+g0iyT3nkoWz5lVBwxJJ1/FZv7EkEyFAQbTqXS87lW4VGUE/In0P6I74hXGaFPAmrHtbG4djcGChijJO0GbYK NjuQiW45ChPTa0RunWaOCv6MBDpGG8pcQeaId13E25O57p9G3fzFX+BIlsPQeOsCTdJl6X4Gu2HPG/jMuXnI/NOuI0VvIctgWcbE83nDm2/kpDsOqI5KzT4z 57KgJuti5c0+wlbI+56VeeSpJxzRNvItM/urYFiJxCWUsTVITjq4GiERwYMt4bLQ+ziD8L5DgnXoFuv2BS6FDg== Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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 for ARM and M68K are also covered. 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 Reviewed-by: Greg Ungerer --- arch/arm/include/asm/flat.h | 5 +++-- arch/m68k/include/asm/flat.h | 5 +++-- fs/binfmt_flat.c | 31 +++++++++++++++++++------------ 3 files changed, 25 insertions(+), 16 deletions(-) -- 2.7.4 diff --git a/arch/arm/include/asm/flat.h b/arch/arm/include/asm/flat.h index e847d23351..acf1d14b89 100644 --- a/arch/arm/include/asm/flat.h +++ b/arch/arm/include/asm/flat.h @@ -8,8 +8,9 @@ #define flat_argvp_envp_on_stack() 1 #define flat_old_ram_flag(flags) (flags) #define flat_reloc_valid(reloc, size) ((reloc) <= (size)) -#define flat_get_addr_from_rp(rp, relval, flags, persistent) ((void)persistent,get_unaligned(rp)) -#define flat_put_addr_at_rp(rp, val, relval) put_unaligned(val,rp) +#define flat_get_addr_from_rp(rp, relval, flags, persistent) \ + ({ unsigned long __val; __get_user_unaligned(__val, rp); __val; }) +#define flat_put_addr_at_rp(rp, val, relval) __put_user_unaligned(val, rp) #define flat_get_relocate_addr(rel) (rel) #define flat_set_persistent(relval, p) 0 diff --git a/arch/m68k/include/asm/flat.h b/arch/m68k/include/asm/flat.h index f9454b89a5..f3f592d03e 100644 --- a/arch/m68k/include/asm/flat.h +++ b/arch/m68k/include/asm/flat.h @@ -8,8 +8,9 @@ #define flat_argvp_envp_on_stack() 1 #define flat_old_ram_flag(flags) (flags) #define flat_reloc_valid(reloc, size) ((reloc) <= (size)) -#define flat_get_addr_from_rp(rp, relval, flags, p) get_unaligned(rp) -#define flat_put_addr_at_rp(rp, val, relval) put_unaligned(val,rp) +#define flat_get_addr_from_rp(rp, relval, flags, p) \ + ({ unsigned long __val; __get_user_unaligned(__val, rp); __val; }) +#define flat_put_addr_at_rp(rp, val, relval) __put_user_unaligned(val, rp) #define flat_get_relocate_addr(rel) (rel) static inline int flat_set_persistent(unsigned long relval, diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c index 90a10d7149..34f815540e 100644 --- a/fs/binfmt_flat.c +++ b/fs/binfmt_flat.c @@ -423,7 +423,7 @@ static int load_flat_file(struct linux_binprm * bprm, unsigned long textpos, datapos, realdatastart; unsigned long text_len, data_len, bss_len, stack_len, full_data, flags; unsigned long len, memp, memp_size, extra, rlim; - unsigned long *reloc, *rp; + unsigned long __user *reloc, *rp; struct inode *inode; int i, rev, relocs; loff_t fpos; @@ -595,7 +595,7 @@ static int load_flat_file(struct linux_binprm * bprm, goto err; } - reloc = (unsigned long *) + reloc = (unsigned long __user *) (datapos + (ntohl(hdr->reloc_start) - text_len)); memp = realdatastart; memp_size = len; @@ -620,7 +620,7 @@ static int load_flat_file(struct linux_binprm * bprm, MAX_SHARED_LIBS * sizeof(unsigned long), FLAT_DATA_ALIGN); - reloc = (unsigned long *) + reloc = (unsigned long __user *) (datapos + (ntohl(hdr->reloc_start) - text_len)); memp = textpos; memp_size = len; @@ -713,15 +713,20 @@ static int load_flat_file(struct linux_binprm * bprm, * image. */ if (flags & FLAT_FLAG_GOTPIC) { - for (rp = (unsigned long *)datapos; *rp != 0xffffffff; rp++) { - unsigned long addr; - if (*rp) { - addr = calc_reloc(*rp, libinfo, id, 0); + for (rp = (unsigned long __user *)datapos; ; rp++) { + unsigned long addr, rp_val; + if (get_user(rp_val, rp)) + return -EFAULT; + if (rp_val == 0xffffffff) + break; + if (rp_val) { + addr = calc_reloc(rp_val, libinfo, id, 0); if (addr == RELOC_FAILED) { ret = -ENOEXEC; goto err; } - *rp = addr; + if (put_user(addr, rp)) + return -EFAULT; } } } @@ -738,19 +743,21 @@ static int load_flat_file(struct linux_binprm * bprm, * __start to address 4 so that is okay). */ if (rev > OLD_FLAT_VERSION) { - unsigned long persistent = 0; + unsigned long __maybe_unused persistent = 0; for (i=0; i < relocs; i++) { unsigned long addr, relval; /* Get the address of the pointer to be relocated (of course, the address has to be relocated first). */ - relval = ntohl(reloc[i]); + if (get_user(relval, reloc + i)) + return -EFAULT; + relval = ntohl(relval); if (flat_set_persistent (relval, &persistent)) continue; addr = flat_get_relocate_addr(relval); - rp = (unsigned long *) calc_reloc(addr, libinfo, id, 1); - if (rp == (unsigned long *)RELOC_FAILED) { + rp = (unsigned long __user *)calc_reloc(addr, libinfo, id, 1); + if (rp == (unsigned long __user *)RELOC_FAILED) { ret = -ENOEXEC; goto err; }