Received: by 2002:a25:ad19:0:0:0:0:0 with SMTP id y25csp1078148ybi; Fri, 12 Jul 2019 09:19:15 -0700 (PDT) X-Google-Smtp-Source: APXvYqw6UYhGdQdXbhtkCrZpoLLXrGEQdAIUcRNUZDD/WYdevs8HJbZn2yx6Il1hpXNSF1KYGam4 X-Received: by 2002:a17:902:4683:: with SMTP id p3mr11416527pld.31.1562948355272; Fri, 12 Jul 2019 09:19:15 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1562948355; cv=none; d=google.com; s=arc-20160816; b=AvWUloVb7eqClpBlFB4Sk3ItORon+YnhdF1DS/v21oBPCIEXqHAtiMSr2fSiwPFKaZ 2VVirRdaFWqavWiQWkFOYpm6YUwLNuxffi3Srx8S7qy1DNsOyk8I8m6JD9ldToAV7oom 2dKTJilznhvHwZFZX/ndepW4tU2vnaVzh1VS4SawJA1T/AQ/CdEgYQrsSocMqL67Q2KB 0+9D8hr6HeB8gKt+uvVtH4weqOODuq/n07Isduj4GjzrTCGyy63136x8rkYFRtQggM4L Pu/HVdMKIA935tBjJevCNBCLJNXIO+3KMucmEN+Qxh5sCPf9uM9mIVgkE2M6bZgVh851 f7Nw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :message-id:date:subject:cc:to:from; bh=Yqs1skTfixjSuOG4YiACnwRCg5Z7Y5I9dvpffM+qh4g=; b=THgPf6cpDxcUvg1mhAiRv8Z2SOELGvQVZaKJtJIwnrR9YYKuhBXDaBLd/iReUiyI7n HZTp5vyFEQI+TSO9mP5Bmvk5DbmS8PLU2DjvEhQzGB1VoiYxcdS9K7XsgNqeunFHsqTn 2uf3lA/OdwL/Cka7Pvh287RYQqPvUb4wkbyfDipzA43a5cdsUGuPhc8/mkHS022mBReG KRUv1FuaUGBQ1VeiKWtBDrVB04xMc5H9s3COe6f/eRpu7R9F1pPmGbLPFw3NsP4Gxi3i xx8Lpi66oU19UKdjkAYO3hY1Kbmj/PcSjQiad0HDm23Ouo8MvINacjUsXDK/U0hyBTv9 7ZXQ== ARC-Authentication-Results: i=1; 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 sp=NONE dis=NONE) header.from=ispras.ru Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id g18si8388693plq.190.2019.07.12.09.18.59; Fri, 12 Jul 2019 09:19:15 -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 sp=NONE dis=NONE) header.from=ispras.ru Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727031AbfGLQSa (ORCPT + 99 others); Fri, 12 Jul 2019 12:18:30 -0400 Received: from bran.ispras.ru ([83.149.199.196]:30264 "EHLO smtp.ispras.ru" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1726449AbfGLQS3 (ORCPT ); Fri, 12 Jul 2019 12:18:29 -0400 X-Greylist: delayed 303 seconds by postgrey-1.27 at vger.kernel.org; Fri, 12 Jul 2019 12:18:28 EDT Received: from falasarna.intra.ispras.ru (falasarna.intra.ispras.ru [10.10.3.49]) by smtp.ispras.ru (Postfix) with ESMTP id D61F9201D0; Fri, 12 Jul 2019 19:13:23 +0300 (MSK) From: Alexey Izbyshev To: Alexey Dobriyan Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, security@kernel.org, Alexey Izbyshev , Oleg Nesterov Subject: [PATCH] proc: Fix uninitialized byte read in get_mm_cmdline() Date: Fri, 12 Jul 2019 19:09:13 +0300 Message-Id: <20190712160913.17727-1-izbyshev@ispras.ru> X-Mailer: git-send-email 2.21.0 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org get_mm_cmdline() leaks an uninitialized byte located at user-controlled offset in a newly-allocated kernel page in the following scenario. - When reading the last chunk of cmdline, access_remote_vm() fails to copy the requested number of bytes, but still copies enough bytes so that we get into the body of "if (pos + got >= arg_end)" statement. This can be arranged by user, for example, by applying mprotect(PROT_NONE) to the env block. - strnlen() doesn't find a NUL byte. This too can be arranged by user via suitable modifications of argument and env blocks. - The above causes the following condition to be true despite that no NUL byte was found: /* Include the NUL if it existed */ if (got < size) got++; The resulting increment causes the subsequent copy_to_user() to copy an extra byte from "page" to userspace. That byte might come from previous uses of memory referred by "page" before it was allocated by get_mm_cmdline(), potentially leaking data belonging to other processes or kernel. Fix this by ensuring that "size + offset" doesn't exceed the number of bytes copied by access_remote_vm(). Fixes: f5b65348fd77 ("proc: fix missing final NUL in get_mm_cmdline() rewrite") Cc: Alexey Dobriyan Cc: Oleg Nesterov Signed-off-by: Alexey Izbyshev --- This patch was initially sent to accompanied with a little program that exploits the bug to dump the kernel page used in get_mm_cmdline(). Thanks to Oleg Nesterov and Laura Abbott for their feedback! fs/proc/base.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/proc/base.c b/fs/proc/base.c index 255f6754c70d..6e30dd791761 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -275,6 +275,8 @@ static ssize_t get_mm_cmdline(struct mm_struct *mm, char __user *buf, if (got <= offset) break; got -= offset; + if (got < size) + size = got; /* Don't walk past a NUL character once you hit arg_end */ if (pos + got >= arg_end) { -- 2.21.0