mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-18 00:24:58 +08:00
Filter MSR writes from user-space by default, and print a syslog entry if
they happen outside the allowed set of MSRs, which is a single one for now, MSR_IA32_ENERGY_PERF_BIAS. The plan is to eventually disable MSR writes by default (they can still be enabled via allow_writes=on). Signed-off-by: Ingo Molnar <mingo@kernel.org> -----BEGIN PGP SIGNATURE----- iQJFBAABCgAvFiEEBpT5eoXrXCwVQwEKEnMQ0APhK1gFAl8oWVwRHG1pbmdvQGtl cm5lbC5vcmcACgkQEnMQ0APhK1j61Q/+KDteLFjfVaJIEe0yfZ8YWjAPb1HRDg1u ia8wyZael5hHpLOQSOhkaTwbvF8dMSLK3oky8ZO2oA5gv99jyB+OZxOGS6mvMcGM aI9chECEghlvUKy1i+NNHSK4W9p4SSu0eK57EkX1VRalZmntTVEX7nlw7oI6nacW 8iP7MIqYWdF1QI6n5gDh0i/62/ictOjG2yemooPNh1I5E5Cw+MhOqTZ7gL+nu1M6 e2+oqo9i3+1yBAN3RH4M8tCwrtTwoVnmQlgPAqT5u2eOATu1b8cTOs2/aC6dfcGg 3u1hcbXuQKRE4DuT7QhDJN1cQZt/GMdymTkR7xIlVqzmNPkM+DCiWPujVMU7r2ia z1Chwxd1gmDrX3g6XPrcXneGrasLkHIRAwYS8EN2wZyNIpb71Y9/uWZVJPza6OO2 Gdxz/y1vCYUu43FSy+gCCirWW+h/HFc4BEzikvB+splQPSiJWJw/Nol+xkBnPds7 LjQTpKSXd1nDtDyTsz0nZAp7EEft78Ez2mj4zYNgqZDBXLEiRPES47VEO3Ls9SS4 t7AtIY1GtdUlFIPrA0mrbcggf/gYxJCFofxR2J7gzyH3DFXIlfw9HbS4+r4xv9RP v2wJUwN35y5SJRNymztanArTNPkGXOlcJ3s7nYQk13UQ0hWTtW3e86pMPsi5C3ui 6DjHG8GXWh4= =X+M1 -----END PGP SIGNATURE----- Merge tag 'x86-misc-2020-08-03' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip Pull x86 MSR filtering from Ingo Molnar: "Filter MSR writes from user-space by default, and print a syslog entry if they happen outside the allowed set of MSRs, which is a single one for now, MSR_IA32_ENERGY_PERF_BIAS. The plan is to eventually disable MSR writes by default (they can still be enabled via allow_writes=on)" * tag 'x86-misc-2020-08-03' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/msr: Filter MSR writes
This commit is contained in:
commit
c813e8c9df
@ -42,6 +42,14 @@
|
||||
static struct class *msr_class;
|
||||
static enum cpuhp_state cpuhp_msr_state;
|
||||
|
||||
enum allow_write_msrs {
|
||||
MSR_WRITES_ON,
|
||||
MSR_WRITES_OFF,
|
||||
MSR_WRITES_DEFAULT,
|
||||
};
|
||||
|
||||
static enum allow_write_msrs allow_writes = MSR_WRITES_DEFAULT;
|
||||
|
||||
static ssize_t msr_read(struct file *file, char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
@ -70,6 +78,24 @@ static ssize_t msr_read(struct file *file, char __user *buf,
|
||||
return bytes ? bytes : err;
|
||||
}
|
||||
|
||||
static int filter_write(u32 reg)
|
||||
{
|
||||
switch (allow_writes) {
|
||||
case MSR_WRITES_ON: return 0;
|
||||
case MSR_WRITES_OFF: return -EPERM;
|
||||
default: break;
|
||||
}
|
||||
|
||||
if (reg == MSR_IA32_ENERGY_PERF_BIAS)
|
||||
return 0;
|
||||
|
||||
pr_err_ratelimited("Write to unrecognized MSR 0x%x by %s\n"
|
||||
"Please report to x86@kernel.org\n",
|
||||
reg, current->comm);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t msr_write(struct file *file, const char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
@ -84,6 +110,10 @@ static ssize_t msr_write(struct file *file, const char __user *buf,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = filter_write(reg);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (count % 8)
|
||||
return -EINVAL; /* Invalid chunk size */
|
||||
|
||||
@ -92,9 +122,13 @@ static ssize_t msr_write(struct file *file, const char __user *buf,
|
||||
err = -EFAULT;
|
||||
break;
|
||||
}
|
||||
|
||||
add_taint(TAINT_CPU_OUT_OF_SPEC, LOCKDEP_STILL_OK);
|
||||
|
||||
err = wrmsr_safe_on_cpu(cpu, reg, data[0], data[1]);
|
||||
if (err)
|
||||
break;
|
||||
|
||||
tmp += 2;
|
||||
bytes += 8;
|
||||
}
|
||||
@ -242,6 +276,41 @@ static void __exit msr_exit(void)
|
||||
}
|
||||
module_exit(msr_exit)
|
||||
|
||||
static int set_allow_writes(const char *val, const struct kernel_param *cp)
|
||||
{
|
||||
/* val is NUL-terminated, see kernfs_fop_write() */
|
||||
char *s = strstrip((char *)val);
|
||||
|
||||
if (!strcmp(s, "on"))
|
||||
allow_writes = MSR_WRITES_ON;
|
||||
else if (!strcmp(s, "off"))
|
||||
allow_writes = MSR_WRITES_OFF;
|
||||
else
|
||||
allow_writes = MSR_WRITES_DEFAULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_allow_writes(char *buf, const struct kernel_param *kp)
|
||||
{
|
||||
const char *res;
|
||||
|
||||
switch (allow_writes) {
|
||||
case MSR_WRITES_ON: res = "on"; break;
|
||||
case MSR_WRITES_OFF: res = "off"; break;
|
||||
default: res = "default"; break;
|
||||
}
|
||||
|
||||
return sprintf(buf, "%s\n", res);
|
||||
}
|
||||
|
||||
static const struct kernel_param_ops allow_writes_ops = {
|
||||
.set = set_allow_writes,
|
||||
.get = get_allow_writes
|
||||
};
|
||||
|
||||
module_param_cb(allow_writes, &allow_writes_ops, NULL, 0600);
|
||||
|
||||
MODULE_AUTHOR("H. Peter Anvin <hpa@zytor.com>");
|
||||
MODULE_DESCRIPTION("x86 generic MSR driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
Loading…
Reference in New Issue
Block a user