From patchwork Thu Jun 22 17:38:38 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 9805005 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 52A356086C for ; Thu, 22 Jun 2017 17:38:59 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D9B7B223B2 for ; Thu, 22 Jun 2017 17:38:58 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id CE0BD28707; Thu, 22 Jun 2017 17:38:58 +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=-4.1 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from mother.openwall.net (mother.openwall.net [195.42.179.200]) by mail.wl.linuxfoundation.org (Postfix) with SMTP id E91FA223B2 for ; Thu, 22 Jun 2017 17:38:57 +0000 (UTC) Received: (qmail 22028 invoked by uid 550); 22 Jun 2017 17:38:54 -0000 Mailing-List: contact kernel-hardening-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-ID: Delivered-To: mailing list kernel-hardening@lists.openwall.com Received: (qmail 22002 invoked from network); 22 Jun 2017 17:38:53 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=date:from:to:cc:subject:message-id:mime-version:content-disposition; bh=0FVYDIuHXVgUN53dIjPPToBhQC7Jyw/gtn9FZ8UzwKg=; b=FvtVwE6S+Toa9O7QcdYsL7nWYugdUZMK7daI9Wj32zEsznuof8dDs9ngrN2TFDsig1 M8wstZjqIX722CRn0emZOCG1odu1XWmqKqnC0HPZq0bx/KVoCBui+ni03HOYw1nWOcDu mjZHx24O3ms0EqF8CSwcG27n703DU2bnhxSrg= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:mime-version :content-disposition; bh=0FVYDIuHXVgUN53dIjPPToBhQC7Jyw/gtn9FZ8UzwKg=; b=Fy/MHEwNaZ7Fp6QeCihIYsdaZM7IYsJ2bLf52tCj6nkFCTFPWeKp2SuhSOAwsMnqSN ORlyNi/Yc6qdH4VjMm++rv9rkpaPIJSnEDhcDwqxED9dhyQl35Y+r66uerFQks4nk2c9 Ov7/sjLmaYJ1L/dtwNRbwAhpF1z0KRfBZR/ItUjAdn72FjB+gltj5hRofDO2yq3PZ999 6Z80b3Pav3nWsZqAbiVTyr6Y4kRh9PZrchJIWFYLeIMTUAJrihx/2bLGFU/2nqnrj1aL EZf1whMflyFBhZBh7QxqBxiPPOgof1UD9dU4wIlooOb3TImEjTtYzwC1yqDduaG863wv cXAg== X-Gm-Message-State: AKS2vOzy0UHzzo2ek+z63OlYn9Vvq7RpRxDM/VLTLe04b6YOM1r0uLrv kkt+ez28INO+J1jv X-Received: by 10.98.106.66 with SMTP id f63mr3843726pfc.169.1498153120313; Thu, 22 Jun 2017 10:38:40 -0700 (PDT) Date: Thu, 22 Jun 2017 10:38:38 -0700 From: Kees Cook To: Andrew Morton Cc: Rik van Riel , Daniel Micay , Qualys Security Advisory , Thomas Gleixner , Ingo Molnar , "H. Peter Anvin" , x86@kernel.org, Alexander Viro , Dmitry Safonov , Andy Lutomirski , Grzegorz Andrejczuk , Masahiro Yamada , linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, kernel-hardening@lists.openwall.com Message-ID: <20170622173838.GA43308@beast> MIME-Version: 1.0 Content-Disposition: inline Subject: [kernel-hardening] [PATCH] binfmt_elf: Safely increment argv pointers X-Virus-Scanned: ClamAV using ClamSMTP When building the argv/envp pointers, the envp is needlessly pre-incremented instead of just continuing after the argv pointers are finished. In some (likely impossible) race where the strings could be changed from userspace between copy_strings() and here, it might be possible to confuse the envp position. Instead, just use sp like everything else. Signed-off-by: Kees Cook --- fs/binfmt_elf.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 7465c3ea5dd5..879ff9c7ffd0 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -163,8 +163,6 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec, unsigned long p = bprm->p; int argc = bprm->argc; int envc = bprm->envc; - elf_addr_t __user *argv; - elf_addr_t __user *envp; elf_addr_t __user *sp; elf_addr_t __user *u_platform; elf_addr_t __user *u_base_platform; @@ -304,38 +302,38 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec, /* Now, let's put argc (and argv, envp if appropriate) on the stack */ if (__put_user(argc, sp++)) return -EFAULT; - argv = sp; - envp = argv + argc + 1; - /* Populate argv and envp */ + /* Populate list of argv pointers back to argv strings. */ p = current->mm->arg_end = current->mm->arg_start; while (argc-- > 0) { size_t len; - if (__put_user((elf_addr_t)p, argv++)) + if (__put_user((elf_addr_t)p, sp++)) return -EFAULT; len = strnlen_user((void __user *)p, MAX_ARG_STRLEN); if (!len || len > MAX_ARG_STRLEN) return -EINVAL; p += len; } - if (__put_user(0, argv)) + if (__put_user(0, sp++)) return -EFAULT; - current->mm->arg_end = current->mm->env_start = p; + current->mm->arg_end = p; + + /* Populate list of envp pointers back to envp strings. */ + current->mm->env_end = current->mm->env_start = p; while (envc-- > 0) { size_t len; - if (__put_user((elf_addr_t)p, envp++)) + if (__put_user((elf_addr_t)p, sp++)) return -EFAULT; len = strnlen_user((void __user *)p, MAX_ARG_STRLEN); if (!len || len > MAX_ARG_STRLEN) return -EINVAL; p += len; } - if (__put_user(0, envp)) + if (__put_user(0, sp++)) return -EFAULT; current->mm->env_end = p; /* Put the elf_info on the stack in the right place. */ - sp = (elf_addr_t __user *)envp + 1; if (copy_to_user(sp, elf_info, ei_index * sizeof(elf_addr_t))) return -EFAULT; return 0;