Deny all userspace MSR writes except those explicitly whitelisted for
i915 thermal controls. Without this, processes with CAP_SYS_RAWIO can
run arbitrary kernel code via MSR writing.
BUG=chromium-os:38756
TEST=link build, wrmsr works only on i915 thermal registers
Change-Id: Iff5b9a466dbddd5d94e9246ff99b63a21c975406
Signed-off-by: Kees Cook <keescook@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/42910
Reviewed-by: Mandeep Singh Baines <msb@chromium.org>
#include <linux/notifier.h>
#include <linux/uaccess.h>
#include <linux/gfp.h>
#include <linux/notifier.h>
#include <linux/uaccess.h>
#include <linux/gfp.h>
+#include <linux/ratelimit.h>
#include <asm/processor.h>
#include <asm/msr.h>
#include <asm/processor.h>
#include <asm/msr.h>
return bytes ? bytes : err;
}
return bytes ? bytes : err;
}
+/*
+ * TODO(keescook): This check should just return -EPERM for all registers.
+ * crosbug.com/38756
+ */
+static int msr_write_allowed(u32 reg)
+{
+ switch (reg) {
+ case 0x19a:
+ case 0x610:
+ case 0x64c:
+ /* Allowed: i915 thermal controls. */
+ return 0;
+ default:
+ break;
+ }
+
+ /* Everything else: denied. */
+ printk_ratelimited(KERN_ERR "msr: write denied: register 0x%x " \
+ "not whitelisted by driver.\n", reg);
+ return -EPERM;
+}
+
static ssize_t msr_write(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
static ssize_t msr_write(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
if (count % 8)
return -EINVAL; /* Invalid chunk size */
if (count % 8)
return -EINVAL; /* Invalid chunk size */
+ err = msr_write_allowed(reg);
+ if (err)
+ return err;
for (; count; count -= 8) {
if (copy_from_user(&data, tmp, 8)) {
for (; count; count -= 8) {
if (copy_from_user(&data, tmp, 8)) {
+ err = msr_write_allowed(regs[1]);
+ if (err)
+ break;
err = wrmsr_safe_regs_on_cpu(cpu, regs);
if (err)
break;
err = wrmsr_safe_regs_on_cpu(cpu, regs);
if (err)
break;