La page de manuel Linuxproc(5)
me dit que /proc/$pid/mem
"peut être utilisé pour accéder aux pages de la mémoire d'un processus". Mais une simple tentative d'utilisation ne me donne que
$ cat /proc/$$/mem /proc/self/mem
cat: /proc/3065/mem: No such process
cat: /proc/self/mem: Input/output error
Pourquoi ne cat
peut-il pas imprimer sa propre mémoire ( /proc/self/mem
)? Et quelle est cette étrange erreur «pas de tel processus» lorsque j'essaie d'imprimer la mémoire du shell ( /proc/$$/mem
, évidemment, le processus existe)? Comment puis-je lire /proc/$pid/mem
, alors?
Réponses:
/proc/$pid/maps
/proc/$pid/mem
affiche le contenu de la mémoire de $ pid mappée de la même manière que dans le processus, c'est-à-dire que l'octet au décalage x dans le pseudo-fichier est le même que l'octet à l'adresse x dans le processus. Si une adresse n'est pas mappée dans le processus, la lecture de l'offset correspondant dans le fichier est renvoyéeEIO
(erreur d'entrée / sortie). Par exemple, étant donné que la première page d'un processus n'est jamais mappée (de sorte que la déréférencement d'unNULL
pointeur échoue proprement plutôt que d'accéder involontairement à la mémoire réelle), la lecture du premier octet de/proc/$pid/mem
toujours génère une erreur d'entrée / sortie.La manière de savoir quelles parties de la mémoire de processus sont mappées est de lire
/proc/$pid/maps
. Ce fichier contient une ligne par région mappée, ressemblant à ceci:Les deux premiers chiffres représentent les limites de la région (adresses du premier octet et de l'octet après le dernier, en hexa). La colonne suivante contient les autorisations, puis contient des informations sur le fichier (offset, périphérique, inode et nom) s'il s'agit d'un mappage de fichier. Voir la
proc(5)
page de manuel ou Comprendre Linux / proc / id / maps pour plus d'informations.Voici un script de validation de principe qui extrait le contenu de sa propre mémoire.
/proc/$pid/mem
Si vous essayez de lire le
mem
pseudo-fichier d'un autre processus, cela ne fonctionne pas: vous obtenez uneESRCH
erreur (Aucun processus de ce type).Les autorisations sur
/proc/$pid/mem
(r--------
) sont plus libérales que ce qui devrait être le cas. Par exemple, vous ne devriez pas pouvoir lire la mémoire d'un processus setuid. De plus, essayer de lire la mémoire d’un processus pendant que celui-ci est en train de le modifier pourrait donner au lecteur une vue incohérente de la mémoire, et pire encore, il existait des conditions de concurrence qui pouvaient retracer les anciennes versions du noyau Linux (selon ce fil de discussion lkml , bien que ne connais pas les détails). Des vérifications supplémentaires sont donc nécessaires:/proc/$pid/mem
doit être attaché au processus en utilisantptrace
avec lePTRACE_ATTACH
drapeau. C'est ce que font les débogueurs lorsqu'ils commencent à déboguer un processus. c'est aussi ce quistrace
fait aux appels système d'un processus. Une fois que le lecteur a fini de lire/proc/$pid/mem
, il devrait se détacher en appelantptrace
avec lePTRACE_DETACH
drapeau.ptrace(PTRACE_ATTACH, …)
arrêtera le processus cible (il enverra unSTOP
signal), mais il y a une condition de concurrence critique (la livraison du signal est asynchrone). Le traceur doit donc appelerwait
(comme indiqué dansptrace(2)
).Un processus exécuté en tant que root peut lire la mémoire de n'importe quel processus, sans avoir à appeler
ptrace
, mais le processus observé doit être arrêté ou la lecture sera toujours renvoyéeESRCH
.Dans la source du noyau Linux, le code fournit des entrées par processus en
/proc
est dansfs/proc/base.c
, et la fonction de lire/proc/$pid/mem
estmem_read
. La vérification supplémentaire est effectuée parcheck_mem_permission
.Voici un exemple de code C à attacher à un processus et à lire un fragment de
mem
fichier (vérification d'erreur omise):J'ai déjà posté un script de validation de principe pour le dumping
/proc/$pid/mem
sur un autre thread .la source
/proc/$pid/mem
directe (aveccat
oudd
ou autre chose) ne fonctionne pas. Lire ma réponse./proc/self/mem
. Un processus peut très bien lire son propre espace mémoire. Il lit également l’espace mémoire d’un autre processusPTRACE_ATTACH
.process_vm_readv()
appel système (Linux 3.2).ESRCH
erreur dans ce scénario.Cette commande (de gdb) vide la mémoire de manière fiable:
Les dumps peuvent être volumineux, utilisez-les
-o outfile
si votre répertoire actuel n’a pas assez de place.la source
Lorsque vous exécutez
cat /proc/$$/mem
la variable$$
est évaluée par bash qui insère son propre pid. Il exécute ensuitecat
un pid différent. Vous finissez parcat
essayer de lire la mémoire debash
son processus parent. Les processus non privilégiés ne pouvant lire que leur propre espace mémoire, le noyau le refuse.Voici un exemple:
Notez que la valeur est
$$
17823. Voyons quel processus il s'agit.C'est ma coquille actuelle.
Ici encore
$$
évalue à 17823, qui est ma coquille.cat
ne peut pas lire l'espace mémoire de mon shell.la source
$pid
est. Comme je l'explique dans ma réponse, pour lire la mémoire d'un processus différent, vous devez le rechercher.$$
quand vous écrivez (et lisez)$pid
?$$
et à mettre$pid
à la fin. Je l'ai transposé dans ma tête sans m'en rendre compte. Toute ma réponse devrait faire référence$$
, pas$pid
.Voici un petit programme que j'ai écrit en C:
Usage:
Le programme utilise / proc / $ pid / maps pour rechercher toutes les régions de mémoire mappées du processus, puis lit ces régions dans / proc / $ pid / mem, une page à la fois. ces pages sont écrites sur stdout ou sur l'adresse IP et le port TCP que vous avez spécifiés.
Code (testé sur Android, nécessite des autorisations de superutilisateur):
la source
write to stdout
immédiatement au-dessusfwrite(..., stdout)
. Voir programmers.stackexchange.com/questions/119600/…