Comment fonctionne mmap'ing / dev / mem en dépit d'être en mode non privilégié?

Pour autant que je sache, les programmes d'espace user s'exécutent en mode sans privilèges et n'ont donc pas d'access direct à la memory ou aux E / S.

Alors, comment pouvons-nous accéder directement à la memory ou aux locations d'E / S lorsque nous utilisons mmap / dev / mem dans les programmes d'espace user?

Par exemple:

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); 

C'est un hack très couramment utilisé dans les appareils embarqués.

Maintenant, les variables leds peuvent être utilisées à la volée pour accéder à n'importe quel périphérique qui pourrait être présent à 0x80840000.

Nous n'utiliserons plus aucun appel système pour accéder à cette adresse.

Même quelque chose comme

 leds[0x20] = val; 

travaillerait.

Mais les opérations privilégiées, telles que la lecture / écriture directement depuis / vers une adresse d'E / S, ne devraient être possibles qu'en mettant le processeur en mode privilégié via un appel système.

Source .

Permettre l'access à /dev/mem par des process non privilégiés serait en effet un problème de security et ne devrait pas être autorisé.

Sur mon système, ls -l /dev/mem ressemble à ceci:

 crw-r----- 1 root kmem 1, 1 Sep 8 10:12 /dev/mem 

Donc, root peut le lire et l'écrire, les membres du groupe kmem (dont il n'y en a pas) peuvent le lire mais ne pas l'écrire, et tout le monde ne peut pas l'ouvrir du tout. Donc, cela devrait être sécurisé.

Si votre /dev/mem est quelque chose comme le mien, votre process non privilégié ne devrait même pas avoir pu ouvrir le file du tout, encore less mmap it.

Vérifiez les permissions de /dev/mem sur votre système pour vous assurer qu'elles sont sécurisées!

Les adresses visibles par un process user (qu'il s'agisse d'un user root ou d'un user non privilégié) sont des adresses virtuelles qui sont mappées à des adresses physiques par le MMU via les tables de pages. La configuration des tables de pages est une opération privilégiée et ne peut être effectuée que par le code du kernel; Cependant, une fois les tables de pages définies, l'access à la memory est autorisé en mode user.

Concrètement, votre code utilise mmap pour requestr au kernel de configurer les tables de pages pour permettre l'access à une plage donnée de memory physique. Le kernel vérifie les privilèges du process (il a un access en lecture / écriture à /dev/mem ) et configure les tables de page pour lui permettre d'accéder à la memory physique.

La valeur des leds est une adresse virtuelle. Tant que c'est dans l'espace user du process en cours, le process peut y accéder directement via des instructions comme leds[0] = val sans avoir à être en mode privilégié, peu importe où dans la RAM cette adresse virtuelle est mappée