Comment accéder à mmaped /dev/mem sans se planter le noyau Linux?
J'ai un programme simple qui tente d'accéder à la mémoire physique dans l'espace utilisateur, où le noyau magasins le 1er struct page. Sur un ordinateur 64 bits cette adresse est:
- virtuelle du noyau adresse: ffffea0000000000
- adresse physique: 0000620000000000
Je suis en train d'essayer d'accéder à cette adresse physique par le biais de mmap dans l'espace utilisateur. Mais le code suivant planter le noyau.
int *addr;
if ((fd = open("/dev/mem", O_RDWR|O_SYNC)) < 0 ) {
printf("Error opening file. \n");
close(fd);
return (-1);
}
/* mmap. address of first struct page for 64 bit architectures
* is 0x0000620000000000.
*/
addr = (int *)mmap(0, num*STRUCT_PAGE_SIZE, PROT_READ, MAP_PRIVATE,
fd, 0x0000620000000000);
printf("addr: %p \n",addr);
printf("addr: %d \n",*addr); /* CRASH. */
Quelle est la valeur de mmap() renvoie dans l'adresse?
J'ai essayé ci-dessus sur un 32 bits x86 (en remplacement de mmap compensation de la 0x01000000); addr = 0xffffffff . Et oui, il se bloque, bien sûr, sur le déréférencer. Quelle est la solution?
0xffffffff == -1 -> mmap() retourne une erreur. Selon la page de man, la raison de l'erreur est donnée dans le "errno" variable. De sorte que vous pourriez vouloir vérifier tat.
Voir aussi Comment accéder à mmaped /dev/mem sans se planter le noyau Linux?, mmap de /dev/mem échoue avec un argument non valide, mais l'adresse est alignée sur et Comment accéder à l'espace du noyau à partir de l'espace utilisateur?
J'ai essayé ci-dessus sur un 32 bits x86 (en remplacement de mmap compensation de la 0x01000000); addr = 0xffffffff . Et oui, il se bloque, bien sûr, sur le déréférencer. Quelle est la solution?
0xffffffff == -1 -> mmap() retourne une erreur. Selon la page de man, la raison de l'erreur est donnée dans le "errno" variable. De sorte que vous pourriez vouloir vérifier tat.
Voir aussi Comment accéder à mmaped /dev/mem sans se planter le noyau Linux?, mmap de /dev/mem échoue avec un argument non valide, mais l'adresse est alignée sur et Comment accéder à l'espace du noyau à partir de l'espace utilisateur?
OriginalL'auteur Vinay | 2012-08-09
Vous devez vous connecter pour publier un commentaire.
Je crois que j'ai trouvé le problème, c'est de le faire avec /dev/mem mémoire de cartographie de protection sur les architectures x86.
Pl se référer à cet article LWN:
"x86: présenter /dev/mem restrictions avec une option de configuration"
http://lwn.net/Articles/267427/
CONFIG_NONPROMISC_DEVMEM
Maintenant (j'ai testé cela sur une récente 3.2.21 noyau), l'option de configuration semble être appelé CONFIG_STRICT_DEVMEM.
J'ai changé de configuration du noyau:
Lorsque les ci-dessus prg a été exécuté avec les précédente noyau, avec CONFIG_STRICT_DEVMEM ENSEMBLE:
dmesg affiche:
C'est à cause de la protection du noyau..
Lorsque le noyau a été reconstruit (avec le CONFIG_STRICT_DEVMEM UNSET) et la ci-dessus prg :
C'est parce que le 'décalage' paramètres > 1 MO (non valide sur x86) (c'était de 16 mo).
Après avoir fait le mmap compensé à l'intérieur de 1 MO:
Ça marche!!!
Voir ci-dessus l'article LWN pour plus de détails.
Sur les architectures x86 avec prise en charge PAT (Attribut de la Page Table), le noyau empêche encore la cartographie de la DRAM régions. La raison pour cela comme mentionné dans le source du noyau est:
Cette case sera la cause d'une erreur similaire à celui mentionné ci-dessus. Par exemple:
Cette restriction peut être retiré par la désactivation de la PAT. PAT peut être désactivé par l'ajout de la "nopat" argument de la ligne de commande du noyau au moment du démarrage.
Aussi, je réglage de la compensation de 0x0000000000000000 et je reçois valide l'adresse de retour. Mais si j'ai mis le décalage de quelques adresse aléatoire dire 0x00000000000000ff, je ne revenons pas une adresse valide. Dois-je régler l'adresse sur la limite de la page?
BRAS nécessite l'utilisation d'une limite de la page pour mmap(). À partir d'un peu de tests sur IA32 il semble être le cas là...(& vous avez essayé sur le x86_64 je présume). Aussi, wrt votre commentaire sur l'accès à la première structure de la page, avec CONFIG_STRICT_DEVMEM Off, j'ai pensé qu'il serait de travailler (sur une frontière de page).. pas sûr à ce sujet..
Vous pouvez désactiver la vérification. Par exemple, toujours faire
devmem_is_allowed
retour 1. Je sais que c'est un hack. 😉Merci! votre mise en œuvre semble simple à mmap un codée en dur de l'av. Je maintiens une plus généralisée des logiciels qui peuvent être utilisés pour gagner de la r/w de l'accès à la mémoire (MMIO/registres/RAM) fr usermode; pl découvrez: github.com/kaiwan/device-memory-readwrite
OriginalL'auteur kaiwan
Sur les architectures x86 avec prise en charge PAT (Attribut de la Page Table), le noyau peut empêcher le mappage de DRAM régions (même si il est compilé sans réglage CONFIG_NONPROMISC_DEVMEM).
La raison comme mentionné dans le source du noyau est:
Cette case sera la cause d'une erreur similaire à apparaître dans
dmesg
que celui mentionné dans kaiwan la réponse ci-dessus ci-dessus. Par exemple:Cette restriction peut être retiré par la désactivation de la PAT.
PAT peut être désactivé par l'ajout de la
nopat
argument de la ligne de commande du noyau au moment du démarrage.C'était moi. J'étais le seul qui l'a ajoutée à la réponse précédente, puis de l'ajouter comme une réponse distincte parce que (apparemment) je ne sais pas comment utiliser l'outil :D.
OK! Laissez-moi savoir si vous voulez qu'il soit enlevé de la réponse ci-dessus. Des acclamations.
OriginalL'auteur Safayet Ahmed