2010-06-09 2 views
51

OS X не хватает Linux strace, но он имеет dtrace, который должен быть намного лучше.Как можно заставить dtrace запустить прослеживаемую команду с привилегиями non-root?

Однако, я пропускаю возможность простейшего отслеживания по отдельным командам. Например, на Linux я могу написать strace -f gcc hello.c в caputre все системные вызовы, которые дает мне список все имена файлов, необходимые компилятором скомпилировать свою программу (отличный memoize сценарий построен на этот трюк)

I хочу портировать memoize на mac, поэтому мне нужен какой-то strace. Мне действительно нужен список файлов gcc, который читает и записывает, поэтому мне нужно больше truss. Разумеется, я могу сказать dtruss -f gcc hello.c и получить несколько ту же функциональность, но тогда компилятор запускается с привилегиями root, что явно нежелательно (кроме огромного риска для безопасности, одна проблема заключается в том, что файл a.out теперь принадлежит root :-)

затем я попытался dtruss -f sudo -u myusername gcc hello.c, но это чувствует себя немного не так, и все равно не работает (я не получаю a.out файла на все это время, не знаю, почему)

Все, что длинная история пытается мотивировать свой оригинальный вопрос : Как мне получить dtrace для запуска моей команды с обычными привилегиями пользователя, как и в случае с strace в linux?

Edit: это, кажется, что я не единственный, кто задавался вопросом, как сделать это: вопрос #1204256 является почти такой же, как у меня (и имеет тот же самый неоптимальный SUDO ответ :-)

ответ

5

Не ответ на ваш вопрос, а что-то знать. OpenSolaris решил эту проблему (частично) с «привилегиями» - см. this page. Даже в OpenSolaris было бы невозможно разрешить пользователю без каких-либо дополнительных привилегий обрабатывать собственный процесс. Причина в том, как работает dtrace - он позволяет зондам в ядре. Таким образом, позволяя не-привилегированному пользователю исследовать ядро, пользователь может делать много нежелательных вещей, например. sniffing passwd другого пользователя, включив зонды в драйвере клавиатуры!

+0

Возможно, вы правы. хотя получение прав root не является проблемой здесь, так как на моем ноутбуке я могу (и сделал это) 'chmod a + s dtrace', но dtrace не предназначен как инструмент« unix power user », а как" unix administrator ". Вот почему попытка использовать его из пользовательских программ приводит к такой надуманной ситуации. Большое спасибо за ваш ответ. – Gyom

+0

Не мог ли он иметь «ограниченный режим», в котором будут запускаться только некоторые зонды (например, зонды зондов или зондовые зонды) и только в некоторых процессах (принадлежащих соответствующему пользователю), и будут доступны только некоторые функции : те, которые могут быть легко сделаны только для проверки собственных процессов пользователя или которые предоставляют доступ к информации, уже доступной пользователю другими способами? – SamB

1

Я не» t знать способ запустить то, что вы хотите, как обычный пользователь, поскольку кажется, что dtruss, который использует dtrace, требует привилегий su.

Однако, я считаю, что команда, которую вы искали вместо

dtruss -f sudo -u myusername gcc hello.c

является

sudo dtruss -f gcc hello.c

После ввода пароля, dtruss будет работать привилегии SUDO DTrace будет, и вы получите трассировку, а также файл a.out.

Извините, но я не могу помочь.

+3

Проблема с фактическим запуском самой команды как root (кроме очевидного гигантского риска для безопасности) заключается в том, что среда выполнения sudo (PATH, env variables, permissions) сильно отличается от обычной, а воздействие резко влияет на поведение трассированная программа. Linux 'strace', напротив, почти прозрачен с точки зрения функционального поведения отслеживаемой команды. – Gyom

5

Я не знаю, можете ли вы получить как неинвазивный, как strace.

Вариант «Суд [искоренять] dtruss Судо [назад некорневой] CMD», что, кажется, лучше работать в некотором быстром тестировании для меня:

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

Внешних Судо, конечно, так dtruss работает как root.

Внутреннее su возвращается ко мне, а с -l оно воссоздает среду должным образом, и в этот момент нам нужно вернуться к тому, с чего мы начали.

Я думаю, что «su -l user» лучше, чем «sudo -u user», если вы хотите, чтобы среда была тем, что обычно получает пользователь.Однако это будет их среда входа; Я не знаю, есть ли хороший способ позволить среде наследовать через два пользовательских изменения.

В вашем вопросе еще одна жалоба, которую вы имели об обходном решении «sudo dtruss sudo», кроме уродства, заключалась в том, что «я не получаю никакого файла a.out на все это время, не знаю почему». Я тоже не знаю, почему, но в моем маленьком тестовом сценарии вариант «sudo dtruss sudo» также не смог записать в тестовый выходной файл, а вариант «sudo dtruss su» выше создал выходной файл.

+0

действительно, спасибо за эту попытку. Тем не менее, похоже, мне придется отказаться от этого.В linux я использовал команды 'strace' из скрипта замены makefile, чтобы отслеживать, какие файлы были затронуты командами. Я хотел перенести эти сценарии в mac os x, но в конце дня я понимаю, что мне не нравится идея иметь все мои сборки с несколькими уровнями sudo только для того, чтобы шпионить за моими собственными командами. – Gyom

+0

Да. Непосредственная попытка заставить dtruss выступать в качестве неинвазивной замены strace, похоже, лает по неправильному дереву по причинам, которые вы описываете. Возможно, необходим альтернативный подход. 2 вещи, которые могут возникнуть для меня: 1) захватить источник dtrace, изменить внешний интерфейс userlevel (который должен запускаться от имени root), поэтому он запускает только новые процессы и только шпионы на них, добавляет опцию, чтобы сообщить, кто запустите эти процессы, а затем сделайте его setuid, принадлежащим root. – metamatt

+0

И № 2 (продолжение с предыдущего комментария): используйте dtrace прямо так, как он был разработан для ответа на вопрос, на который вы хотите ответить, вместо того, чтобы пытаться использовать его как замену dropin для strace в ваших файлах make-файлов, чтобы посмотреть, что делают команды-дети - Можете ли вы написать dtrace-зонды вне процесса make, которые идентифицируют и комментируют то, что делает процесс make? – metamatt

39

Самый простой способ заключается в использовании Sudo:

sudo dtruss -f sudo -u $USER whoami 

Другое решение было бы запустить отладчик первый и монитор для новых специфических процессов. .

sudo dtruss -fn whoami 

Затем в другом терминале просто запустите:

whoami 

просто.

Более сложные аргументы вы можете найти в руководстве: man dtruss


В качестве альтернативы вы можете прикрепить dtruss к запущенному процессу пользователя, например, на Mac:

sudo dtruss -fp PID 

или сходного на Linux/Unix с помощью Трассирование:

sudo strace -fp PID 

Другой Hacky трюк может быть, чтобы выполнить команду и сразу после этого подключить к процессу.Вот некоторые примеры:

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` 

Примечание:

  • первый Судо только для кэширования пароля в первый раз бега,

  • этот трюк не работает для быстрой команды линии, такие как ls, date, так как требуется некоторое время, пока отладчик не присоединяется к этому процессу,

  • Вы должны ввести команду в две плоскости цы,

  • вы можете игнорировать &, чтобы запустить процесс в фоновом режиме, если он уже делает это,

  • после завершения отладки, вам придется вручную убить фоновый процесс (например, killall -v tail)

+5

Вы являетесь рок-звездой для указания опции '-n' для dtruss. Это 100% правильный ответ. – wfaulk

7

-n аргумент dtruss заставит dtruss ждать и исследовать процессы, которые соответствуют аргументу -n. Опция -f будет по-прежнему работать, чтобы отслеживать процессы, связанные с процессами, соответствующими -n.

Всего это означает, что если вы хотите dtruss процесса (ради аргумента, скажем, это whoami) работает в качестве непривилегированного пользователя, выполните следующие действия:

  1. Откройте корневую оболочку
  2. Запуск dtruss -fn whoami
    • это будет сидеть и ждать, пока процесс под названием «Whoami» существовать
  3. Открыть nonprivilege d оболочки
  4. Run whoami
    • это будет выполняться и выход нормально
  5. Наблюдайте след системного вызова в dtruss окне
    • dtruss не выходит сама по себе - он будет продолжать ждать для согласования процессов - поэтому выйти из него, когда вы сделали

Этот ответ дублирует последнюю часть ответа @ kenorb, но он заслуживает того, чтобы быть первоклассным ответом.

3

Кажется, что OS X не поддерживает использование dtrace для репликации всех функций strace, которые вам нужны. Тем не менее, я предлагаю попробовать создать обертку вокруг подходящих системных вызовов. Похоже, что DYLD_INSERT_LIBRARIES - это переменная среды, которую вы хотите взломать. Это в основном то же самое, что и для LD_PRELOAD.

Гораздо проще способ сделать библиотечные функции переопределяет использует переменную DYLD_INSERT_LIBRARIES среды (по аналогии с LD_PRELOAD на Linux). Концепция проста: во время загрузки динамический компоновщик (dyld) загрузит любые динамические библиотеки, указанные в DYLD_INSERT_LIBRARIES , перед любыми библиотеками, которые хочет загрузить исполняемый файл. Назвав функцию такой же, как в библиотечной функции, она переопределит любые вызовы на оригинала.

Исходная функция также загружается и может быть получена с помощью dlsym (RTLD_NEXT, «имя_функции»); функция. Это позволяет использовать простой метод для обертывания существующих функций библиотеки.

Согласно example по Tom Robinson вам может понадобиться установить DYLD_FORCE_FLAT_NAMESPACE=1 тоже.

Копия исходного примера (lib_overrides.c), который переопределяет только 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; 
} 

Использование:

$ 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

Отказ от ответственности: это происходит от @ kenorb-х answer. Это имеет некоторые преимущества: PID более специфичен, чем execname. И мы можем сделать краткосрочный процесс ожидания DTrace до его начала.

Это немного гонки conditiony, но ...

Допустим, мы хотим проследить cat /etc/hosts:

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

Мы используем sudo true, чтобы убедиться, что мы очищаем запрос пароля SUDO перед нами начать работать что-то чувствительное к времени.

Мы начинаем фоновый процесс («подождите 1 секунду, затем сделайте что-нибудь интересное»). Между тем, мы начинаем DTrace. Мы зафиксировали PID фонового процесса в $!, поэтому мы можем передать это DTrace как arg.

kill $! работает после закрытия DTrace. Это не обязательно для нашего примера cat (процесс закрывается сам по себе), но он помогает нам прекратить длительные фоновые процессы, такие как ping. Передача -p $! в DTrace - это предпочтительный способ сделать это, но на macOS, по-видимому, требуется исполняемый код.


Другое, что вы можете сделать, это запустить команду в отдельной оболочке и отследить эту оболочку. См. Мой answer.

 Смежные вопросы

  • Нет связанных вопросов^_^