Skip to content

Commit a7e1f67

Browse files
committed
x86/msr: Filter MSR writes
Add functionality to disable writing to MSRs from userspace. Writes can still be allowed by supplying the allow_writes=on module parameter. 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 log writing to MSRs by default. Longer term, such writes will be disabled 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. [ Fix sparse warnings. ] Reported-by: kernel test robot <[email protected]> Signed-off-by: Borislav Petkov <[email protected]> Tested-by: Sean Christopherson <[email protected]> Link: https://lkml.kernel.org/r/[email protected]
1 parent b3a9e3b commit a7e1f67

File tree

1 file changed

+69
-0
lines changed

1 file changed

+69
-0
lines changed

arch/x86/kernel/msr.c

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,14 @@
4242
static struct class *msr_class;
4343
static enum cpuhp_state cpuhp_msr_state;
4444

45+
enum allow_write_msrs {
46+
MSR_WRITES_ON,
47+
MSR_WRITES_OFF,
48+
MSR_WRITES_DEFAULT,
49+
};
50+
51+
static enum allow_write_msrs allow_writes = MSR_WRITES_DEFAULT;
52+
4553
static ssize_t msr_read(struct file *file, char __user *buf,
4654
size_t count, loff_t *ppos)
4755
{
@@ -70,6 +78,24 @@ static ssize_t msr_read(struct file *file, char __user *buf,
7078
return bytes ? bytes : err;
7179
}
7280

81+
static int filter_write(u32 reg)
82+
{
83+
switch (allow_writes) {
84+
case MSR_WRITES_ON: return 0;
85+
case MSR_WRITES_OFF: return -EPERM;
86+
default: break;
87+
}
88+
89+
if (reg == MSR_IA32_ENERGY_PERF_BIAS)
90+
return 0;
91+
92+
pr_err_ratelimited("Write to unrecognized MSR 0x%x by %s\n"
93+
"Please report to [email protected]\n",
94+
reg, current->comm);
95+
96+
return 0;
97+
}
98+
7399
static ssize_t msr_write(struct file *file, const char __user *buf,
74100
size_t count, loff_t *ppos)
75101
{
@@ -84,6 +110,10 @@ static ssize_t msr_write(struct file *file, const char __user *buf,
84110
if (err)
85111
return err;
86112

113+
err = filter_write(reg);
114+
if (err)
115+
return err;
116+
87117
if (count % 8)
88118
return -EINVAL; /* Invalid chunk size */
89119

@@ -92,9 +122,13 @@ static ssize_t msr_write(struct file *file, const char __user *buf,
92122
err = -EFAULT;
93123
break;
94124
}
125+
126+
add_taint(TAINT_CPU_OUT_OF_SPEC, LOCKDEP_STILL_OK);
127+
95128
err = wrmsr_safe_on_cpu(cpu, reg, data[0], data[1]);
96129
if (err)
97130
break;
131+
98132
tmp += 2;
99133
bytes += 8;
100134
}
@@ -242,6 +276,41 @@ static void __exit msr_exit(void)
242276
}
243277
module_exit(msr_exit)
244278

279+
static int set_allow_writes(const char *val, const struct kernel_param *cp)
280+
{
281+
/* val is NUL-terminated, see kernfs_fop_write() */
282+
char *s = strstrip((char *)val);
283+
284+
if (!strcmp(s, "on"))
285+
allow_writes = MSR_WRITES_ON;
286+
else if (!strcmp(s, "off"))
287+
allow_writes = MSR_WRITES_OFF;
288+
else
289+
allow_writes = MSR_WRITES_DEFAULT;
290+
291+
return 0;
292+
}
293+
294+
static int get_allow_writes(char *buf, const struct kernel_param *kp)
295+
{
296+
const char *res;
297+
298+
switch (allow_writes) {
299+
case MSR_WRITES_ON: res = "on"; break;
300+
case MSR_WRITES_OFF: res = "off"; break;
301+
default: res = "default"; break;
302+
}
303+
304+
return sprintf(buf, "%s\n", res);
305+
}
306+
307+
static const struct kernel_param_ops allow_writes_ops = {
308+
.set = set_allow_writes,
309+
.get = get_allow_writes
310+
};
311+
312+
module_param_cb(allow_writes, &allow_writes_ops, NULL, 0600);
313+
245314
MODULE_AUTHOR("H. Peter Anvin <[email protected]>");
246315
MODULE_DESCRIPTION("x86 generic MSR driver");
247316
MODULE_LICENSE("GPL");

0 commit comments

Comments
 (0)