From patchwork Tue Jul 12 21:27:37 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicolas Pitre X-Patchwork-Id: 9226259 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id B8BD260871 for ; Tue, 12 Jul 2016 21:44:54 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id AED6327D29 for ; Tue, 12 Jul 2016 21:44:54 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A3CC5272AA; Tue, 12 Jul 2016 21:44:54 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 25DDF27F9E for ; Tue, 12 Jul 2016 21:44:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752013AbcGLVnk (ORCPT ); Tue, 12 Jul 2016 17:43:40 -0400 Received: from alt22.smtp-out.videotron.ca ([70.80.0.73]:53619 "EHLO alt22.smtp-out.videotron.ca" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752000AbcGLVnj (ORCPT ); Tue, 12 Jul 2016 17:43:39 -0400 Received: from yoda.home ([96.23.157.65]) by Videotron with SMTP id N5DlbZxrpzCgpN5DmbODPI; Tue, 12 Jul 2016 17:28:02 -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=l9tmOqL0Dy40VvG665wA:9 a=fPom8XY73oTNoMuS:21 a=ln4dNxqUidl9LKeb:21 Received: from xanadu.home (xanadu.home [192.168.2.2]) by yoda.home (Postfix) with ESMTP id 1FFBB2DA0683; Tue, 12 Jul 2016 17:28:00 -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 05/10] binfmt_flat: use proper user space accessors with relocs processing code Date: Tue, 12 Jul 2016 17:27:37 -0400 Message-Id: <1468358862-11799-6-git-send-email-nicolas.pitre@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1468358862-11799-1-git-send-email-nicolas.pitre@linaro.org> References: <1468358862-11799-1-git-send-email-nicolas.pitre@linaro.org> X-CMAE-Envelope: MS4wfNAVkXSoup1ct6R4bHdC1CAJoF0KM8EmOB78CDnEhLfgho8UXjObIuOh7yrTk35Yn8nmPfj2cRtW8Vk5Vm/FCqLzWATOrStLWgnkMhojg6VMOkB+Heda uNBnWrT8B9ei93yh7+L1LJV/pQhffUM6a6jwpjqtj0f48pljIR+B7RjdPA4g3JEDkLz/O1xKxMeA++GLnS47cAevt5QPBVvOkdaXY8qi+msQdVIBHScyxgOb hz3M0iIKfyj2WhYkyi7iJFy/H8FH+1bFb+3Bk3/0iIZRbWmTChIGbKuFsBQaIdYIscr6meCDnClfd4nrxXQT8A== Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Relocs are fixed up in place in user space memory. The appropriate accessors are required for this code to work with an active MMU. Only those architectures with trivial architecture-specific handlers are covered by this patch. Incidentally, those NOMMU architectures that can also have a MMU are amongst the trivial ones so it should be fine. --- arch/arm/include/asm/flat.h | 5 +++-- arch/m68k/include/asm/flat.h | 5 +++-- arch/sh/include/asm/flat.h | 5 +++-- arch/xtensa/include/asm/flat.h | 5 +++-- fs/binfmt_flat.c | 31 +++++++++++++++++++------------ 5 files changed, 31 insertions(+), 20 deletions(-) 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/arch/sh/include/asm/flat.h b/arch/sh/include/asm/flat.h index 5d84df5e27..0f4f49ed6b 100644 --- a/arch/sh/include/asm/flat.h +++ b/arch/sh/include/asm/flat.h @@ -15,8 +15,9 @@ #define flat_argvp_envp_on_stack() 0 #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) #define flat_set_persistent(relval, p) ({ (void)p; 0; }) diff --git a/arch/xtensa/include/asm/flat.h b/arch/xtensa/include/asm/flat.h index 94c44abf15..fffad219af 100644 --- a/arch/xtensa/include/asm/flat.h +++ b/arch/xtensa/include/asm/flat.h @@ -4,8 +4,9 @@ #define flat_argvp_envp_on_stack() 0 #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) #define flat_set_persistent(relval, p) 0 diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c index 9538901fe8..fc0ee3ed5d 100644 --- a/fs/binfmt_flat.c +++ b/fs/binfmt_flat.c @@ -438,7 +438,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; @@ -600,7 +600,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; @@ -625,7 +625,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; @@ -718,15 +718,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; } } } @@ -743,19 +748,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; }