Reading /dev/cpu/*/msr from userspace: operation not permitted

8.6k views Asked by At

I am trying to write a simple application that can read msr registers, and am running this application from userspace.

I have loaded the msr module and given read permissions for everyone to /dev/cpu/*/msr. But still the user is not able to access these files but the root can.

The permissions look like this:

crw-r--r-- 1 root root 202, 0 sep  6 17:55 /dev/cpu/0/msr

crw-r--r-- 1 root root 202, 1 sep  6 17:55 /dev/cpu/1/msr

crw-r--r-- 1 root root 202, 2 sep  6 17:55 /dev/cpu/2/msr

crw-r--r-- 1 root root 202, 3 sep  6 17:55 /dev/cpu/3/msr

I keep getting "Operation not permitted" error message when I try to read these files from userspace but works fine when root tries to access them. What am I doing wrong? I am on Ubuntu 13.04 with kernel version 3.11.0.

4

There are 4 answers

0
Chester Gillon On

Responding to the following in the answer from user Benjamin Peter:

I also heard secure boot must be disabled.

With AlmaLinux 8.7 and a 4.18.0-425.3.1.el8.x86_64 kernel was able to read a MSR when secure boot was enabled.

read_smi_count.c is the code for program tested. Was able to run it to successfully read the MSR_SMI_COUNT (0x34) register. The following is the output after had built the program, which prompts what needs to be done to give the user program access to read the MSR register:

[mr_halfword@skylake-alma release]$ read_smi_count/read_smi_count 
Error: No permission to open /dev/cpu/0/msr. Try:
sudo chmod o+r /dev/cpu/0/msr
[mr_halfword@skylake-alma release]$ sudo chmod o+r /dev/cpu/0/msr
[sudo] password for mr_halfword: 
[mr_halfword@skylake-alma release]$ read_smi_count/read_smi_count 
Error: No permission to open /dev/cpu/0/msr. Try:
sudo setcap cap_sys_rawio=ep read_smi_count/read_smi_count
[mr_halfword@skylake-alma release]$ sudo setcap cap_sys_rawio=ep read_smi_count/read_smi_count
[mr_halfword@skylake-alma release]$ read_smi_count/read_smi_count 
SMI COUNT = 15240

The output of dmesg confirms the Kernel is locked down as a result of EFI secure boot being enabled:

mr_halfword@skylake-alma release]$ dmesg|grep lockdown
[    0.000000] Kernel is locked down from EFI secure boot; see man kernel_lockdown.7
[    1.578247] Lockdown: swapper/0: Hibernation is restricted; see man kernel_lockdown.7
[   37.750117] Lockdown: x86_energy_perf: Direct MSR access is restricted; see man kernel_lockdown.7

The lockdown mode is integrity:

[mr_halfword@skylake-alma release]$ cat /sys/kernel/security/lockdown 
none [integrity]

The above output doesn't show the option of a lockdown mode of confidentiality. Haven't investigated if confidentiality mode would prevent reading of MSR registers.

Linux kernel lockdown, integrity, and confidentiality notes that confidentiality mode applies additional restrictions to prevent reading of secrets from the Kernel.

0
leesagacious On

You can see vfs_read:

ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
{
    ret = rw_verify_area(READ, file, pos, count);
    if (ret >= 0) {
        ...
        if (file->f_op->read)  // your driver read .
            ret = file->f_op->read(file, buf, count, pos);
        else
            ret = do_sync_read(file, buf, count, pos);
        ....

    }
    // here,  if the ret is  13.  your error will be occur.
    return ret;
}
0
Benjamin Peter On

For me (on debian) it helped to set the device permissions after loading the msr module. In addition to the answer of PaulUTK, as root:

setcap cap_sys_rawio=ep <user_executable>

Setting device permission (check before):

ls -l /dev/cpu/*/msr
crw------- ... /dev/cpu/0/msr

I added a group msr and assigned it. As root:

chgrp msr /dev/cpu/*/msr
chmod g+rw /dev/cpu/*/msr
ls -l /dev/cpu/*/msr
crw-rw---- ... /dev/cpu/0/msr

Assign the group to the user:

usermod -aG msr hardworkinguser

Bonus hint:

Apply the group as the hardworkinguser without relogin:

newgrp msr

I also heard secure boot must be disabled.

3
PaulUTK On

Changes in the mainline Linux kernel since around 3.7 now require an executable to have capability CAP_SYS_RAWIO to open the MSR device file [2]. Besides loading the MSR kernel module and setting the appropriate file permissions on the msr device file, one must grant the CAP_SYS_RAWIO capability to any user executable that needs access to the MSR driver, using the command below:

sudo setcap cap_sys_rawio=ep <user_executable>