Received: by 2002:a25:683:0:0:0:0:0 with SMTP id 125csp371210ybg; Fri, 12 Jun 2020 03:54:49 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxoZ1dseBzAbUMkUAoSOEBmoKOo8JQVAUtPDm+QDnqkbulf001JfCqdcMhAhrYMgoHZcG68 X-Received: by 2002:a17:906:e257:: with SMTP id gq23mr11875292ejb.398.1591959289061; Fri, 12 Jun 2020 03:54:49 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1591959289; cv=none; d=google.com; s=arc-20160816; b=DixONuGYW2TOHsgQ7d1PJUldqx6Xwgsl5irO5EXf+qdLVND0rhzFHZt4ABxrX56Khu 5j/rWzsXiuew/vbHp7nJye46nKMMnv2qVxwHFIdyBPNAIRePV+XV5EPNVE3jaJ/fA7S/ pbEoxbpPYtIJomXZqpWcPCj/Bj7YZzQgQ7Lj9gHy8/3iHqaUvXoEuv0AbR71ytdaYrBe BQU4JBVJnLsmRBvKgp/smoUo1ik5RPtK53fuNY+HgfQC1XpEK4BXrjRb8Xw1qmU5Z/7w 4+d6i7Re023Y870DiW1XzBKVZ+8hu+foXkJ5qXZK1SSzWq8k9sGlPu7Ykzo0lz9TTzEA gc1w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-disposition:mime-version :message-id:subject:cc:to:from:date:dkim-signature; bh=i67OvWK19gpLvFCtSsadQeL9dLaZioiCanotMz9MAN4=; b=e4YEt5ybcWOi3fBVv6mPjPcZHuBmyUMEwRhhLDAX6df3EXqq81CFYBxTVYdUIPH6Ze xYxBb87C77MvevnXO3FrPhQvVD7qQ9lLSNX7pf71ynET67Fg4iJ3OyDuvDJUJRVXfuUc GpWraxcLEjA6lIMBidJvANJxwFmPcA2XKxe6HTCOWd0V13lW/HrR5T6IfQClzoGC5pU5 Ew9xMyd/bLy/YRaer39vua7e7SHIXmvdVeLeEaRLkxyho6r3IKuEoMekJf3uwuDb4fiO ym1jPGRJtfvr7sO/FTdiNjaaC10HLBd7wL+Lr8Wj2h0l88e0tk6YND9lDw4BPYG/IeN5 H2tg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@alien8.de header.s=dkim header.b=n2lti7DG; 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=pass (p=NONE sp=NONE dis=NONE) header.from=alien8.de Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id z18si3553482ejb.75.2020.06.12.03.54.26; Fri, 12 Jun 2020 03:54:49 -0700 (PDT) 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=@alien8.de header.s=dkim header.b=n2lti7DG; 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=pass (p=NONE sp=NONE dis=NONE) header.from=alien8.de Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726306AbgFLKui (ORCPT + 99 others); Fri, 12 Jun 2020 06:50:38 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50344 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726219AbgFLKui (ORCPT ); Fri, 12 Jun 2020 06:50:38 -0400 Received: from mail.skyhub.de (mail.skyhub.de [IPv6:2a01:4f8:190:11c2::b:1457]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 95B54C03E96F for ; Fri, 12 Jun 2020 03:50:37 -0700 (PDT) Received: from zn.tnic (p200300ec2f0af400c173145ce686c7e8.dip0.t-ipconnect.de [IPv6:2003:ec:2f0a:f400:c173:145c:e686:c7e8]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.skyhub.de (SuperMail on ZX Spectrum 128k) with ESMTPSA id 7CF6D1EC02E0; Fri, 12 Jun 2020 12:50:34 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=alien8.de; s=dkim; t=1591959034; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:in-reply-to:references; bh=i67OvWK19gpLvFCtSsadQeL9dLaZioiCanotMz9MAN4=; b=n2lti7DGntdg6i8Xr02yv60JBjBlu4dSe7Jl39iorfmHHkkPCpskSkS7GPXhxuya1pkyag Zph75nKViDADXboKl4MFuuI2wd94mFYp1gQiFR63xLZgx3g1mHi65f42wY9+Vj0kLxXvxo NX4B+nrVEItKlgBDsIh+QaSLeKqe9Y8= Date: Fri, 12 Jun 2020 12:50:26 +0200 From: Borislav Petkov To: x86-ml , Linus Torvalds Cc: lkml Subject: [RFC PATCH] x86/msr: Filter MSR writes Message-ID: <20200612105026.GA22660@zn.tnic> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hi, so this has been popping up from time to time in the last couple of years so let's have a go at it. The reason for it is explained in the commit message below but basically the goal is to have MSR writes disabled by default on distros and on the general Linux setup and only those who know what they're doing, can reenable them if they really need to. The other, more important goal is to stop the perpetuation of poking at naked MSRs from userspace instead of defining proper functionality and interfaces which synchronize with the kernel's access to those MSRs. Hell, even while testing this, I did # wrmsr --all 0x10 12; rdmsr --all 0x10 0x10 being the TSC MSR and the module wouldn't unload after that. And this is just the latest example of what can go wrong. Now, a concern with questionable validity has been raised that this might break "some tools on github" which poke directly at MSRs. And we don't break userspace. Well, for starters, the functionality is still there - it is just behind a module parameter. Then, it'll hopefully convince people providing the functionality controlled by those MSRs, to design proper interfaces for that. For example, the whitelisted MSR_IA32_ENERGY_PERF_BIAS is used by cpupower in tools/. The hope is that this gets converted to a proper interface too. In any case, let me add Linus as I might be missing some angle here. Thx. -- Disable writing to MSRs from userspace by default. Writes can still be allowed by supplying the allow_writes=1 module parameter and the kernel will be tainted so that it shows in oopses. Having unfettered access to all MSRs on a system is and has always been a disaster waiting to happen. Think performance counter MSRs, MSRs with sticky or locked bits, MSRs making major system changes like loading microcode, MTRRs, PAT configuration, TSC counter, security mitigations MSRs, you name it. This also destroys all the kernel's caching of MSR values for performance, as the recent case with MSR_AMD64_LS_CFG showed. Another example is writing MSRs by mistake by simply typing the wrong MSR address. System freezes have been experienced that way. In general, poking at MSRs under the kernel's feet is a bad bad idea. So disable poking directly at the MSRs by default. If userspace still wants to do that, then proper interfaces should be defined which are under the kernel's control and accesses to those MSRs can be synchronized and sanitized properly. Signed-off-by: Borislav Petkov diff --git a/arch/x86/kernel/msr.c b/arch/x86/kernel/msr.c index 1547be359d7f..931e7b00ffb7 100644 --- a/arch/x86/kernel/msr.c +++ b/arch/x86/kernel/msr.c @@ -41,6 +41,7 @@ static struct class *msr_class; static enum cpuhp_state cpuhp_msr_state; +static bool allow_writes; static ssize_t msr_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) @@ -70,6 +71,18 @@ static ssize_t msr_read(struct file *file, char __user *buf, return bytes ? bytes : err; } +static int filter_write(u32 reg) +{ + switch (reg) { + case MSR_IA32_ENERGY_PERF_BIAS: + return 0; + + default: + pr_err("%s: Filter out MSR write to 0x%x\n", __func__, reg); + return -EPERM; + } +} + static ssize_t msr_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { @@ -84,6 +97,12 @@ static ssize_t msr_write(struct file *file, const char __user *buf, if (err) return err; + if (!allow_writes) { + err = filter_write(reg); + if (err) + return err; + } + if (count % 8) return -EINVAL; /* Invalid chunk size */ @@ -95,11 +114,18 @@ static ssize_t msr_write(struct file *file, const char __user *buf, err = wrmsr_safe_on_cpu(cpu, reg, data[0], data[1]); if (err) break; + tmp += 2; bytes += 8; } - return bytes ? bytes : err; + if (bytes) { + add_taint(TAINT_CPU_OUT_OF_SPEC, LOCKDEP_STILL_OK); + + return bytes; + } + + return err; } static long msr_ioctl(struct file *file, unsigned int ioc, unsigned long arg) @@ -242,6 +268,8 @@ static void __exit msr_exit(void) } module_exit(msr_exit) +module_param(allow_writes, bool, 0400); + MODULE_AUTHOR("H. Peter Anvin "); MODULE_DESCRIPTION("x86 generic MSR driver"); MODULE_LICENSE("GPL");