実行するように指示されたシェルで実行すると、strace
実際のバイナリが実行される前に広範な統計を示す次の出力が得られます。bash
mkdir
mkdir
BASH$> strace -f sh -c "bash -c \"mkdir /tmp\" 2>&1 | nl | grep -e "execve\|stat\|access"
[.....]
2766 [pid 17371] stat(".", {st_mode=S_IFDIR|0750, st_size=17262, ...}) = 0
2767 [pid 17371] stat("/usr/local/sbin/mkdir", 0x7ffd87aad0a0) = -1 ENOENT 2767 (No such file or directory)
2768 [pid 17371] stat("/usr/local/bin/mkdir", 0x7ffd87aad0a0) = -1 ENOENT (No such file or directory)
2769 [pid 17371] stat("/usr/bin/mkdir", {st_mode=S_IFREG|0755, st_size=51136, ...}) = 0
2770 [pid 17371] stat("/usr/bin/mkdir", {st_mode=S_IFREG|0755, st_size=51136, ...}) = 0
2771 [pid 17371] access("/usr/bin/mkdir", X_OK) = 0
2772 [pid 17371] stat("/usr/bin/mkdir", {st_mode=S_IFREG|0755, st_size=51136, ...}) = 0
2773 [pid 17371] access("/usr/bin/mkdir", R_OK) = 0
2774 [pid 17371] stat("/usr/bin/mkdir", {st_mode=S_IFREG|0755, st_size=51136, ...}) = 0
2775 [pid 17371] stat("/usr/bin/mkdir", {st_mode=S_IFREG|0755, st_size=51136, ...}) = 0
2776 [pid 17371] access("/usr/bin/mkdir", X_OK) = 0
2777 [pid 17371] stat("/usr/bin/mkdir", {st_mode=S_IFREG|0755, st_size=51136, ...}) = 0
2778 [pid 17371] access("/usr/bin/mkdir", R_OK) = 0
2779 [pid 17371] execve("/usr/bin/mkdir", ["mkdir", "/tmp"], 0x557ec7e15920 /* 5 vars */) = 0
/usr/bin/mkdir
stat()
私の質問は:頻繁に編集されるのが普通ですか(それではなぜですか?)出力ラインには番号が付けられています。特にこの行が実行され2776
たらどういう意味があるのか知りたいです2771
。また、私はbashがすぐに情報を提供する必要があるため、2770
すべてのシステムコールを最初から最後まで保存するという印象を受けました。私は何を見逃していますか?execve
stat
以降の説明を調べて、代替dash
シェルがどのように機能するかを確認し、次のstat()
内容も表示されます。
DASH$> strace -f sh -c "dash -c \"mkdir /tmp\" 2>&1 | nl | grep -e "execve\|stat\|access"
[....]
2792 [pid 17372] stat("/usr/local/sbin/mkdir", 0x7ffc66010b50) = -1 ENOENT (No such file or directory)
2793 [pid 17372] stat("/usr/local/bin/mkdir", 0x7ffc66010b50) = -1 ENOENT (No such file or directory)
2794 [pid 17372] stat("/usr/sbin/mkdir", {st_mode=S_IFREG|0755, st_size=51136, ...}) = 0
2795 [pid 17372] execve("/usr/sbin/mkdir", ["mkdir", "/run"], 0x55d8d3453bb8 /* 6 vars */) = 0
私は2792
、2793
が2768 PATH`行に似ていることを知っています。2767
are because of searching the executable in the various directories in the current
これがセール中であれば、一統計dash
だけしてbash
10回だけしてください。もう一度質問:これは普通ですか?
修正する:Bash統計には、より多くのgeteuid()
、getguid()
およびgetuid()
混合項目があります。getgid()
BASH$>strace -f sh -c "bash -c \"mkdir /tmp\"" 2>&1 | grep -e "execve\|stat\|access\|geteuid\|getegid\|getuid\|getgid"
[....]
[pid 24534] stat("/usr/local/bin/mkdir", 0x7fffda480f30) = -1 ENOENT (No such file or directory)
[pid 24534] stat("/usr/local/sbin/mkdir", 0x7fffda480f30) = -1 ENOENT (No such file or directory)
[pid 24534] stat("/usr/bin/mkdir", {st_mode=S_IFREG|0755, st_size=51136, ...}) = 0
[pid 24534] stat("/usr/bin/mkdir", {st_mode=S_IFREG|0755, st_size=51136, ...}) = 0
[pid 24534] geteuid() = 1000
[pid 24534] getegid() = 1000
[pid 24534] getuid() = 1000
[pid 24534] getgid() = 1000
[pid 24534] access("/usr/bin/mkdir", X_OK) = 0
[pid 24534] stat("/usr/bin/mkdir", {st_mode=S_IFREG|0755, st_size=51136, ...}) = 0
[pid 24534] geteuid() = 1000
[pid 24534] getegid() = 1000
[pid 24534] getuid() = 1000
[pid 24534] getgid() = 1000
[pid 24534] access("/usr/bin/mkdir", R_OK) = 0
[pid 24534] stat("/usr/bin/mkdir", {st_mode=S_IFREG|0755, st_size=51136, ...}) = 0
[pid 24534] stat("/usr/bin/mkdir", {st_mode=S_IFREG|0755, st_size=51136, ...}) = 0
[pid 24534] geteuid() = 1000
[pid 24534] getegid() = 1000
[pid 24534] getuid() = 1000
[pid 24534] getgid() = 1000
[pid 24534] access("/usr/bin/mkdir", X_OK) = 0
[pid 24534] stat("/usr/bin/mkdir", {st_mode=S_IFREG|0755, st_size=51136, ...}) = 0
[pid 24534] geteuid() = 1000
[pid 24534] getegid() = 1000
[pid 24534] getuid() = 1000
[pid 24534] getgid() = 1000
[pid 24534] access("/usr/bin/mkdir", R_OK) = 0
[pid 24534] execve("/usr/bin/mkdir", ["mkdir", "/tmp"], 0x55adcd4dc040 /* 55 vars */) = 0
それでは、これが「ここで何が起こっているのか」についての手がかりを提供できますか?悪用を防ぐためにいくつかのテストが実施されていますかsetuid
?
**更新2:** geteuid()
、getguid()
およびgetuid()
アクセスの組み合わせは、ライブラリ機能の使用の特徴であるようですgetgid()
。使用するたびにbashが実行されるため、all、およびを使用します。glibc
int eaccess(const char *pathname, int mode);
eaccess
geteuid
getguid
getuid
getgid
access
findcmd.c関数はfile_status
このようにeaccessを2回実行します。
#if defined (HAVE_EACCESS)
/* Use eaccess(2) if we have it to take things like ACLs and other
file access mechanisms into account. eaccess uses the effective
user and group IDs, not the real ones. We could use sh_eaccess,
but we don't want any special treatment for /dev/fd. */
if (eaccess (name, X_OK) == 0)
r |= FS_EXECABLE;
if (eaccess (name, R_OK) == 0)
r |= FS_READABLE;
これらの各eaccessは、4つのシステムコールに接続できます。
ベストアンサー1
ループを見てください。findcmd.c:find_user_command_in_path()
。
stat()
(からfile_status()
)パスの各要素を2回:find_in_path_element()
at行を介して1回640is_directory()
atラインを通って一度645話。
おっしゃった通りfile_status()
いわゆるeaccess()
。
これは最適化できますが、パスがハッシュされ、これらのすべての検索と統計はコマンドが最初に使用されたときにのみ発生するため、大きな問題ではないことに注意してください。