Comment puis-je faire en sorte que dtrace exécute la commande tracée avec des privilèges non root?

OS X manque de strace de linux, mais il y a dtrace qui est supposé être tellement meilleur.

Cependant, la capacité de faire un traçage simple sur des commandes individuelles me manque. Par exemple, sous Linux, je peux écrire strace -f gcc hello.c pour contrôler tous les appels système, ce qui me donne la liste de tous les noms de fichiers nécessaires au compilateur pour comstackr mon programme (l’excellent script de mémo est basé sur cette astuce)

Je veux mettre la mémoire sur le mac, donc j’ai besoin d’une sorte de strace . Ce dont j’ai vraiment besoin, c’est la liste des fichiers lus et écrits par gcc . Bien sûr, puis-je dire dtruss -f gcc hello.c et obtenir les mêmes fonctionnalités, mais le compilateur est exécuté avec les privilèges root, ce qui est évidemment indésirable (à part le risque de sécurité énorme, un problème est que le fichier a.out est maintenant la propriété de root 🙂

J’ai ensuite essayé dtruss -f sudo -u myusername gcc hello.c , mais cela semble un peu faux, et ne fonctionne pas du tout (je n’ai pas de fichier a.out à tout moment, je ne sais pas pourquoi)

Toute cette histoire tente de motiver ma question initiale: comment est-ce que dtrace peut exécuter ma commande avec des privilèges d’utilisateur normaux, comme le fait strace sous Linux?

Edit: il semble que je ne sois pas le seul à me demander comment faire: la question # 1204256 est à peu près la même que la mienne (et a la même réponse sudo sous-optimale 🙂

Pas une réponse à votre question mais quelque chose à savoir. OpenSolaris a résolu ce problème (partiellement) avec des “privilèges” – voir cette page . Même dans OpenSolaris, il ne serait pas possible d’autoriser un utilisateur, sans privilèges supplémentaires, à contester son propre processus. La raison en est le fonctionnement de dtrace: il active les sondes dans le kernel. Donc, permettre à un utilisateur non privilégié de sonder le kernel signifie que l’utilisateur peut faire beaucoup de choses indésirables, par exemple renifler le mot de passe d’un autre utilisateur en activant les sondes dans le pilote du clavier!

Le plus simple est d’utiliser sudo:

 sudo dtruss -f sudo -u $USER whoami 

Une autre solution consisterait à exécuter le débogueur en premier et à surveiller les nouveaux processus spécifiques. Par exemple

 sudo dtruss -fn whoami 

Ensuite, dans un autre terminal, lancez simplement:

 whoami 

Aussi simple que cela.

Vous trouverez des arguments plus compliqués dans le manuel: man dtruss


Alternativement, vous pouvez attacher dtruss au processus utilisateur en cours d’exécution, par exemple sur Mac:

 sudo dtruss -fp PID 

ou similaire sous Linux / Unix en utilisant strace:

 sudo strace -fp PID 

Une autre astuce pourrait être d’exécuter la commande immédiatement après le processus. Voici quelques exemples:

 sudo true; (./Pages &); sudo dtruss -fp `pgrep -n -x Pages` sudo true; (sleep 1 &); sudo dtruss -fp `pgrep -n -x sleep` sudo true; (tail -f /var/log/system.log &); sudo dtruss -fp `pgrep -n -x tail` 

Remarque:

  • premier sudo est juste pour mettre en cache le mot de passe lors de la première exécution,

  • cette astuce ne fonctionne pas pour les lignes de commande rapides comme ls, date car cela prend un certain temps avant que le débogueur ne s’attache au processus,

  • vous devez taper votre commande à deux endroits,

  • vous pouvez ignorer & exécuter le processus en arrière-plan, si c’est déjà fait,

  • Après avoir terminé le débogage, vous devrez tuer manuellement le processus d’arrière-plan (par exemple, killall -v tail )

L’argument -n de dtruss provoquera l’attente de dtruss et examinera les processus correspondant à l’argument -n . L’option -f fonctionnera toujours pour suivre les processus issus des processus correspondant à -n .

Tout cela signifie que si vous voulez lancer un processus (pour des raisons d’argument, disons que c’est du whoami ) en tant whoami , whoami comme suit:

  1. Ouvrir un shell racine
  2. Exécuter dtruss -fn whoami
    • cela va s’asseoir et attendre un processus nommé “whoami” pour exister
  3. Ouvrez un shell non privilégié
  4. Run whoami
    • cela va exécuter et quitter normalement
  5. Observer le suivi des appels système dans la fenêtre de dtruss
    • dtruss ne sortira pas de lui-même – il continuera d’attendre les processus correspondants – alors sortez de là quand vous avez terminé

Cette réponse fait double emploi avec la dernière partie de la réponse de @kenorb, mais elle mérite d’être une réponse de premier ordre.

Je ne sais pas si vous pouvez faire en sorte que dtruss soit aussi non invasif que strace.

Une variante du fichier “sudo [à la racine] dtruss sudo [retour à la version non root] qui semble mieux fonctionner dans certains tests rapides est:

 sudo dtruss -f su -l `whoami` cd `pwd` && cmd.... 

Le sudo externe est bien sûr donc dtruss s’exécute en tant que root.

Le su interne est de retour pour moi, et avec -l, il recrée l’environnement correctement, à quel point nous devons revenir à l’endroit où nous avons commencé.

Je pense que “utilisateur su -l” est préférable à “utilisateur sudo -u” si vous voulez que l’environnement soit ce que cet utilisateur reçoit normalement. Ce sera leur environnement de connexion cependant; Je ne sais pas s’il existe un bon moyen de laisser l’environnement hériter des deux modifications utilisateur.

Dans votre question, une autre plainte que vous aviez à propos de la solution de contournement “sudo dtruss sudo”, autre que la laideur, était que “je n’ai pas de fichier a.out du tout à ce moment, je ne sais pas pourquoi”. Je ne sais pas non plus pourquoi, mais dans mon petit script de test, une variante “sudo dtruss sudo” n’a pas non plus réussi à écrire dans un fichier de sortie de test et la variante “sudo dtruss su” ci-dessus a créé le fichier de sortie.

Il semble que OS X ne supporte pas l’utilisation de dtrace pour répliquer toutes les fonctionnalités de strace dont vous avez besoin. Cependant, je suggère d’essayer de créer un wrapper autour des appels système appropriés. On dirait que DYLD_INSERT_LIBRARIES est la variable d’environnement que vous voulez pirater un peu. C’est fondamentalement la même chose que LD_PRELOAD pour Linux.

Une méthode beaucoup plus simple de remplacement des fonctions de bibliothèque consiste à utiliser la variable d’environnement DYLD_INSERT_LIBRARIES (analogue à LD_PRELOAD sous Linux). Le concept est simple: au moment du chargement, l’éditeur de liens dynamic (dyld) charge toutes les bibliothèques dynamics spécifiées dans DYLD_INSERT_LIBRARIES avant les bibliothèques que l’exécutable veut charger. En nommant une fonction de la même manière qu’une fonction de bibliothèque, elle annulera tout appel à l’original.

La fonction d’origine est également chargée et peut être récupérée à l’aide du dlsym (RTLD_NEXT, “nom_fonction”); fonction. Cela permet une méthode simple pour encapsuler les fonctions de bibliothèque existantes.

Selon l’ exemple de Tom Robinson, vous devrez peut-être également définir DYLD_FORCE_FLAT_NAMESPACE=1 .

Copie de l’exemple d’origine ( lib_overrides.c ) qui ne remplace que fopen :

 #include  #include  #include  // for caching the original fopen implementation FILE * (*original_fopen) (const char *, const char *) = NULL; // our fopen override implmentation FILE * fopen(const char * filename, const char * mode) { // if we haven't already, resortingeve the original fopen implementation if (!original_fopen) original_fopen = dlsym(RTLD_NEXT, "fopen"); // do our own processing; in this case just print the parameters printf("== fopen: {%s,%s} ==\n", filename, mode); // call the original fopen with the same arugments FILE* f = original_fopen(filename, mode); // return the result return f; } 

Usage:

 $ gcc -Wall -o lib_overrides.dylib -dynamiclib lib_overrides.c $ DYLD_FORCE_FLAT_NAMESPACE=1 DYLD_INSERT_LIBRARIES=lib_overrides.dylib command-to-test 

Disclaimer: ceci est dérivé de la réponse de @kenorb. Cela présente cependant certains avantages: PID est plus spécifique que execname. Et nous pouvons faire en sorte qu’un processus de courte durée attende DTrace avant qu’il ne commence.

C’est un peu conditionnel, mais…

Disons que nous voulons tracer le cat /etc/hosts :

 sudo true && \ (sleep 1; cat /etc/hosts) &; \ sudo dtrace -n 'syscall:::entry /pid == $1/ {@[probefunc] = count();}' $!; \ kill $! 

Nous utilisons sudo true pour nous assurer que nous supprimons l’invite de mot de passe de sudo avant de commencer à exécuter quelque chose de sensible au temps.

Nous commençons un processus d’arrière-plan (“attendez 1 seconde, puis faites quelque chose d’intéressant”). Pendant ce temps, nous démarrons DTrace. Nous avons capturé le PID du processus d’arrière-plan dans $! , nous pouvons donc le transmettre à DTrace en tant qu’arg.

The kill $! s’exécute après la fermeture de DTrace. Ce n’est pas nécessaire pour notre exemple de cat (le processus se ferme tout seul), mais cela nous aide à mettre fin à des processus d’arrière-plan de longue durée comme ping . Pass -p $! pour DTrace est la manière préférée de le faire, mais sur MacOS, il faut apparemment un exécutable signé par code.


L’autre chose que vous pouvez faire est d’exécuter la commande dans un shell séparé et de rechercher ce shell. Voir ma réponse

Je ne connais pas de moyen d’exécuter ce que vous voulez en tant qu’utilisateur normal, car il semble que dtruss, qui utilise dtrace, nécessite des privilèges su.

Cependant, je crois que le commandement que vous recherchiez au lieu de

dtruss -f sudo -u myusername gcc hello.c

est

sudo dtruss -f gcc hello.c

Après avoir tapé votre mot de passe, dtruss exécutera les privilèges dtrace will sudo, et vous obtiendrez la trace ainsi que le fichier a.out.

Désolé je ne pouvais pas être plus utile.

Désolé je ne peux pas aider! Je taperais le d program under test bash $ d program under test pour lancer dtruss en toute sécurité dans une fenêtre racine distincte, mais il semblerait que MacOSX SIP, ou tout ce qui dtruss -p maintenant dtruss -p et opensnoop -p identique à l’ancien. Un * x racine. Ainsi, ce script bash ne fonctionne plus:

 d () { case "$*" in [0-9] | [0-9][0-9] | [0-9][0-9][0-9] | [0-9][0-9][0-9][0-9] | [0-9][0-9][0-9][0-9][0-9]) dtruss -f -p "$*" ;; *) bash -c 'echo -en "\t <<< press return in this window to run after launching trace in root window like this >>> \t # d $$" >/dev/tty; (read -u3 3 

Il y a des décennies, nous avions des ordinateurs Apple pour pousser les données et les jeans Levi's pour conduire des tracteurs - maintenant l'idiocratie règne (puh-leaze, gag me…) tous les deux sont de simples entresockets de mode.