
Hasta donde tengo entendido, los programas del espacio de usuario se ejecutan en modo sin privilegios y, por lo tanto, no tienen acceso directo a la memoria ni a la E/S.
Entonces, ¿cómo exactamente podemos acceder directamente a la memoria o a las ubicaciones de E/S cuando mmap /dev/mem en programas de espacio de usuario?
Por ejemplo:
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);
Este es un truco muy utilizado en dispositivos integrados.
Ahora la variable leds
se puede utilizar sobre la marcha para acceder a cualquier dispositivo que pueda estar presente en 0x80840000.
Ya no utilizaremos ninguna llamada al sistema para acceder a esa dirección.
Incluso algo como
leds[0x20] = val;
trabajaría.
Pero las operaciones privilegiadas, como leer/escribir directamente en/desde una dirección de E/S, sólo deberían ser posibles poniendo el procesador en modo privilegiado a través de una llamada al sistema.
Respuesta1
Permitir el acceso a /dev/mem
procesos sin privilegios sería de hecho un problema de seguridad y no debería permitirse.
En mi sistema, ls -l /dev/mem
se ve así:
crw-r----- 1 root kmem 1, 1 Sep 8 10:12 /dev/mem
Entonces root
pueden leerlo y escribirlo, los miembros del kmem
grupo (que resulta que no hay ninguno) pueden leerlo pero no escribirlo, y todos los demás no pueden abrirlo en absoluto. Entonces esto debería ser seguro.
Si /dev/mem
se parece en algo al mío, su proceso sin privilegios ni siquiera debería haber podido abrir el archivo, y mucho menos mmap
.
¡Verifique los permisos de /dev/mem
su sistema para asegurarse de que sean seguros!
Respuesta2
Las direcciones visibles para un proceso de usuario (ya sea que se ejecute como root o como usuario sin privilegios) son direcciones virtuales, que la MMU asigna a direcciones físicas a través de las tablas de páginas. La configuración de las tablas de páginas es una operación privilegiada y sólo puede realizarse mediante código del kernel; sin embargo, una vez configuradas las tablas de páginas, se permite acceder a la memoria en modo usuario.
Concretamente, su código suele mmap
solicitar que el kernel configure las tablas de páginas para permitir el acceso a un rango determinado de memoria física. El kernel verifica los privilegios del proceso (tiene acceso de lectura/escritura /dev/mem
) y configura las tablas de páginas para permitirle acceder a la memoria física.
Respuesta3
El valor de leds
es una dirección virtual. Siempre que esté en el espacio de usuario del proceso actual, el proceso puede acceder a él directamente mediante instrucciones, como leds[0] = val
sin tener que estar en modo privilegiado, sin importar en qué parte de la RAM esté asignada esta dirección virtual.