flat assembler
Message board for the users of flat assembler.

Index > Linux > accessing MSRs in Linux from usermode

Author
Thread Post new topic Reply to topic
Feryno



Joined: 23 Mar 2005
Posts: 509
Location: Czech republic, Slovak republic
Feryno 21 Aug 2023, 19:01
I needed to read few MSRs in Linux and did not want to compile any kernel module.
sys_iopl is deprecated and does not work in today kernels. Luckily there is a device which allows the access from usermode (requires root access).
https://man7.org/linux/man-pages/man4/msr.4.html

Reading a MSR is performed by opening the device, seeking (lseek) into the same offset as the desired MSR and then reading 8 bytes.

Here the code fragment for reading few MSRs in a loop:
Code:
include 'linux_def.inc'
include 'unistd64.inc'

format ELF64 executable at (1 shl 32)           ; we are on new AMD64 platform,
                                                ; so we put image
                                                ; over old 32-bit limit !!!

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


segment executable readable

entry $

        mov     esi,O_RDONLY
        lea     rdi,[filename]
        mov     eax,sys_open
        syscall
        test    rax,rax
        js      exit

        mov     rbx,rax         ; file handle

        xor     ebp,ebp         ; counter

align 10h
L0:
        mov     edx,SEEK_SET
        lea     rcx,[msrs]
        mov     esi,[rcx+rbp*4] ; offset to seek in the file
        mov     rdi,rbx
        mov     eax,sys_lseek
        syscall
;       test    rax,rax
;       js      exit
        lea     rcx,[msrs]
        mov     ecx,[rcx+rbp*4]
        cmp     rax,rcx
        jnz     exit

        mov     edx,8           ; size
        lea     rax,[buffer]
        lea     rsi,[rax+rbp*8]
        mov     rdi,rbx
        mov     eax,sys_read
        syscall
;       test    rax,rax
;       js      exit
        cmp     rax,8
        jnz     exit

        inc     ebp
        cmp     ebp,cnt_of_msrs
        jc      L0

        mov     rdi,rbx
        mov     eax,sys_close
        syscall

exit:
        xor     edi,edi
        mov     eax,sys_exit
        syscall


segment readable writeable
rb      10h - ($ mod 10h)
msrs            dd      6A2h,6A4h,6A5h,6A6h,6A7h,6A8h,1Bh,0C0000080h
cnt_of_msrs     =       ($-msrs) / 4
;buffer         rq      cnt_of_msrs
buffer:         times cnt_of_msrs dq -1
filename        db      '/dev/cpu/0/msr',0    


Description:
Download
Filename: msr.tar.gz
Filesize: 6.51 KB
Downloaded: 161 Time(s)

Post 21 Aug 2023, 19:01
View user's profile Send private message Visit poster's website ICQ Number Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20357
Location: In your JS exploiting you and your system
revolution 21 Aug 2023, 22:48
The /dev/cpu/0/msr is usermode accessible, but it still requires root privileges.

There are also some restrictions on how to format the data requests. The alignment and sizes need to be multiples of 8 for x64.
Code:
~ sudo dd if=/dev/cpu/0/msr bs=4 count=1 status=none | xxd
dd: error reading 'msr': Invalid argument
~ sudo dd if=/dev/cpu/0/msr bs=8 count=1 status=none | xxd
00000000: 0000 0000 0000 0000                      ........    
Post 21 Aug 2023, 22:48
View user's profile Send private message Visit poster's website Reply with quote
I



Joined: 19 May 2022
Posts: 58
I 22 Aug 2023, 02:52
FWIW I use sys_pread64 and sys_pwrite64.

64bit
Code:
        mov     eax, sys_pread64
        mov     rdi, [rbp-40h]                  ; fd handle of logical CPU
        lea     rsi, [rbp-20h]                  ; Buffer for result
        mov     edx, 8                          ; Count, 8 bytes per MSR [EDX:EAX]
        mov     r10,0x35                        ; fd Offset / MSR Number
        xor     r8d,r8d                         ; ?
        syscall
    


32bit
Code:
        mov     eax, sys_pread64
        mov     ebx, [ebp-40h]                  ; fd handle of logical CPU
        lea     ecx, [ebp-34h]                  ; Buffer for for result
        mov     edx, 8                          ; Count, 8 bytes per MSR [EDX:EAX]
        mov     esi,0x35                        ; fd Offset / MSR Number
        xor     edi,edi                         ; ?
        int     0x80
    

Had to zero 5th arg IIRC but don't know why as not shown in my syscall table?

Edit: Trying now without clearing edi/r8 works as it should so not sure what the reason was for it needed from some time ago.

Edit2: Running older OS (64bit Fedora 34) on VirtualBox sees EINVAL when 32-bit code is run and edi isn't zero!
Post 22 Aug 2023, 02:52
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.