setuid したバイナリの strace を取ると /etc/suid-debug を access(2) でみている - LD_DEBUG の制御に使うファイルだった

Linux で setuid したバイナリで検証作業している時に知った /edtc/suid-debug について調べた内容です。

なぜ こんなことを調べているのですか?

まず、setuid-sleep という setuid したバイナリがあリます。これは sleep するだけの setuid 検証用のバイナリです。

$ ls -hal setuid-sleep                                                                                                                                                                               
-rwsr-xr-x 1 root hiboma 16K Jun  6 10:50 setuid-sleep                                                                                                                                                           

$ stat setuid-sleep
  File: setuid-sleep
  Size: 15960           Blocks: 32         IO Block: 4096   regular file
Device: fc02h/64514d    Inode: 135566      Links: 1
Access: (4755/-rwsr-xr-x)  Uid: (    0/    root)   Gid: ( 1000/  hiboma)
Access: 2023-06-06 10:56:50.342504983 +0900
Modify: 2023-06-06 10:50:08.884304931 +0900
Change: 2023-06-06 10:56:46.206522908 +0900
 Birth: 2023-06-06 10:50:08.872304965 +0900

# 環境は Ubuntu Jammy です
$ uname -a
Linux vps 5.15.0-60-generic #66-Ubuntu SMP Fri Jan 20 14:29:49 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux

strace をとると access(2) で /etc/suid-debug の有無を確認しているのを発見しました。

$ strace -f ./setuid-sleep
execve("./setuid-sleep", ["./setuid-sleep"], 0x7ffc7af04528 /* 23 vars */) = 0
🔥 access("/etc/suid-debug", F_OK)         = -1 ENOENT (No such file or directory)
brk(NULL)                               = 0x55653bde3000
arch_prctl(0x3001 /* ARCH_??? */, 0x7ffd013de010) = -1 EINVAL (Invalid argument)
fcntl(0, F_GETFD)                       = 0
fcntl(1, F_GETFD)                       = 0
fcntl(2, F_GETFD)                       = 0
🔥 access("/etc/suid-debug", F_OK)         = -1 ENOENT (No such file or directory)

おっと /etc/suid-debug ファイルはなんだろう? 🤔 ... となって調べた次第です。

調べてみた

Google で調べて man にたどりつきました。

ld-linux.so(8) — manpages — Debian testing — Debian Manpages

Since glibc 2.3.4, LD_DEBUG is ignored in secure-execution mode, unless the file /etc/suid-debug exists (the content of the file is irrelevant).

  • setuid していると LD_DEBUG が無視される ( secure-execution mode )
  • /etc/suid-debug があれば、LD_DEBUG が有効なままになる

ということらしいです。

LD_DEBUG とは?

LD_DEBUG については下記の説明を引用します

LD_DEBUG

(glibc 2.1 以降) 動的リンカーの詳細なデバッグ情報を出力する。 all に設定した場合、全ての動的リンカーが持つデバッグ情報を表示する。 help に設定した場合、この環境変数で指定されるカテゴリーのヘルプ情報を表示する。 glibc 2.3.4 以降、 set-user-ID/set-group-ID されたバイナリでは LD_DEBUG は無視される。

実験: /etc/suid-debug の有無で LD_DEBUG のふるまいを観察する

/etc/suid-debug がないと何もでないですね

$ LD_DEBUG=symbols ./setuid-sleep 

次に、 /etc/suid-debug を touch(3) で作成して、再度実行します。するとデバッグのログがたくさん出てきた!

$ sudo touch  /etc/suid-debug 
$ LD_DEBUG=symbols ./setuid-sleep
    963912:     symbol=__vdso_clock_gettime;  lookup in file=linux-vdso.so.1 [0]
    963912:     symbol=__vdso_gettimeofday;  lookup in file=linux-vdso.so.1 [0]
    963912:     symbol=__vdso_time;  lookup in file=linux-vdso.so.1 [0]
    963912:     symbol=__vdso_getcpu;  lookup in file=linux-vdso.so.1 [0]
    963912:     symbol=__vdso_clock_getres;  lookup in file=linux-vdso.so.1 [0]
    963912:     symbol=_res;  lookup in file=./setuid-sleep [0]
    963912:     symbol=_res;  lookup in file=/lib/x86_64-linux-gnu/libc.so.6 [0]
    963912:     symbol=svc_max_pollfd;  lookup in file=./setuid-sleep [0]
    963912:     symbol=svc_max_pollfd;  lookup in file=/lib/x86_64-linux-gnu/libc.so.6 [0]
    963912:     symbol=obstack_alloc_failed_handler;  lookup in file=./setuid-sleep [0]
    963912:     symbol=obstack_alloc_failed_handler;  lookup in file=/lib/x86_64-linux-gnu/libc.so.6 [0]
    963912:     symbol=__ctype_toupper;  lookup in file=./setuid-sleep [0]
    963912:     symbol=__ctype_toupper;  lookup in file=/lib/x86_64-linux-gnu/libc.so.6 [0]
    963912:     symbol=loc1;  lookup in file=./setuid-sleep [0]
    963912:     symbol=loc1;  lookup in file=/lib/x86_64-linux-gnu/libc.so.6 [0]
    963912:     symbol=_dl_argv;  lookup in file=./setuid-sleep [0]
    963912:     symbol=_dl_argv;  lookup in file=/lib/x86_64-linux-gnu/libc.so.6 [0]
    963912:     symbol=_dl_argv;  lookup in file=/lib64/ld-linux-x86-64.so.2 [0]

... 略

感想

  • strace してると「あれ なんだこれ? 」って発見がある
    • もともと調べたいことではなくて、脇道にそれてしまう 🌝

参考

LD_DEBUG で指定できるオプションは下記の通りです。

LD_DEBUG (since glibc 2.1)

Output verbose debugging information about operation of the dynamic linker. The content of this variable is one of more of the following categories, separated by colons, commas, or (if the value is quoted) spaces:

help
    Specifying help in the value of this variable does not run the specified program, and displays a help message about which categories can be specified in this environment variable.

all
    Print all debugging information (except statistics and unused; see below).

bindings
  Display information about which definition each symbol is bound to.

files
    Display progress for input file.

libs
    Display library search paths.

reloc
    Display relocation processing.

scopes
    Display scope information.

statistics
    Display relocation statistics.

symbols
    Display search paths for each symbol look-up.

unused
    Determine unused DSOs.

versions
    Display version dependencies.

Since glibc 2.3.4, LD_DEBUG is ignored in secure-execution mode, unless the file /etc/suid-debug exists (the content of the file is irrelevant).
`