Цель этого кода - создать трассировку стека всякий раз, когда вызывается sigterm/sigint/sigsegv/etc. Чтобы не полагаться на управление памятью внутри кода C++ в случае sigsegv, я решил написать сценарий bash, который получит адреса PID и памяти в массиве trace. События Sig захватываются.
Ниже я создаю вызов сценария bash
trace_size = backtrace(trace, 16);
trace[1] = (void *)ctx->rsi;
messages = backtrace_symbols(trace, trace_size);
char syscom[356] = {0};
sprintf(syscom,"bash_crash_supp.sh %d", getpid());
for (i=1; i<(trace_size-1) && i < 10; ++i)
{
sprintf(syscom,"%s %p",syscom,trace[i]);
}
Ниже приведена моя проблема. Команда в syscom генерируется правильно. Я могу остановить код до следующего всплывающего окна, запустить команду в терминале и правильно работать. Однако запуск скрипта непосредственно из кода C++ не работает.
setuid(0);
FILE *bashCommand = popen(syscom,"r");
char buf[256] = {0};
while(fgets(buf,sizeof(buf),bashCommand) != 0) {
LogMessage(LOG_WARNING, "%s\n", buf);
}
pclose(bashCommand);
exit(sig);
Цель сценария bash - получить смещение от /proc/pid/maps, а затем использовать его для запуска addr2line, чтобы получить имя файла/номер строки.
strResult=$(sudo cat /proc/"$1"/maps | grep "target_file" | grep -m 1 '[0-9a-fA-F]')
offset=$( cut -d '-' -f 1 <<< "$strResult");
Однако смещение становится 0, когда я запускаю код C++, но когда я запускаю ту же самую команду (которая хранится в syscom в коде C++) в терминале, я получаю ожидаемый результат.
Я пытался это исправить некоторое время. Разрешения, скорее всего, являются проблемой, но я попытался обойти их всеми способами, которые я знаю/видел через Google. Пользователь, пытающийся запустить скрипт (в настоящее время выполняется код C++), является apache.
Исправить не нужно беспокоиться о безопасности коробки. Если бы работало так просто, как "chmod 777/proc -r", это было бы решением (к сожалению, ОС не позволяет мне делать такие команды с /proc).
Вещи, которые я уже пробовал:
Команда, сгенерированная в C++
bash_crash_supp.sh 25817 0x7f4bfe600ec8 0x7f4bf28f7400 0x7f4bf28f83c6 0x7f4bf2904f02 0x7f4bfdf0fbb0 0x7f4bfdf1346e 0x7f4bfdf1eb30 0x7f4bfdf1b9a8 0x7f4bfdf176b8
Params in bash:
25817 0x7f4bfe600ec8 0x7f4bf28f7400 0x7f4bf28f83c6 0x7f4bf2904f02 0x7f4bfdf0fbb0 0x7f4bfdf1346e 0x7f4bfdf1eb30 0x7f4bfdf1b9a8 0x7f4bfdf176b8
Может ли кто-нибудь подумать о других способах решения этого?
Короче говоря, почти все системы на основе Unix игнорируют setuid
на любом интерпретируемом скрипте (что-либо с shebang #!
) В качестве меры предосторожности.
Вы можете использовать setuid
для реальных исполняемых файлов, но не сами сценарии оболочки. Если вы готовы принять серьезный риск для безопасности, вы можете сделать исполняемый файл оболочки для запуска сценария оболочки и предоставить исполняемый setuid
.
Для получения дополнительной информации см. Этот вопрос в Unix StackExchange: https://unix.stackexchange.com/a/2910
#!
)bash_crash_supp.sh
сценарииbash_crash_supp.sh
и 2)bash_crash_supp.sh
echo "$*"
в сценарий оболочки иbash_crash_supp.sh
результаты.