** Description changed: [ Impact ] - * Running rdmsr or wrmsr with the -a (all processors) flag - when the msr kernel module is not loaded causes an immediate - Segmentation Fault. + * Running rdmsr or wrmsr with the -a (all processors) flag + when the msr kernel module is not loaded causes an immediate + Segmentation Fault. - * The utilities use scandir() to list CPU device nodes under /dev/cpu. - When the msr module is absent, /dev/cpu does not exist on the filesystem, - causing scandir() to return -1. Neither utility checks for a negative - return value and proceeds directly into a loop, dereferencing an - uninitialized namelist pointer (namelist[-2]). + * The utilities use scandir() to list CPU device nodes under /dev/cpu. + When the msr module is absent, /dev/cpu does not exist on the filesystem, + causing scandir() to return -1. Neither utility checks for a negative + return value and proceeds directly into a loop, dereferencing an + uninitialized namelist pointer (namelist[-2]). - * Users or automation scripts querying hardware registers across all CPU - cores on bare-metal systems encounter unhandled crashes instead of an - informative error message. + * Users or automation scripts querying hardware registers across all CPU + cores on bare-metal systems encounter unhandled crashes instead of an + informative error message. - * The fix adds error handling after the scandir() call in both rdmsr.c - and wrmsr.c. If /dev/cpu is missing or unreadable, the utilities print - a clean diagnostic message advising the user to load the msr driver - and exit gracefully with status 1. + * The fix adds error handling after the scandir() call in both rdmsr.c + and wrmsr.c. If /dev/cpu is missing or unreadable, the utilities print + a clean diagnostic message advising the user to load the msr driver + and exit gracefully with status 1. [ Test Plan ] - * [0] msr-tools will be tested in the following environments: - - Stonking (26.10 LTS) - - Resolute (26.04 LTS) - - Noble (24.04 LTS) - - Jammy (22.04 LTS) - - You can reproduce this in a bare metal machine - (or an environment where MSR access is supported). + * [0] msr-tools will be tested in the following environments: + - Stonking (26.10 LTS) + - Resolute (26.04 LTS) + - Noble (24.04 LTS) + - Jammy (22.04 LTS) - I reproduced this on a Multipass VM, e.g. - multipass launch \ - --cpus 4 \ - --memory 8GB \ - --disk 25GB \ - --name sandbox-stonking \ - stonking + You can reproduce this in a bare metal machine + (or an environment where MSR access is supported). - * [1] Install msr-tools: - sudo apt update && sudo apt install -y msr-tools + I reproduced this on a Multipass VM, e.g. + multipass launch \ + --cpus 4 \ + --memory 8GB \ + --disk 25GB \ + --name sandbox-stonking \ + stonking - * [2] Unload the msr module: - sudo rmmod msr + * [1] Install msr-tools: + sudo apt update && sudo apt install -y msr-tools - * [3] Verify that /dev/cpu is not available: - ls -ld /dev/cpu + * [2] Unload the msr module: + sudo rmmod msr - * [4] Trigger the segfault: - sudo rdmsr -a 0x10 - sudo -a 0x8b 0 + * [3] Verify that /dev/cpu is not available: + ls -ld /dev/cpu - The output will look something like: - Segmentation fault (core dumped) sudo rdmsr -a 0xe2 - Segmentation fault (core dumped) sudo wrmsr -a 0xe2 123 + * [4] Trigger the segfault: + sudo rdmsr -a 0x10 + sudo wrmsr -a 0x8b 0 - * [5] Install the updated package containing the fix. + The output will look something like: + Segmentation fault (core dumped) sudo rdmsr -a 0xe2 + Segmentation fault (core dumped) sudo wrmsr -a 0xe2 123 - * [6] Run sudo rdmsr -a 0x10 and sudo wrmsr -a 0x8b 0 again + * [5] Install the updated package containing the fix. - This time, it should print and error message without crashing: - rdmsr: may need to load msr module to populate /dev/cpu + * [6] Run sudo rdmsr -a 0x10 and sudo wrmsr -a 0x8b 0 again + This time, it should print and error message without crashing: + rdmsr: may need to load msr module to populate /dev/cpu [ Where problems could occur ] - * The fix changes the behavior of rdmsr and wrmsr when /dev/cpu cannot - be accessed. Instead of continuing and potentially crashing, the command - now exits with status 1 and display an error message. This should not - affect normal usage when /dev/cpu is available, but could possibly affect - scripts that expect a different exit status. - + * The fix changes the behavior of rdmsr and wrmsr when /dev/cpu cannot + be accessed. Instead of continuing and potentially crashing, the command + now exits with status 1 and display an error message. This should not + affect normal usage when /dev/cpu is available, but could possibly affect + scripts that expect a different exit status. [ Other Info ] - * The workaround to this issue is to manually load the msr kernel module - (sudo modprobe msr) before using rdmsr or wrmsr with the -a flag. + * The workaround to this issue is to manually load the msr kernel module + (sudo modprobe msr) before using rdmsr or wrmsr with the -a flag. - * Upstream project (https://github.com/intel/msr-tools) is archived and - in read only mode. + * Upstream project (https://github.com/intel/msr-tools) is archived and + in read only mode. - * Filed and forwarded a bug to Debian: - https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1144405 + * Filed and forwarded a bug to Debian: + https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1144405 ------------------------- ORIGINAL BUG DESCRIPTION - Description: ------------ The rdmsr and wrmsr utilities from msr-tools get a segmentation fault when invoked with the -a (all processors) flag while the msr kernel module is not loaded, which means the /dev/cpu directory is not available. Looking at the upstream source code, the vulnerability lies in both rdmsr.c and wrmsr.c inside the rdmsr_on_all_cpus and wrmsr_on_all_cpus functions, respectively. The code uses the scandir() function to read the /dev/cpu directory: https://github.com/intel/msr-tools/blob/7d78c80d66463ac598bcc8bf1dc260418788dfda/rdmsr.c#L106 https://github.com/intel/msr-tools/blob/7d78c80d66463ac598bcc8bf1dc260418788dfda/wrmsr.c#L67 When /dev/cpu does not exist, scandir() returns -1 to indicate an error, and the namelist pointer remains uninitialized. However, the code does not check if dir_entries < 0. Because dir_entries is -1, it evaluates as true in the while (dir_entries--) condition, decrements to -2, and immediately attempts to access namelist[-2]->d_name. Attempting to dereference this uninitialized pointer at a negative offset causes the segmentation fault. Reproducer: ----------- In a bare metal machine (or an environment where MSR access is supported): Unload the msr module if it is currently loaded: sudo rmmod msr Verify that /dev/cpu is not available: ls -l /dev/cpu ls: cannot access '/dev/cpu': No such file or directory Run rdmsr or wrmsr querying all CPUs to trigger the segfault: sudo rdmsr -a 0xe2 Segmentation fault sudo wrmsr -a 0xe2 123 Segmentation fault Workaround: ----------- Manually load the msr kernel module before using rdmsr or wrmsr with the -a flag. Loading the module populates /dev/cpu and its child CPU nodes, preventing the scandir failure. sudo modprobe msr sudo rdmsr -a 0xe2 74008008 74008008 Additional Info: ---------------- Upstream project is in read only mode. This was tested in Jammy, Noble and Resolute. All of them have the same issue.
-- You received this bug notification because you are a member of Ubuntu Bugs, which is subscribed to Ubuntu. https://bugs.launchpad.net/bugs/2163089 Title: rdmsr and wrmsr segfault when invoked with -a without the msr module loaded To manage notifications about this bug go to: https://bugs.launchpad.net/ubuntu/+source/msr-tools/+bug/2163089/+subscriptions -- ubuntu-bugs mailing list [email protected] https://lists.ubuntu.com/mailman/listinfo/ubuntu-bugs
