Received: by 2002:a05:6a10:16a7:0:0:0:0 with SMTP id gp39csp3890171pxb; Tue, 17 Nov 2020 06:17:34 -0800 (PST) X-Google-Smtp-Source: ABdhPJwt/wFBa1y3KVCJdylF858FJsylBBnQB9lF64xKmrFDuYgjiq0eGJ3QFf5kNdVJyNoC/M+O X-Received: by 2002:aa7:c40b:: with SMTP id j11mr20240628edq.151.1605622654525; Tue, 17 Nov 2020 06:17:34 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1605622654; cv=none; d=google.com; s=arc-20160816; b=TfbmIvEhWpa3Nw6Sb+94PLUxMC+dXkscBUxRYg1eZ77CTQ8TTKjhbtNroZP28WtW74 WSCmtVMI1F6/zPivef6ujFFpC+wPFMNOYyM23jqQeL+lLwm8G5Kz/amVx8MnNhrO8DoZ Hs2XMpuwYGgmK1TgUJSVGfGUQ0Fgii/4/ObBsHqiNFXMvny24VUBvZPNbiPRVFV8uRJv IgsqqfG0HZYSVAtPjgb4AdcugSe3Rk1prD9o/HfWEDaeM5c2aU4OJnabbtuJNnSp8IgA hEwCL+QBpqCfWGM5jKE7YnPYxVqgu7HbF+Euql4jUUT9FskZ57fPcUlfdwxGEhPvNzIu OJaA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=Wi83jmS1Oz2KJOxvn3dMff0JOBW9W+winwBy+EcYHLI=; b=WN/BDiO6EHObw5WlKwIvV6D+Y3EJXugBw8e6vnV2wFfmrkpBMuUsPk1oY9MWczt8hJ 69n6iygvrX0r/N7njxgzRVRSMON/S3jUBuUCQJkh6TUvxGI2DQ8JpHpLaFKptGrZGKrf PiZQyrAaI1PsvI+Dg0YM6KOF4H0qgR+jLKkpdtqrriM+BDx9qWzGm7aQVRxnWyNIzkds VTBb3YFX2Ha5q47npX2xOrEB342MP/n/m1B+hO1WeHKFZ9jBmjawni8B2uOWIo7ASJOg QSk8r4QkJS2G07pBIH6jnGVvsRhHcnrs/DQsJoCzIBojPkRbnG+Avklf407vF3vulEZh P6Eg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=TfGjB7+g; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id g15si4064896ejc.324.2020.11.17.06.17.08; Tue, 17 Nov 2020 06:17:34 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=TfGjB7+g; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729225AbgKQNIF (ORCPT + 99 others); Tue, 17 Nov 2020 08:08:05 -0500 Received: from mail.kernel.org ([198.145.29.99]:36512 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729215AbgKQNIB (ORCPT ); Tue, 17 Nov 2020 08:08:01 -0500 Received: from localhost (83-86-74-64.cable.dynamic.v4.ziggo.nl [83.86.74.64]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 228CD246BF; Tue, 17 Nov 2020 13:07:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1605618480; bh=NsSMxTTXiXeT1xzRNNesefAXSNHTiC/wjqSL1jedHOI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=TfGjB7+gXdYGWBTPuWuLcoJz5kM55xLxyomJ8Zx8ppZtXjJ19GXA0GmBm+NVNArhp w4HPj3lSwmqLlzdWHkqC2UxjT6JpsxxU369WYAcdGYcS/ki8Q+rMph5GxqznvPwv7v 6SgpZZCKHmwIYZaF1gfdmzBCjOTPnLQwQG2zTWWU= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Anand K Mistry , Borislav Petkov , Thomas Gleixner , Tom Lendacky Subject: [PATCH 4.4 47/64] x86/speculation: Allow IBPB to be conditionally enabled on CPUs with always-on STIBP Date: Tue, 17 Nov 2020 14:05:10 +0100 Message-Id: <20201117122108.484682239@linuxfoundation.org> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20201117122106.144800239@linuxfoundation.org> References: <20201117122106.144800239@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Anand K Mistry commit 1978b3a53a74e3230cd46932b149c6e62e832e9a upstream. On AMD CPUs which have the feature X86_FEATURE_AMD_STIBP_ALWAYS_ON, STIBP is set to on and spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT_PREFERRED At the same time, IBPB can be set to conditional. However, this leads to the case where it's impossible to turn on IBPB for a process because in the PR_SPEC_DISABLE case in ib_prctl_set() the spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT_PREFERRED condition leads to a return before the task flag is set. Similarly, ib_prctl_get() will return PR_SPEC_DISABLE even though IBPB is set to conditional. More generally, the following cases are possible: 1. STIBP = conditional && IBPB = on for spectre_v2_user=seccomp,ibpb 2. STIBP = on && IBPB = conditional for AMD CPUs with X86_FEATURE_AMD_STIBP_ALWAYS_ON The first case functions correctly today, but only because spectre_v2_user_ibpb isn't updated to reflect the IBPB mode. At a high level, this change does one thing. If either STIBP or IBPB is set to conditional, allow the prctl to change the task flag. Also, reflect that capability when querying the state. This isn't perfect since it doesn't take into account if only STIBP or IBPB is unconditionally on. But it allows the conditional feature to work as expected, without affecting the unconditional one. [ bp: Massage commit message and comment; space out statements for better readability. ] Fixes: 21998a351512 ("x86/speculation: Avoid force-disabling IBPB based on STIBP and enhanced IBRS.") Signed-off-by: Anand K Mistry Signed-off-by: Borislav Petkov Acked-by: Thomas Gleixner Acked-by: Tom Lendacky Link: https://lkml.kernel.org/r/20201105163246.v2.1.Ifd7243cd3e2c2206a893ad0a5b9a4f19549e22c6@changeid Signed-off-by: Greg Kroah-Hartman --- arch/x86/kernel/cpu/bugs.c | 52 ++++++++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 19 deletions(-) --- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c @@ -1223,6 +1223,14 @@ static int ssb_prctl_set(struct task_str return 0; } +static bool is_spec_ib_user_controlled(void) +{ + return spectre_v2_user_ibpb == SPECTRE_V2_USER_PRCTL || + spectre_v2_user_ibpb == SPECTRE_V2_USER_SECCOMP || + spectre_v2_user_stibp == SPECTRE_V2_USER_PRCTL || + spectre_v2_user_stibp == SPECTRE_V2_USER_SECCOMP; +} + static int ib_prctl_set(struct task_struct *task, unsigned long ctrl) { switch (ctrl) { @@ -1230,17 +1238,26 @@ static int ib_prctl_set(struct task_stru if (spectre_v2_user_ibpb == SPECTRE_V2_USER_NONE && spectre_v2_user_stibp == SPECTRE_V2_USER_NONE) return 0; - /* - * Indirect branch speculation is always disabled in strict - * mode. It can neither be enabled if it was force-disabled - * by a previous prctl call. + /* + * With strict mode for both IBPB and STIBP, the instruction + * code paths avoid checking this task flag and instead, + * unconditionally run the instruction. However, STIBP and IBPB + * are independent and either can be set to conditionally + * enabled regardless of the mode of the other. + * + * If either is set to conditional, allow the task flag to be + * updated, unless it was force-disabled by a previous prctl + * call. Currently, this is possible on an AMD CPU which has the + * feature X86_FEATURE_AMD_STIBP_ALWAYS_ON. In this case, if the + * kernel is booted with 'spectre_v2_user=seccomp', then + * spectre_v2_user_ibpb == SPECTRE_V2_USER_SECCOMP and + * spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT_PREFERRED. */ - if (spectre_v2_user_ibpb == SPECTRE_V2_USER_STRICT || - spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT || - spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT_PREFERRED || + if (!is_spec_ib_user_controlled() || task_spec_ib_force_disable(task)) return -EPERM; + task_clear_spec_ib_disable(task); task_update_spec_tif(task); break; @@ -1253,10 +1270,10 @@ static int ib_prctl_set(struct task_stru if (spectre_v2_user_ibpb == SPECTRE_V2_USER_NONE && spectre_v2_user_stibp == SPECTRE_V2_USER_NONE) return -EPERM; - if (spectre_v2_user_ibpb == SPECTRE_V2_USER_STRICT || - spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT || - spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT_PREFERRED) + + if (!is_spec_ib_user_controlled()) return 0; + task_set_spec_ib_disable(task); if (ctrl == PR_SPEC_FORCE_DISABLE) task_set_spec_ib_force_disable(task); @@ -1319,20 +1336,17 @@ static int ib_prctl_get(struct task_stru if (spectre_v2_user_ibpb == SPECTRE_V2_USER_NONE && spectre_v2_user_stibp == SPECTRE_V2_USER_NONE) return PR_SPEC_ENABLE; - else if (spectre_v2_user_ibpb == SPECTRE_V2_USER_STRICT || - spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT || - spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT_PREFERRED) - return PR_SPEC_DISABLE; - else if (spectre_v2_user_ibpb == SPECTRE_V2_USER_PRCTL || - spectre_v2_user_ibpb == SPECTRE_V2_USER_SECCOMP || - spectre_v2_user_stibp == SPECTRE_V2_USER_PRCTL || - spectre_v2_user_stibp == SPECTRE_V2_USER_SECCOMP) { + else if (is_spec_ib_user_controlled()) { if (task_spec_ib_force_disable(task)) return PR_SPEC_PRCTL | PR_SPEC_FORCE_DISABLE; if (task_spec_ib_disable(task)) return PR_SPEC_PRCTL | PR_SPEC_DISABLE; return PR_SPEC_PRCTL | PR_SPEC_ENABLE; - } else + } else if (spectre_v2_user_ibpb == SPECTRE_V2_USER_STRICT || + spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT || + spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT_PREFERRED) + return PR_SPEC_DISABLE; + else return PR_SPEC_NOT_AFFECTED; }