「Binary Hacks Rebooted」を読んだメモ
· 約7分
MEMO
shebang
- interpreter 以外のプログラムを指定することもできるらしい
% cat test.sh
───────┬──────────────────────────────────────────
│ File: test.sh
───────┼──────────────────────────────────────────
1 │ #!/bin/ls -al
2 │ echo "Hello World"
───────┴──────────────────────────────────────────
% ./test.sh
-rwxr-xr-x 1 mmori mmori 33 Mar 25 18:35 ./test.sh
- 引数は複数渡そうとしても無理っぽい
% cat test.sh
───────┬──────────────────────────────────
│ File: test.sh
───────┼──────────────────────────────────
1 │ #!/bin/ls --all -l
2 │ echo "Hello World"
───────┴──────────────────────────────────
% ./test.sh
/bin/ls: unrecognized option '--all -l'
Try '/bin/ls --help' for more information.
-
Impl: https://elixir.bootlin.com/linux/v6.13.7/source/fs/binfmt_script.c#L34-L138
-
interpreter を見つけたあとにオプションとして一つ引数を取る
/* Is there an optional argument? */
i_arg = NULL;
i_sep = next_terminator(i_name, i_end);
if (i_sep && (*i_sep != '\0'))
i_arg = next_non_spacetab(i_sep, i_end);
-
よく
#!/bin/env python3
とかがあるけどこれのおかげで動いている -
色々飛ばして最後は open_exec で実行
/*
* OK, now restart the process with the interpreter's dentry.
*/
file = open_exec(i_name);
if (IS_ERR(file))
return PTR_ERR(file);
binfmt_misc
# binfmt
sudo pacman -S qemu-user-static-binfmt binfmt-wasm
# Compilers
sudo pacman -S aarch64-linux-gnu-gcc aarch64-linux-gnu-glibc
% ls /proc/sys/fs/binfmt_misc/
DOSWin qemu-alpha qemu-hexagon qemu-m68k qemu-mips qemu-mipsel qemu-or1k qemu-ppc64le qemu-s390x qemu-sparc qemu-xtensa status
qemu-aarch64 qemu-arm qemu-hppa qemu-microblaze qemu-mips64 qemu-mipsn32 qemu-ppc qemu-riscv32 qemu-sh4 qemu-sparc32plus qemu-xtensaeb wasip1
qemu-aarch64_be qemu-armeb qemu-loongarch64 qemu-microblazeel qemu-mips64el qemu-mipsn32el qemu-ppc64 qemu-riscv64 qemu-sh4eb qemu-sparc64 register wasip2
% cat /proc/sys/fs/binfmt_misc/qemu-aarch64
───────┬───────────────────────────────────────────────
│ File: /proc/sys/fs/binfmt_misc/qemu-aarch64
───────┼───────────────────────────────────────────────
1 │ enabled
2 │ interpreter /usr/bin/qemu-aarch64-static
3 │ flags: PF
4 │ offset 0
5 │ magic 7f454c460201010000000000000000000200b700
6 │ mask ffffffffffffff00fffffffffffffffffeffffff
───────┴───────────────────────────────────────────────
% aarch64-linux-gnu-gcc hello.c -static -o hello-aarch64
% xxd -l 0x20 hello-aarch64
00000000: 7f45 4c46 0201 0103 0000 0000 0000 0000 .ELF............
00000010: 0200 b700 0100 0000 c006 4000 0000 0000 ..........@.....
- EI_OSABI が違うけど動く…
- ELF header
% cat /proc/sys/fs/binfmt_misc/wasip1
───────┬─────────────────────────────────────────────
│ File: /proc/sys/fs/binfmt_misc/wasip1
───────┼─────────────────────────────────────────────
1 │ enabled
2 │ interpreter /usr/bin/binfmt-wasmtime-wrapper
3 │ flags:
4 │ offset 0
5 │ magic 0061736d01000000
───────┴─────────────────────────────────────────────
% cat /proc/sys/fs/binfmt_misc/wasip2
───────┬─────────────────────────────────────────────
│ File: /proc/sys/fs/binfmt_misc/wasip2
───────┼─────────────────────────────────────────────
1 │ enabled
2 │ interpreter /usr/bin/binfmt-wasmtime-wrapper
3 │ flags:
4 │ offset 0
5 │ magic 0061736d0d000100
───────┴─────────────────────────────────────────────
% rustc --target wasm32-wasip1 main.rs -o hello-wasm
% rustc --target wasm32-wasip2 main.rs -o hello-wasmp2
% xxd -l 0x20 hello-wasm
00000000: 0061 736d 0100 0000 016c 0f60 0000 6001 .asm.....l.`..`.
00000010: 7f00 6002 7f7f 017f 6001 7f01 7f60 037f ..`.....`....`..
% xxd -l 0x20 hello-wasmp2
00000000: 0061 736d 0d00 0100 0724 0142 0401 6f02 .asm.....$.B..o.
00000010: 7373 0170 0001 4000 0001 0400 0f67 6574 ss.p..@......get
- cargo で aarch64 用のバイナリを作るときには .cargo/config.toml でも設定できる
% cat .cargo/config.toml
───────┬─────────────────────────────────────────────────
│ File: .cargo/config.toml
───────┼─────────────────────────────────────────────────
1 │ [target.aarch64-unknown-linux-gnu]
2 │ linker = "aarch64-linux-gnu-gcc"
3 │ rustflags = ["-C", "target-feature=+crt-static"]
───────┴─────────────────────────────────────────────────
CRIU
- /proc/sys/kernel/ns_last_pid は CRIU の開発者が追加したらしい
- criu-ns を使うと PID の namespace を分けて重複を避けることができる
Unikernel
- Unikraft: https://github.com/unikraft/unikraft
- CLI tool: https://github.com/unikraft/kraftkit
- Tutorials: https://unikraft.org/docs/cli
# ディストリビューションごとの package manager を使ってくれる
curl -sSfL https://get.kraftkit.sh | sh
cd workspace
# Create Kraftfile
cat << EOF | tee Kraftfile
spec: v0.6
name: template
unikraft: stable
targets:
- qemu/x86_64
EOF
# Config
kraft menu
# Create Makefile
cat << EOF | tee Makefile
$(eval $(call addlib,apphelloworld))
APPHELLOWORLD_SRCS-y += $(APPHELLOWORLD_BASE)/main.c
EOF
# main.c
cat << EOF | tee main.c
#include <stdio.h>
#include <unistd.h>
int main(void) {
printf("Hello, Kernel World!\n");
for (;;) {}
printf("Can't reach here\n");
return 0;
}
EOF
# Build
kraft build
# Run
kraft run
% kraft build
[+] updating index... done! [6.3s]
[?] project already configured, are you sure you want to rerun the configure step: [Y/n]
[+] configuring template (qemu/x86_64) ••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••• 100% [1.3s]
[+] building template (qemu/x86_64) ••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••• 100% [3.7s]
[●] Build completed successfully!
│
└─ kernel: .unikraft/build/template_qemu-x86_64 (242 kB)
Learn how to package your unikernel with: kraft pkg --help
kraft build 4.37s user 2.42s system 49% cpu 13.588 total
% kraft run
i using arch=x86_64 plat=qemu
o. .o _ _ __ _
Oo Oo ___ (_) | __ __ __ _ ' _) :_
oO oO ' _ `| | |/ / _)' _` | |_| _)
oOo oOO| | | | | (| | | (_) | _) :_
OoOoO ._, ._:_:_,\_._, .__,_:_, \___)
Helene 0.18.0
Hello, Kernel World!
% ps ax | grep qemu
2896210 ? Sl 0:14 qemu-system-x86_64 -cpu host,+x2apic,-pmu -daemonize -device pvpanic -display none -enable-kvm -kernel $WORKDIR/.unikraft/build/template_qemu-x86_64 -machine pc,accel=kvm -m size=64M -monitor unix:$HOME/.local/share/kraftkit/runtime/0d3aa028c089/mon.sock,server,nowait -name 0d3aa028c089 -nographic -no-reboot -S -parallel none -pidfile $HOME/.local/share/kraftkit/runtime/0d3aa028c089/machine.pid -qmp unix:$HOME/.local/share/kraftkit/runtime/0d3aa028c089/ctrl.sock,server,nowait -qmp unix:$HOME/.local/share/kraftkit/runtime/0d3aa028c089/evnt.sock,server,nowait -rtc base=utc -serial file:$HOME/.local/share/kraftkit/runtime/0d3aa028c089/vm.log -smp cpus=1,threads=1,sockets=1 -vga none
sleep 関数を呼ぼうとしたら build でこけた。今回はテストなので一旦無視する
% kraft build
[+] updating index... done! [6.3s]
[?] project already configured, are you sure you want to rerun the configure step: [Y/n]
[+] configuring template (qemu/x86_64) ••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••• 100% [1.2s]
<!> building template (qemu/x86_64) •• 2% [4.1s]
W make: hostname: No such file or directory
i LN Makefile
W make[1]: hostname: No such file or directory
W which: no time in ($HOME/.cargo/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/var/lib/flatpak/exports/bin:/usr/lib/jvm/default/bin:/usr/bin/site_perl:/usr/bin/vendor
i CP config
i GEN libuklibid: libraries.in.new
W make: hostname: No such file or directory
W make[1]: hostname: No such file or directory
W which: no time in ($HOME/.cargo/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/var/lib/flatpak/exports/bin:/usr/lib/jvm/default/bin:/usr/bin/site_perl:/usr/bin/vendor
W make: hostname: No such file or directory
i LN Makefile
W make[1]: hostname: No such file or directory
W which: no time in ($HOME/.cargo/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/var/lib/flatpak/exports/bin:/usr/lib/jvm/default/bin:/usr/bin/site_perl:/usr/bin/vendor
i CP config
i GEN libuklibid: libraries.in.new
i CP libuklibid: libraries.in
W $WORKDIR/main.c: In function ‘main’:
W $WORKDIR/main.c:6:9: error: implicit declaration of function ‘sleep’ [-Wimplicit-function-declaration]
W 6 | sleep(10);
W | ^~~~~
W make[1]: *** [$WORKDIR/.unikraft/unikraft/support/build/Makefile.build:27: $HOME/workspace/binary_hacks_rebooted/uniker
i CC apphelloworld: main.o
W make: *** [Makefile:1175: sub-make] Error 2
E could not complete build: build failed: exit status 2
kraft build 4.75s user 2.70s system 36% cpu 20.281 total
bpftrace
https://github.com/bpftrace/bpftrace
% sudo bpftrace tools/bashreadline.bt
Attaching 3 probes...
Tracing bash commands... Hit Ctrl-C to end.
TIME PID COMMAND
09:41:34 3091887 ls
09:41:42 3091887 echo hello
09:41:48 3091887 df -h
^C
% sudo bpftrace tools/cpuwalk.bt
Attaching 2 probes...
Sampling CPU at 99hz... Hit Ctrl-C to end.
^C
@cpu:
[0, 1) 17 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
[1, 2) 18 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
[2, 3) 22 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
[3, 4) 19 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
[4, 5) 7 |@@@@@@@@@@@@@ |
[5, 6) 5 |@@@@@@@@@ |
[6, 7) 18 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
[7, 8) 15 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
[8, 9) 1 |@ |
[9, 10) 9 |@@@@@@@@@@@@@@@@@ |
[10, 11) 14 |@@@@@@@@@@@@@@@@@@@@@@@@@@ |
[11, 12) 20 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
[12, 13) 12 |@@@@@@@@@@@@@@@@@@@@@@@ |
[13, 14) 17 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
[14, 15) 15 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
[15, 16) 27 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
Meltdown/Spectre
https://github.com/kianenigma/meltdown-spectre/blob/master/meltdown-spectre/main-meltdown.c