Existe-t-il un meilleur moyen que d'analyser / proc / self / maps pour comprendre la protection de la mémoire?
-
06-07-2019 - |
Question
Sous Linux (ou Solaris), existe-t-il un meilleur moyen que d'analyser manuellement / proc / self / maps
pour déterminer si vous pouvez ou non lire, écrire ou exécuter tout ce qui est stocké chez plus d'adresses en mémoire?
Par exemple, sous Windows, vous avez VirtualQuery
.
Sous Linux, je peux mprotect
pour modifier ces valeurs, mais je ne peux pas les relire.
De plus, existe-t-il un moyen de savoir quand ces autorisations changent (par exemple, lorsqu'une personne utilise mmap
sur un fichier derrière mon dos), mis à part faire quelque chose de terriblement envahissant et d'utiliser ptrace
sur tous les threads du processus et interceptant toute tentative de passer un appel système
pouvant affecter la carte mémoire?
Mise à jour:
Malheureusement, je l’utilise dans un JIT qui contient très peu d’informations sur le code qu’il exécute pour obtenir une approximation de ce qui est constant. Oui, je me rends compte que je pourrais avoir une carte constante de données mutables, comme la page vsyscall utilisée par Linux. Je peux revenir en toute sécurité sur l'hypothèse que tout ce qui n'est pas inclus dans l'analyse initiale est modifiable et dangereux, mais je ne suis pas entièrement satisfait de cette option.
Actuellement, je lis / proc / self / maps
et construis une structure dans laquelle je peux effectuer une recherche binaire pour la protection d'une adresse donnée. Chaque fois que j'ai besoin de savoir quelque chose sur une page qui ne se trouve pas dans ma structure, je relis / proc / self / maps en supposant qu'elle a été ajoutée entre-temps, sinon je serais sur le point de faire une erreur de segmentation de toute façon.
Il semble simplement que l'analyse de texte pour obtenir cette information sans savoir quand elle change est extrêmement cruelle. ( / dev / inotify
ne fonctionne pratiquement pas dans / proc
)
La solution
Je ne connais pas d'équivalent de VirtualQuery
sous Linux. Mais il existe d’autres moyens de le faire qui peuvent ou non fonctionner:
-
vous configurez un gestionnaire de signal piégeant SIGBUS / SIGSEGV et poursuivez votre lecture ou votre écriture. Si la mémoire est protégée, votre code d'interception de signal sera appelé. Sinon, votre code d'interception de signal n'est pas appelé. De toute façon, vous gagnez.
-
vous pouvez suivre chaque fois que vous appelez
mprotect
et créer une structure de données correspondante qui vous aide à savoir si une région est protégée en lecture ou en écriture. C'est bien si vous avez accès à tout le code qui utilisemprotect
. -
vous pouvez surveiller tous les appels
mprotect
de votre processus en liant votre code à une bibliothèque redéfinissant la fonctionmprotect
. Vous pouvez ensuite créer la structure de données nécessaire pour savoir si une région est protégée en lecture ou en écriture, puis appeler le systèmemprotect
pour définir réellement la protection. -
vous pouvez essayer d'utiliser
/ dev / inotify
et surveiller le fichier/ proc / self / maps
pour tout changement. Je suppose que celui-ci ne fonctionne pas, mais devrait en valoir la peine.
Autres conseils
Il y a en quelque sorte / was / proc / [pid | self] / pagemap, de la documentation dans le noyau, mises en garde ici: https://lkml.org/lkml/2015/7/14/477 Donc, ce n'est pas complètement inoffensif ...