From patchwork Sun Jul 24 15:30:21 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicolas Pitre X-Patchwork-Id: 9244919 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 346266089D for ; Sun, 24 Jul 2016 15:31:23 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 260B5265F9 for ; Sun, 24 Jul 2016 15:31:23 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1A01A269E2; Sun, 24 Jul 2016 15:31:23 +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=ham 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 738B82623C for ; Sun, 24 Jul 2016 15:31:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752322AbcGXPbE (ORCPT ); Sun, 24 Jul 2016 11:31:04 -0400 Received: from alt13.smtp-out.videotron.ca ([135.19.0.26]:52540 "EHLO alt12.smtp-out.videotron.ca" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1752100AbcGXPal (ORCPT ); Sun, 24 Jul 2016 11:30:41 -0400 Received: from yoda.home ([96.23.157.65]) by Videotron with SMTP id RLMUbx2oZHh2dRLMVbZL9N; Sun, 24 Jul 2016 11:30:39 -0400 X-Authority-Analysis: v=2.1 cv=Lv0ysipc 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=-idCLtiN88whoaIA1WcA:9 a=hxSL6KlSJACab5C9:21 a=7q3AuHUVWiNrc2AV: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 E58B72DA0697; Sun, 24 Jul 2016 11:30:35 -0400 (EDT) From: Nicolas Pitre To: Greg Ungerer , linux-fsdevel@vger.kernel.org Cc: Alan Cox , Alexander Viro , David Howells , linux-arm-kernel@lists.infradead.org, linux-m68k@lists.linux-m68k.org, linux-kernel@vger.kernel.org Subject: [PATCH v5 07/15] binfmt_flat: use proper user space accessors with relocs processing code Date: Sun, 24 Jul 2016 11:30:21 -0400 Message-Id: <1469374229-21585-8-git-send-email-nicolas.pitre@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1469374229-21585-1-git-send-email-nicolas.pitre@linaro.org> References: <1469374229-21585-1-git-send-email-nicolas.pitre@linaro.org> X-CMAE-Envelope: MS4wfHJdigL4HZsTbhxaz3Sua2cw0NUAr3hlt0h5DN0toKIxzm6ETgoexfeV2ffOvdecIC9LaHHlVDzGtIKi5D/lIbkjWAAx3LXJUP23wv9EGvDDNIhoi5EL 3+gZ19vvG8VB3V5jSU3HKSCiO8dM1920VnLVJlsUKl8oiLyndLkMDWT6+EdReEQfwmWu3RmvZXIog63p4tXMgqF8wHX8IXgE6K4OvIPef3qOtQ+13qKINqXo sY8JwfMX3d4jgE6LECL06TbYA4PujkyQrsbJWSf3FxE6d18pprtADwfLHZVOrJ3NWx4nV5dke2YJ0HDuyzGRmpk0Yglb7TeFQJj8xZoDE51h1KrE7MFX1xer AgVMcJFLoGtONtDVfdvTyHpKbN1nnb8K5MieypCoI4KKfPaZ4gcesPhCI5uEU5E0pkU43ZPn1DmlDQLzy3s17ZZpUu01ey+IvY7k5o11OjyxW3gBqJA= 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. 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 Reviewed-by: Greg Ungerer --- fs/binfmt_flat.c | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c index 5dc7968a42..9deafb282d 100644 --- a/fs/binfmt_flat.c +++ b/fs/binfmt_flat.c @@ -419,7 +419,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; @@ -591,7 +591,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; @@ -616,7 +616,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; @@ -708,15 +708,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; } } } @@ -733,7 +738,7 @@ 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; @@ -742,12 +747,14 @@ static int load_flat_file(struct linux_binprm *bprm, * 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; }