Как получить дополнительную информацию о происхождении кода выхода?

Как оказалось, для моей конкретной системы конфигурация ядра отсутствовала. Это была поддержка LPSS от Intel. CONFIG_X86_INTEL_LPSS , который имеет особую поддержку 80860F14 acpi периферийных устройств и необходим для моего накопителя Samsung eMMC. После его включения драйверы блока и ядра mmc могли видеть / dev / mmcblk0 .

5
08.09.2016, 15:39
3 ответа

Если вы установите опцию set -x , то вы увидите команды, которые выполняются в оболочке в трассировке.

5
27.01.2020, 20:33

Это немного похоже на взлом, но вы можете предварительно загрузить немного кода C в качестве прокладки, чтобы перехватить вызов exit (126) и получить его выдает сигнал SIGSTOP группе процессов, который приостанавливает процесс (и его родителей в той же группе).

Например, если мы перехватили код выхода 2 в нашей оболочке оболочки, запустите ls для несуществующего файла:

LD_PRELOAD=/home/meuh/shim_exit.so bash -c ' sh -c "ls -l xxx; echo"; echo '

он отобразит в фоновом режиме сообщение

[1]+  Stopped  ...

, и вы сможете увидеть процессы в статусе T wait:

~ $ ps f
  PID TTY      STAT   TIME COMMAND
30528 pts/3    T      0:00  \_ bash -c sh -c "ls -l xxx;echo";echo
30529 pts/3    T      0:00  |   \_ sh -c ls -l xxx;echo
30530 pts/3    T      0:00  |       \_ ls -l xxx

На этом этапе вы можете подключиться к процессам, если они являются отлаживаемыми, или просто передний план или SIGCONT процессы для продолжения.

Вот код shim_exit.c, см. Комментарий C для компиляции.

/*
 * capture calls to a routine and replace with your code
 * http://unix.stackexchange.com/a/308694/119298
 * gcc -Wall -O2 -fpic -shared -ldl -o shim_exit.so shim_exit.c
 * LD_PRELOAD=/home/meuh/shim_exit.so ./test
 */
#define _GNU_SOURCE /* needed to get RTLD_NEXT defined in dlfcn.h */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <dlfcn.h>
/* doesnt work for syscall exit_group() */
void exit(int status){
    static void (*real_exit)(int status) = NULL;

    if (!real_exit) {
        real_exit = dlsym(RTLD_NEXT, "exit");
        char *error = dlerror();
        if (error != NULL) {
            fprintf(stderr, "%s\n", error);
            _exit(1);
        }
    }
    if (status==126/* || status==2*/)kill(0,SIGSTOP);
    real_exit(status);
}
4
27.01.2020, 20:33

Если в Linux, вы можете запустить команду под strace - fe process , чтобы узнать, какой процесс выполнил exit_group (126) и какую команду он (или любая из его родительских, если он сам ничего не выполнял) выполнил последней перед этим:

$ strace -fe process sh -c 'env sh -c /; exit'
execve("/bin/sh", ["sh", "-c", "env sh -c /; exit"], [/* 53 vars */]) = 0
arch_prctl(ARCH_SET_FS, 0x7f24713b1700) = 0
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f24713b19d0) = 26325
strace: Process 26325 attached
[pid 26324] wait4(-1,  <unfinished ...>
[pid 26325] execve("/usr/bin/env", ["env", "sh", "-c", "/"], [/* 53 vars */]) = 0
[pid 26325] arch_prctl(ARCH_SET_FS, 0x7fbdb4e2c700) = 0
[pid 26325] execve("/bin/sh", ["sh", "-c", "/"], [/* 53 vars */]) = 0
[pid 26325] arch_prctl(ARCH_SET_FS, 0x7fef90b3b700) = 0
[pid 26325] clone(strace: Process 26326 attached
child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7fef90b3b9d0) = 26326
[pid 26325] wait4(-1,  <unfinished ...>
[pid 26326] execve("/", ["/"], [/* 53 vars */]) = -1 EACCES (Permission denied)
sh: 1: /: Permission denied
[pid 26326] exit_group(126)             = ?
[pid 26326] +++ exited with 126 +++
[pid 26325] <... wait4 resumed> [{WIFEXITED(s) && WEXITSTATUS(s) == 126}], 0, NULL) = 26326
[pid 26325] --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=26326, si_uid=10031, si_status=126, si_utime=0, si_stime=0} ---
[pid 26325] exit_group(126)             = ?
[pid 26325] +++ exited with 126 +++
<... wait4 resumed> [{WIFEXITED(s) && WEXITSTATUS(s) == 126}], 0, NULL) = 26325
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=26325, si_uid=10031, si_status=126, si_utime=0, si_stime=0} ---
exit_group(126)                         = ?
+++ exited with 126 +++

Выше , это был процесс 26326, который первым завершился с 126, потому что он попытался выполнить / . Это был дочерний процесс 26325, который последний раз выполнил sh -c / .

Если эти сценарии являются сценариями bash или являются сценариями sh , а sh оказывается в вашей системе bash ), вы мог бы сделать:

$ env SHELLOPTS=xtrace \
      BASH_XTRACEFD=7 7>&2 \
      PS4='[$?][$BASHPID|${BASH_SOURCE:-$BASH_EXECUTION_STRING}|$LINENO]+ ' \ 
    sh -c 'env sh -c /; exit'
[0][30625|env sh -c /; exit|0]+ env sh -c /
[0][30626|/|0]+ /
sh: /: Is a directory
[126][30625|env sh -c /; exit|0]+ exit

Это не говорит нам точно, какой процесс завершился с 126, но может дать вам достаточно подсказки.

Мы используем BASH_TRACEFD = 7 7> & 2 , чтобы трассировки выводились на исходном stderr, даже когда stderr перенаправляется в сценариях. В противном случае эти сообщения трассировки могут повлиять на поведение сценариев, если они будут делать что-то вроде (....) 2> & 1 | ... . Это предполагает, что эти скрипты явно не используют и не закрывают fd 7 сами (это маловероятно, гораздо более маловероятно, чем перенаправление stderr).

6
27.01.2020, 20:33

Теги

Похожие вопросы