내가 이해한 바로는 사용자 공간 프로그램은 비권한 모드에서 실행되므로 메모리나 I/O에 직접 액세스할 수 없습니다.
그렇다면 사용자 공간 프로그램에서 /dev/mem을 mmap할 때 어떻게 메모리나 I/O 위치에 직접 접근할 수 있을까요?
예를 들어:
int fd = 0;
u8 leds = 0;
fd = open("/dev/mem", O_RDWR|O_SYNC);
leds = (u8 *)mmap(0, getpagesize(), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0x80840000);
이는 임베디드 장치에서 매우 일반적인 기술입니다.
이제 이 변수를 leds
즉시 사용하여 0x80840000에 존재할 수 있는 모든 장치에 액세스할 수 있습니다.
우리는 더 이상 이 주소에 접근하기 위해 시스템 호출을 사용하지 않을 것입니다.
심지어 좋아한다
leds[0x20] = val;
작동합니다.
그러나 I/O 주소에서 직접 읽기/쓰기와 같은 특권 작업은 시스템 호출을 통해 프로세서를 특권 모드에 배치해야만 달성할 수 있습니다.
원천.
답변1
권한이 없는 프로세스에 대한 액세스를 허용하는 것은 /dev/mem
실제로 보안 문제이므로 허용해서는 안 됩니다.
내 시스템에서는 ls -l /dev/mem
다음과 같습니다.
crw-r----- 1 root kmem 1, 1 Sep 8 10:12 /dev/mem
따라서 root
읽고 쓸 수 있고 kmem
그룹 구성원(아무도 없음)은 읽을 수 있지만 쓸 수는 없으며 다른 사람들은 전혀 열 수 없습니다. 그래서 이것은 안전해야 합니다.
당신의 /dev/mem
것이 나와 같은 것이라면, 당신의 권한이 없는 프로세스는 파일은커녕 아예 열 수도 없어야 합니다 mmap
.
시스템의 권한이 /dev/mem
안전한지 확인하세요!
답변2
루트로 실행하든 권한이 없는 사용자로 실행하든 사용자 프로세스에 표시되는 주소는 페이지 테이블을 통해 MMU에 의해 물리적 주소에 매핑되는 가상 주소입니다. 페이지 테이블 설정은 권한 있는 작업이며 커널 코드로만 수행할 수 있습니다. 그러나 페이지 테이블이 설정되면 사용자 모드에서 메모리에 대한 액세스가 허용됩니다.
특히, 코드는 mmap
특정 범위의 물리적 메모리에 대한 액세스를 허용하도록 페이지 테이블을 설정하도록 커널에 요청하는 데 사용됩니다. 커널은 프로세스의 권한(읽기/쓰기 액세스 권한이 있음 /dev/mem
)을 확인하고 실제 메모리에 액세스할 수 있도록 페이지 테이블을 설정합니다.
답변3
값은 leds
가상 주소입니다. 현재 프로세스의 사용자 공간에 있는 한, 프로세스는 leds[0] = val
RAM의 어느 위치에 가상 주소가 매핑되어 있든 특권 모드에 있지 않고도 명령을 통해 직접 액세스할 수 있습니다.