2010-06-09 15 views
51

OS X carece de strace de Linux, pero tiene dtrace que se supone que es mucho mejor.¿Cómo puede hacer que dtrace ejecute el comando rastreado con privilegios no root?

Sin embargo, echo de menos la capacidad de hacer un seguimiento simple en comandos individuales. Por ejemplo, en Linux Puedo escribir strace -f gcc hello.c a caputre todas las llamadas al sistema, lo que me da la lista de todos los nombres de archivo que necesita el compilador para compilar mi programa (el excelente guión memoize se construye sobre este truco)

I Quiero portar memoize en el mac, así que necesito algún tipo de strace. Lo que realmente necesito es la lista de archivos gcc que lee y escribe, por lo que lo que necesito es más de truss. Efectivamente, puedo decir dtruss -f gcc hello.c y obtener algo de la misma funcionalidad, pero luego el compilador se ejecuta con privilegios de root, lo cual es obviamente indeseable (aparte del enorme riesgo de seguridad, un problema es que el archivo a.out ahora es propiedad de root :-)

luego probé dtruss -f sudo -u myusername gcc hello.c, pero esto se siente un poco mal, y no funciona de todos modos (me da ningún archivo a.out en todo este tiempo, no sé por qué)

todo lo que larga historia trata de motivar a mi pregunta original : ¿Cómo obtengo dtrace para ejecutar mi comando con privilegios de usuario normales, como lo hace strace en Linux?

Editar: se parece que no soy el único que se pregunta cómo hacer esto: #1204256 cuestión es más o menos la misma que la mía (y tiene la misma respuesta subóptima sudo :-)

Respuesta

5

No es una respuesta a tu pregunta, pero algo para saber. OpenSolaris resolvió este problema (parcialmente) con "privilegios" - vea this page. Incluso en OpenSolaris, no sería posible permitir que un usuario, sin ningún privilegio adicional, controle su propio proceso. La razón es la forma en que funciona dtrace: habilita las sondas en el kernel. Por lo tanto, permitir que un usuario sin privilegios explore el núcleo significa que el usuario puede hacer muchas cosas indeseadas, p. ¡oliendo la contraseña de otro usuario habilitando sondeos en el controlador del teclado!

+0

Probablemente tengas razón. a pesar de que obtener privilegios de root no es un problema aquí, ya que en mi computadora portátil puedo (y lo he hecho) 'chmod a + s dtrace', aún así, dtrace no pretende ser una herramienta de usuario de potencia de Unix, sino como un" herramienta de administrador de Unix. Es por eso que tratar de usarlo desde programas de usuario conduce a una situación tan artificial. Muchas gracias por tu respuesta. – Gyom

+0

¿No podría tener un "modo restringido", donde solo se activarán algunas sondas (como las sondas syscall o las sondas de espacio de usuario), y solo en algunos procesos (los que son propiedad del usuario relevante), y solo algunas funciones estarán disponibles : aquellos que pueden hacerse fácilmente para que solo inspeccionen los procesos del usuario, o que solo proporcionan acceso a la información que ya está disponible para el usuario de otras maneras? – SamB

1

I don' Conozco una forma de ejecutar lo que desea como usuario normal, ya que parece que dtruss, que usa dtrace, requiere sus privilegios.

Sin embargo, creo que el comando que estabas buscando en lugar de

dtruss -f sudo -u myusername gcc hello.c

es

sudo dtruss -f gcc hello.c

Después de introducir su contraseña, dtruss se ejecutará privilegios sudo DTrace, y obtendrá el seguimiento así como también el archivo a.out.

Lo siento, no podría ser de ayuda.

+3

el problema con ejecutar realmente el comando como root (aparte del obvio riesgo de seguridad gigantesco) es que el entorno de ejecución de sudo (PATH, variables env, permisos) es muy diferente del normal, y los impactos dramáticamente el comportamiento de el programa rastreado Linux 'strace', por el contrario, es casi transparente en términos de comportamiento funcional del comando trazado. – Gyom

5

No sé si puede conseguir que dtruss sea tan no invasivo como Strace.

Una variante de la "sudo [a raíz] dtruss sudo [volver a nonroot] cmd" que parece funcionar mejor en algunas pruebas rápidas para mí es:

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

El sudo exterior es, por supuesto, por lo dtruss se ejecuta como root.

El interior está de vuelta a mí, y con -l recrea el entorno correctamente, momento en el que tenemos que volver al lugar donde comenzamos.

Creo que "su -l usuario" es mejor que "sudo -u usuario" si quiere que el entorno sea lo que ese usuario normalmente recibe.Sin embargo, ese será su entorno de inicio de sesión; No sé si hay una buena manera de dejar que el entorno herede a través de los dos cambios de usuario.

En su pregunta, una queja adicional que tenía sobre la solución "sudo dtruss sudo", además de la fealdad, era que "no recibí ningún archivo a.out en todo este tiempo, no estoy seguro de por qué". No sé por qué tampoco, pero en mi pequeño script de prueba, una variante "sudo dtruss sudo" tampoco pudo escribir en un archivo de salida de prueba, y la variante "sudo dtruss su" anterior creó el archivo de salida.

+0

de hecho, gracias por este intento. Aún así, parece que voy a tener que darme por vencido en este caso.En Linux, yo solía 'strace' comandos de un script de reemplazo de makefile, para espiar qué archivos estaban siendo tocados por los comandos. Quería portar estos scripts a mac os x, pero al final del día me doy cuenta de que no me gusta la idea de tener todas mis compilaciones involucrando varios niveles de sudo solo para espiar mis propios comandos. – Gyom

+0

Sí. Intento directamente hacer que dtruss actúe como un reemplazo de strain no invasivo parece ladrar el árbol equivocado por las razones que describes. Tal vez se necesite un enfoque alternativo. 2 cosas que se me ocurren que podrían ser posibles: 1) tomar la fuente dtrace, modificar el frontend del nivel de usuario (que necesita ejecutarse como root) para que solo inicie nuevos procesos y solo espíe sobre ellos, agregue una opción para decirle a quién inicia esos procesos como, luego haz que sea propiedad de root. – metamatt

+0

Y # 2 (continuación del comentario anterior): use dtrace directamente de la manera en que fue diseñado para responder la pregunta que desea responder, en lugar de tratar de usarlo como un reemplazo para reemplazar los archivos makefiles para ver lo que los comandos del niño estaban haciendo - ¿puedes escribir pruebas dtrace fuera del proceso de creación que identifiquen y anoten lo que está haciendo el proceso de creación? – metamatt

39

La forma más sencilla es utilizar sudo:

sudo dtruss -f sudo -u $USER whoami 

Otra solución sería la de ejecutar el depurador primera y controlar los nuevos procesos específicos. P. ej.

sudo dtruss -fn whoami 

Luego, en otro terminal sólo tiene que ejecutar:

whoami 

Tan simple como eso.

argumentos más difíciles se pueden encontrar en el manual: man dtruss


Alternativamente se puede adjuntar dtruss al proceso de usuario que ejecuta, por ejemplo, en Mac:

sudo dtruss -fp PID 

o similares en Linux/Unix usando strace:

sudo strace -fp PID 

Otro truco hacky podría ser para ejecutar el comando y justo después de que se adhieren al proceso.He aquí algunos ejemplos:

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` 

Nota:

  • primera sudo es sólo para el almacenamiento en caché la contraseña en la primera vez de correr,

  • este truco no funciona para comandos rápida líneas como ls, date, ya que lleva un tiempo hasta que el depurador se adjuntará al proceso,

  • tiene que escribir su comando en dos pla ces,

  • puede ignorar & para ejecutar el proceso a un segundo plano, si ya está haciendo eso,

  • después de terminar la depuración, tendrá que matar manualmente el proceso en segundo plano (por ejemplo, killall -v tail)

+5

Eres un rockstar por señalar la opción '-n' para dtruss. Esta es 100% la respuesta correcta. – wfaulk

7

El argumento -n a dtruss causará dtruss que esperar y examinar los procesos que coinciden con el argumento de que -n. La opción -f seguirá funcionando para seguir los procesos bifurcados de los procesos que coincidan con -n.

Todo esto significa que si quieres dtruss un proceso (por el bien del argumento, digamos que es whoami) que se ejecuta como usuario sin privilegios, siga estos pasos:

  1. Abra un intérprete de comandos
  2. ejecutar dtruss -fn whoami
    • esto va a sentarse y esperar a un proceso llamado "whoami" existir
  3. Abrir una nonprivilege d concha
  4. Run whoami
    • esto va a ejecutar y salida normalmente
  5. Observar rastreo de llamadas del sistema en la ventana dtruss
    • dtruss no saldrá por sí mismo - que seguirá a la espera de los procesos a juego - por lo que salir de ella cuando haya terminado

Esta respuesta duplica la última parte de la respuesta de @ kenorb, pero merece ser una respuesta de primera clase.

3

Parece que OS X no admite el uso de dtrace para replicar todas las características de strace que necesita. Sin embargo, sugeriría tratar de crear un contenedor de syscalls adecuados. Parece que DYLD_INSERT_LIBRARIES es la variable de entorno que desea hackear un poco. Eso es básicamente lo mismo que LD_PRELOAD para Linux.

Una manera mucho más fácil de hacer anula la función de biblioteca está utilizando la variable de entorno DYLD_INSERT_LIBRARIES (análogo a LD_PRELOAD en Linux). El concepto es simple: en el momento de la carga, el enlazador dinámico (dyld) cargará cualquier biblioteca dinámica especificada en DYLD_INSERT_LIBRARIES antes de cualquier biblioteca que el archivo ejecutable desee cargar. Al nombrar una función igual que una en una función de biblioteca, se anulará cualquier llamada al original.

La función original también se carga, y se puede recuperar utilizando el dlsym (RTLD_NEXT, "nombre_función"); función. Esto permite un método simple para envolver las funciones de biblioteca existentes.

De acuerdo con la example por Tom Robinson puede que tenga que configurar DYLD_FORCE_FLAT_NAMESPACE=1, también.

Copia del ejemplo original (lib_overrides.c) que anula solamente fopen:

#include <stdio.h> 
#include <unistd.h> 
#include <dlfcn.h> 

// 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, retrieve 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; 
} 

Uso:

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

exención de responsabilidad: este se deriva de @ de answer kenorb. Sin embargo, tiene algunas ventajas: PID es más específico que execname. Y podemos hacer que un proceso de corta duración espere a DTrace antes de que comience.

Esta es una carrera de conditiony poco, pero ...

Digamos que queremos trazar cat /etc/hosts:

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

Utilizamos sudo true para asegurarse de que tenemos claro indicador de contraseña de sudo antes de empezar a correr cualquier cosa sensible al tiempo.

Comenzamos un proceso en segundo plano ("espere 1 segundo, luego haga algo interesante"). Mientras tanto, comenzamos DTrace. Hemos capturado el PID del proceso en segundo plano en $!, por lo que podemos pasarlo a DTrace como un argumento.

El kill $! se ejecuta después de que cerramos DTrace. No es necesario para nuestro ejemplo cat (el proceso se cierra solo), pero nos ayuda a finalizar procesos de fondo de larga ejecución como ping. Pasar -p $! a DTrace es la forma preferida de hacerlo, pero en macOS aparentemente se requiere un ejecutable con código firmado.


La otra cosa que puede hacer es ejecutar el comando en un shell separado, y husmear ese shell. Ver mi answer.

Cuestiones relacionadas