Как оказалось, для моей конкретной системы конфигурация ядра отсутствовала. Это была поддержка LPSS от Intel. CONFIG_X86_INTEL_LPSS
, который имеет особую поддержку 80860F14
acpi периферийных устройств и необходим для моего накопителя Samsung eMMC. После его включения драйверы блока и ядра mmc могли видеть / dev / mmcblk0
.
Если вы установите опцию set -x
, то вы увидите команды, которые выполняются в оболочке в трассировке.
Это немного похоже на взлом, но вы можете предварительно загрузить немного кода 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);
}
Если в 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).