From patchwork Wed Jun 6 14:20:50 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Juerg Haefliger X-Patchwork-Id: 925881 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.ubuntu.com (client-ip=91.189.94.19; helo=huckleberry.canonical.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=canonical.com Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4119p04Z2Tz9s0W; Thu, 7 Jun 2018 00:21:12 +1000 (AEST) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.86_2) (envelope-from ) id 1fQZJA-0003zc-MH; Wed, 06 Jun 2018 14:21:04 +0000 Received: from youngberry.canonical.com ([91.189.89.112]) by huckleberry.canonical.com with esmtps (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:128) (Exim 4.86_2) (envelope-from ) id 1fQZJ4-0003tz-1g for kernel-team@lists.ubuntu.com; Wed, 06 Jun 2018 14:20:58 +0000 Received: from mail-wm0-f69.google.com ([74.125.82.69]) by youngberry.canonical.com with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.76) (envelope-from ) id 1fQZJ3-00046S-QZ for kernel-team@lists.ubuntu.com; Wed, 06 Jun 2018 14:20:57 +0000 Received: by mail-wm0-f69.google.com with SMTP id f65-v6so3172500wmd.2 for ; Wed, 06 Jun 2018 07:20:57 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references; bh=hKzrMvh3ltAhLYplxVZkEVC75zZAuECb0kVv8yH0i5w=; b=mOMGOswhwfggrzrLpzK5a9B4SSD7K1J5yz7rCfvnV3+ByQ3uOUGV82cIAz09heuExF OXtHryouveKAJJGQ7skeh6dh+vMXqTrNJKQ5tp0MZDwU/s4gQLADMLnt62GgzGSI/XOk +aikQrjFIaawfd2VCkjzbxAuw3Qavc2CiI9T0AOVhAfqGVXctN9YCC1o0xGLJJ21r+Fy 0r1Y1h7wyLE6qyvfOhWeimZE/85fJtHxGTs7RpzlXe2sAfRhry+nog7O3Rug9opkmIaz 9dujLF4MRhJYcx27AQjG7FigUzd6ykgxquY+a39mdWOEE02o+AJ59wEc35ot2qEWz/D5 0/pg== X-Gm-Message-State: APt69E1DlRzH4eNVuSbIUCxU/oJys1uy8QKFk4/X4YX1++X246VxyXVy M1vbtwrLkXlMM/5cXF1kLh1UNr/ao7TmKW71kbxbXlSaF9U/KikUacZmWwBLrq/gFn1JazeBUO/ TvH0fYIQ6gJ3qrGEDEvi+HH3S9els9AwG0N8yFcld8Q== X-Received: by 2002:a50:a085:: with SMTP id 5-v6mr3923003edo.261.1528294857079; Wed, 06 Jun 2018 07:20:57 -0700 (PDT) X-Google-Smtp-Source: ADUXVKLw44Y0+7GoK8TE2c+VomIfgT4BcRgxP8j629wF6GYi1OQDyfjkXRvsaV6mz29w6/4VPKL3fw== X-Received: by 2002:a50:a085:: with SMTP id 5-v6mr3922976edo.261.1528294856856; Wed, 06 Jun 2018 07:20:56 -0700 (PDT) Received: from gollum.fritz.box ([81.221.205.149]) by smtp.gmail.com with ESMTPSA id f25-v6sm14810130edd.87.2018.06.06.07.20.55 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 06 Jun 2018 07:20:56 -0700 (PDT) From: Juerg Haefliger X-Google-Original-From: Juerg Haefliger To: kernel-team@lists.ubuntu.com Subject: [SRU][Xenial][PATCH 3/5] x86: Introduce __uaccess_begin_nospec() and uaccess_try_nospec Date: Wed, 6 Jun 2018 16:20:50 +0200 Message-Id: <20180606142052.32684-4-juergh@canonical.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180606142052.32684-1-juergh@canonical.com> References: <20180606142052.32684-1-juergh@canonical.com> X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" From: Dan Williams BugLink: https://bugs.launchpad.net/bugs/1775137 For __get_user() paths, do not allow the kernel to speculate on the value of a user controlled pointer. In addition to the 'stac' instruction for Supervisor Mode Access Protection (SMAP), a barrier_nospec() causes the access_ok() result to resolve in the pipeline before the CPU might take any speculative action on the pointer value. Given the cost of 'stac' the speculation barrier is placed after 'stac' to hopefully overlap the cost of disabling SMAP with the cost of flushing the instruction pipeline. Since __get_user is a major kernel interface that deals with user controlled pointers, the __uaccess_begin_nospec() mechanism will prevent speculative execution past an access_ok() permission check. While speculative execution past access_ok() is not enough to lead to a kernel memory leak, it is a necessary precondition. To be clear, __uaccess_begin_nospec() is addressing a class of potential problems near __get_user() usages. Note, that while the barrier_nospec() in __uaccess_begin_nospec() is used to protect __get_user(), pointer masking similar to array_index_nospec() will be used for get_user() since it incorporates a bounds check near the usage. uaccess_try_nospec provides the same mechanism for get_user_try. No functional changes. Suggested-by: Linus Torvalds Suggested-by: Andi Kleen Suggested-by: Ingo Molnar Signed-off-by: Dan Williams Signed-off-by: Thomas Gleixner Cc: linux-arch@vger.kernel.org Cc: Tom Lendacky Cc: Kees Cook Cc: kernel-hardening@lists.openwall.com Cc: gregkh@linuxfoundation.org Cc: Al Viro Cc: alan@linux.intel.com Link: https://lkml.kernel.org/r/151727415922.33451.5796614273104346583.stgit@dwillia2-desk3.amr.corp.intel.com (backported from commit b3bbfb3fb5d25776b8e3f361d2eedaabb0b496cd) [juergh: Use current_thread_info().] Signed-off-by: Juerg Haefliger --- arch/x86/include/asm/uaccess.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h index e93a69f9a225..4b50bc52ea3e 100644 --- a/arch/x86/include/asm/uaccess.h +++ b/arch/x86/include/asm/uaccess.h @@ -146,6 +146,11 @@ extern int __get_user_bad(void); #define __uaccess_begin() stac() #define __uaccess_end() clac() +#define __uaccess_begin_nospec() \ +({ \ + stac(); \ + barrier_nospec(); \ +}) /* * This is a type: either unsigned long, if the argument fits into @@ -473,6 +478,10 @@ struct __large_struct { unsigned long buf[100]; }; __uaccess_begin(); \ barrier(); +#define uaccess_try_nospec do { \ + current_thread_info()->uaccess_err = 0; \ + __uaccess_begin_nospec(); \ + #define uaccess_catch(err) \ __uaccess_end(); \ (err) |= (current_thread_info()->uaccess_err ? -EFAULT : 0); \