Je ne vais pas pour des outils compliqués comme le mode de réclamation AppArmor, j'ai besoin d'outils faciles pour me dire quels fichiers sont accessibles par un programme spécifique.
fstat()
ou lstat()
info, etc.
Je ne vais pas pour des outils compliqués comme le mode de réclamation AppArmor, j'ai besoin d'outils faciles pour me dire quels fichiers sont accessibles par un programme spécifique.
fstat()
ou lstat()
info, etc.
Réponses:
Selon Chris Down, vous pouvez utiliser strace -p
pour examiner un processus déjà en cours d' exécution, pour voir quels fichiers il ouvre à partir de maintenant jusqu'au moment où vous terminez strace ou le processus lui-même se termine.
Si vous souhaitez voir les fichiers ouverts pendant toute la durée d'un processus, utilisez dès le début strace
le nom de l'exécutable. L'ajout -f
garantit que tous les sous-processus bifurqués sont également signalés. Exemple
# strace -e open -f /bin/id
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libselinux.so.1", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libpcre.so.1", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
open("/proc/thread-self/attr/current", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/proc/self/task/1581/attr/current", O_RDONLY|O_CLOEXEC) = 3
open("/usr/share/locale/locale.alias", O_RDONLY|O_CLOEXEC) = 3
open("/usr/share/locale/en_US.UTF-8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en_US.utf8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en_US/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en.UTF-8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en.utf8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/etc/nsswitch.conf", O_RDONLY|O_CLOEXEC) = 3
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libnss_files.so.2", O_RDONLY|O_CLOEXEC) = 3
open("/etc/passwd", O_RDONLY|O_CLOEXEC) = 3
open("/etc/group", O_RDONLY|O_CLOEXEC) = 3
open("/etc/group", O_RDONLY|O_CLOEXEC) = 3
uid=0(root) gid=0(root) groups=0(root) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
+++ exited with 0 +++
#
Utilisation lsof
pour voir quels fichiers un processus a actuellement ouverts
# lsof -p $(pidof NetworkManager)
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
NetworkMa 722 root cwd DIR 253,0 224 64 /
NetworkMa 722 root rtd DIR 253,0 224 64 /
NetworkMa 722 root txt REG 253,0 2618520 288243 /usr/sbin/NetworkManager
NetworkMa 722 root mem REG 253,0 27776 34560 /usr/lib64/libnss_dns-2.17.so
[...]
#
Si vous avez SystemTap, vous pouvez surveiller l'hôte entier pour les fichiers en cours d'ouverture.
[root@localhost tmp]# cat mon
#!/usr/bin/env stap
probe syscall.open { printf ("pid %d program %s opened %s\n", pid(), execname(), filename) }
# ./mon
pid 14813 program touch opened "/etc/ld.so.cache"
pid 14813 program touch opened "/lib64/libc.so.6"
pid 14813 program touch opened 0x7f7a8c6ec8d0
pid 14813 program touch opened "foo2"
[...]
#
open
n'est pas le seul appel système pertinent. Par exemple, il est possible de passer des descripteurs de fichiers entre les processus via un socket Unix, et il y openat
a l'appel système qui peut également ouvrir un fichier.
strace
, voir les lignes ENOENT dans l'exemple.
Vous pouvez utiliser opensnoop
depuis BCC, qui utilise eBPF sous le capot:
# ./opensnoop -p 1576
PID COMM FD ERR PATH
1576 snmpd 11 0 /proc/sys/net/ipv6/conf/lo/forwarding
1576 snmpd 11 0 /proc/sys/net/ipv6/neigh/lo/base_reachable_time_ms
1576 snmpd 9 0 /proc/diskstats
1576 snmpd 9 0 /proc/stat
1576 snmpd 9 0 /proc/vmstat
[...]
C'est assez performant car il utilise kprobes au lieu de devoir redémarrer les appels système, comme le strace
fait.
Vous pouvez également le faire avec strace
(potentiellement avec -f
pour suivre les enfants du processus tracé), mais sa façon de fonctionner, impliquant le redémarrage des appels système dans le cadre de ptrace , ralentira quelque peu votre application:
# strace -e open -p 15735
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
open("/usr/lib/gconv/gconv-modules.cache", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/lib/gconv/gconv-modules", O_RDONLY|O_CLOEXEC) = 3
open("/usr/lib/python2.7/site-packages", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 4
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
open("/etc/localtime", O_RDONLY|O_CLOEXEC) = 8
[...]
Vous pouvez également démarrer votre application de cette façon si vous le souhaitez, en utilisant strace [executable]
ou strace -f [executable]
.
Mon outil préféré pour surveiller les fichiers ouverts par une application est le puissant cadre de surveillance sysdig
.
Pour surveiller tous les fichiers ouverts ouverts par un programme nommé exe_file
:
sudo sysdig -p "proc.name=exe_file %12user.name %6proc.pid %12proc.name %3fd.num %fd.typechar %fd.name" evt.type=open
Surveillance de tous les fichiers ouverts sur le serveur:
sudo sysdig -p "%12user.name %6proc.pid %12proc.name %3fd.num %fd.typechar %fd.name" evt.type=open
Création d'un fichier de trace qui ne contiendra que des événements d'écriture dans les répertoires personnels (que nous pourrons inspecter ultérieurement sysdig -r writetrace.scap.gz
):
sudo sysdig -p "%user.name %proc.name %fd.name" "evt.type=write and fd.name contains /home/" -z -w writetrace.scap.gz
Tout voir au niveau syscall, un processus nommé exe_file
:
sudo sysdig proc.name=exe_file
Sysdig possède de nombreux burins, voir pour des choses plus intéressantes qu'il peut faire:
Vous avez également ce dtrace
qui n'est pas beaucoup utilisé sous Linux, mais qui est toujours beaucoup utilisé avec les systèmes d'exploitation * BSD:
# Files opened by process,
dtrace -n 'syscall::open*:entry { printf("%s %s",execname,copyinstr(arg0)); }'
De plus sysdig
, strace
et dtrace
, vous avez également ltrace
, qui enregistre / intercepte les signaux / bibliothèques dynamiques / appels système qui sont appelés / reçus par un processus:
ltrace
est un programme qui exécute simplement la commande spécifiée jusqu'à sa sortie. Il intercepte et enregistre les appels de bibliothèque dynamique qui sont appelés par le processus exécuté et les signaux qui sont reçus par ce processus. Il peut également intercepter et imprimer les appels système exécutés par le programme.
$ltrace exe_file
_libc_start_main(0x400624, 1, 0x7ffcb7b6d7c8, 0x400710 <unfinished ...>
time(0) = 1508018406
srand(0x59e288e6, 0x7ffcb7b6d7c8, 0x7ffcb7b6d7d8, 0) = 0
sprintf("mkdir -p -- '/opt/sms/AU/mo'", "mkdir -p -- '%s'", "/opt/sms/AU/mo") = 28
system("mkdir -p -- '/opt/sms/AU/mo'" <no return ...>
--- SIGCHLD (Child exited) ---
<... system resumed> ) = 0
rand(2, 0x7ffcb7b6d480, 0, 0x7f9d6d4622b0) = 0x2d8ddbe1
sprintf("/opt/sms/AU/mo/tmp.XXXXXX", "%s/tmp.XXXXXX", "/opt/sms/AU/mo") = 29
mkstemp(0x7ffcb7b6d5c0, 0x40080b, 0x40081a, 0x7ffffff1) = 3
sprintf("/opt/sms/AU/mo/tmp.XXXXXX", "%s/tmp.XXXXXX", "/opt/sms/AU/mo") = 29
mkstemp(0x7ffcb7b6d5c0, 0x40080b, 0x40081a, 0x7ffffff1) = 4
+++ exited (status 0) +++
Si le programme est petit, vous pouvez également envisager de le désassembler objdump -d exe_file
ou de le désassembler / décompiler avec Hopper
, pour voir tous les fichiers qu'il traite.
Pour plus de détails, voir: Comprendre ce que fait un binaire Linux
Dans un premier temps, je ferais aussi:
strings exe_file
Il s'agit d'une approche à faible coût, et avec de la chance, certains des noms de fichiers peuvent simplement être présents en mode ASCII dans le fichier binaire avec chance.
Voir aussi la réponse connexe Pourquoi le vrai et le faux sont-ils si grands?
S'il s'agit de fichiers binaires / fichiers fournis avec la distribution, vous pouvez également récupérer les sources à partir des référentiels sources de la distribution ou des référentiels officiels de l'utilitaire réel.
Comme dernière ressource, vous pouvez toujours utiliser des outils comme gdb ou rr pour déboguer le binaire en temps réel.
sysdig
bogue (utilisez-vous ARM?), Veuillez lui poser une nouvelle question.