
Pelo que entendi, os programas de espaço do usuário são executados no modo sem privilégios e, portanto, não têm acesso direto à memória ou E/S.
Então, como exatamente podemos acessar diretamente a memória ou locais de E/S quando mapeamos /dev/mem em programas de espaço do usuário?
Por exemplo:
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 é um hack muito comumente usado em dispositivos embarcados.
Agora a variável leds
pode ser usada dinamicamente para acessar qualquer dispositivo que possa estar presente em 0x80840000.
Não usaremos mais nenhuma chamada de sistema para acessar esse endereço.
Mesmo algo como
leds[0x20] = val;
podia funcionar.
Mas operações privilegiadas, como ler/escrever diretamente de/para um endereço de E/S, só devem ser possíveis colocando o processador em modo privilegiado por meio de uma chamada de sistema.
Responder1
Permitir o acesso de /dev/mem
processos sem privilégios seria de fato um problema de segurança e não deveria ser permitido.
No meu sistema, ls -l /dev/mem
fica assim:
crw-r----- 1 root kmem 1, 1 Sep 8 10:12 /dev/mem
Assim, root
pode ler e escrever, os membros do kmem
grupo (dos quais não há nenhum) podem lê-lo, mas não podem escrevê-lo, e todos os outros não podem abri-lo. Portanto, isso deve ser seguro.
Se o seu /dev/mem
for parecido com o meu, seu processo sem privilégios nem deveria ter sido capaz de abrir o arquivo, muito menos mmap
ele.
Verifique as permissões do /dev/mem
seu sistema para ter certeza de que estão seguras!
Responder2
Os endereços visíveis para um processo de usuário (seja executado como root ou como usuário sem privilégios) são endereços virtuais, que são mapeados para endereços físicos pelo MMU por meio das tabelas de páginas. Configurar as tabelas de páginas é uma operação privilegiada e só pode ser realizada pelo código do kernel; entretanto, uma vez definidas as tabelas de páginas, o acesso à memória é permitido no modo de usuário.
Concretamente, seu código mmap
solicita que o kernel configure as tabelas de páginas para permitir o acesso a um determinado intervalo de memória física. O kernel verifica os privilégios do processo (ele tem acesso de leitura/gravação /dev/mem
) e configura as tabelas de páginas para permitir que ele acesse a memória física.
Responder3
O valor de leds
é um endereço virtual. Contanto que esteja no espaço do usuário do processo atual, o processo pode acessá-lo diretamente por meio de instruções, leds[0] = val
sem precisar estar em modo privilegiado, não importa onde na RAM esse endereço virtual esteja mapeado.