env for FreeBSD kernel.debug
Table of Contents
minimam jail
前回jailでchrootが利用されてるか調査しようとして、jail構築の複雑さゆえ 断念しちゃった。その後jail(8)してたら、こんな例に出会った。マニュアル をタイパ良く読むコツは、コード例を拾う事です。
Start a shell in the jail: jail -c path=/data/jail/testjail mount.devfs \ host.hostname=testhostname ip4.addr=192.0.2.100 \ command=/bin/sh
そうか、コマンドラインから、jailの骨格を指定できるとな。必須は、刑務所 の所在地と、中に入って何をするかだけなんだな。ホスト名とか、ネットワー ク設定とかは、本質じゃないだろう。
こう想像すると、jail == chrootと見做せそう。
root@fb:~ # chroot /tmp/MINE # exit exit root@fb:~ # jail -c path=/tmp/MINE command=/bin/csh
chrootが出来る事を確認後、jailしてみた。正に刑務所なう である。
sakae@fb:/tmp $ jls JID IP Address Hostname Path 2 /tmp/MINE sakae@fb:/tmp $ ps a PID TT STAT TIME COMMAND : 2624 1 I 0:00.00 jail -c path=/tmp/MINE command=/bin/csh
本当に、刑務所が出来たかは、外部から確認できる。
check chroot
gdbしてみます。
root@fb:~ # gdb -q jail Reading symbols from jail... Reading symbols from /usr/lib/debug//usr/sbin/jail.debug... (gdb) b chroot Function "chroot" not defined. Make breakpoint pending on future shared library load? (y or [n]) y Breakpoint 1 (chroot) pending. (gdb) r -c path=/tmp/MINE command=/bin/csh Starting program: /usr/sbin/jail -c path=/tmp/MINE command=/bin/csh [Detaching after fork from child process 2654] # exit exit [Inferior 1 (process 2652) exited normally] (gdb)
引っかからないですねぇ。
root@fb:~ # ktrace jail -c path=/tmp/MINE command=/bin/csh # exit exit root@fb:~ # kdump -sS >LOG root@fb:~ # grep chroot LOG root@fb:~ #
これにも載っていない。しょうがないので、少しLOGを偵察。
2658 jail CALL jail_set[507](0xffbfe890,0x6,0x1) 2658 jail NAMI "/tmp/MINE" 2658 jail NAMI "/tmp/MINE" 2658 jail RET jail_set[507] 4 2658 jail CALL cpuset_getid[486](0x1,0x2,0xffffffff,0xffffffff,0x41172c) 2658 jail RET cpuset_getid[486] 0 2658 jail CALL fork[2] 2658 jail RET fork[2] 2659/0xa63
pathは出てくるんだけど、command=/bin/cshは出てきていない。それにforkと 対になるexecveも無い。どうなってるの? 一応、足跡だけでも残しておく。
(gdb) bt #0 jail_set () at jail_set.S:4 #1 0x20452b60 in jailparam_set (jp=0xffbfe920, njp=2, flags=1) at /usr/src/lib/libjail/jail.c:550 #2 0x0040805c in jailparam_set_note (j=0x20674000, jp=jp@entry=0xffbfe920, njp=2, flags=1) at /usr/src/usr.sbin/jail/jail.c:917 #3 0x00407cdf in create_jail (j=0x20674000) at /usr/src/usr.sbin/jail/jail.c:659 #4 0x00408843 in run_command (j=j@entry=0x20674000) at /usr/src/usr.sbin/jail/command.c:330 #5 0x004084e7 in next_command (j=0x20674000) at /usr/src/usr.sbin/jail/command.c:167 #6 0x004068e5 in main (argc=2, argv=0x0) at /usr/src/usr.sbin/jail/jail.c:449
vervoseなんてフラグがチラホラしてたんで、
root@fb:~ # jail -v -c path=/tmp/MINE command=/bin/csh jail_set(JAIL_CREATE) persist path=/tmp/MINE created run command in jail: /bin/csh # exit exit jail_set(JAIL_UPDATE) jid=6 nopersist
凄くマクロな説明だな。
add disk
qemuを入れて、そこでFreeBSDを動作させたい。母艦が手狭なんでOSの新規イ ンストールを兼ねて、母艦を広くするか。なんか面倒そうだな。Diskを増設し ちゃうか。やってみた。そして沢山の子分をつれて、qemuがやってきた。
Disk増設は簡単。VMwareの設定でDiskを追加。IDEとかSCSIとかから選べるけ ど、推奨はIDEとの事なんでそれにした。OSを起動したらdmesg
sakae@fb:~ $ dmesg | grep ada Trying to mount root from ufs:/dev/ada0s1a [rw]... ada0 at ata0 bus 0 scbus0 target 0 lun 0 ada0: <VMware Virtual IDE Hard Drive 00000001> ATA-4 device ada0: Serial Number 00000000000000000001 ada0: 33.300MB/s transfers (UDMA2, PIO 32768bytes) ada0: 12288MB (25165824 512 byte sectors) ada1 at ata0 bus 0 scbus0 target 1 lun 0 ada1: <VMware Virtual IDE Hard Drive 00000001> ATA-4 device ada1: Serial Number 01000000000000000001 ada1: 33.300MB/s transfers (UDMA2, PIO 32768bytes) ada1: 12288MB (25165824 512 byte sectors)
母艦がada0だ。だってmountを試みているからね。するってぇと、増設した奴 は、ada1って事になる。newfs /dev/ada1 してから、/optにマウント。忘れず に/etc/fstabを更新しておこう。
母艦のDiskが本当に手狭になってしまったので、/usr/freebsd-distを、増設 Diskである/optに移動した。
FreeBSD on QEMU
現在のFreeBSDにはXを入れていないので、インストール時に必要となるvga端 末が表示できない。そこで、OpneBSD側で、FreeBSDをインストールして、その DISKを利用する事にした。
インストールがめっぽう遅い。おまけに起動すると、パニックですよ。もう一 度試してみる? 御免こうむるな。別の手を考えよう。
sakae@fb:/opt/MINE $ dd if=/dev/zero of=disk.img bs=1M count=2048 root@fb:/opt/MINE # mdconfig -a -t vnode -f disk.img -u 0 root@fb:/opt/MINE # gpart add -t freebsd -s 2000M -a 4k /dev/md0 root@fb:/opt/MINE # gpart set -a active -i 1 /dev/md0 root@fb:/opt/MINE # gpart bootcode -b /boot/boot0 /dev/md0 root@fb:/opt/MINE # gpart create -s BSD -n 20 /dev/md0s1 root@fb:/opt/MINE # gpart add -t freebsd-ufs -s 1800M /dev/md0s1 root@fb:/opt/MINE # gpart add -t freebsd-swap -s 200M /dev/md0s1 root@fb:/opt/MINE # gpart bootcode -b /boot/boot /dev/md0s1 root@fb:/opt/MINE # newfs /dev/md0s1a
こんな風に土台になるファイルを作成。それを仮想diskに見立てる。。gpart を利用して、スライスを切る。スライスはDOSのパーテションの事だ。
root@fb:/opt/MINE # mount /dev/md0s1a /mnt root@fb:/opt/MINE # cd /mnt/ root@fb:/mnt # tar jxf /opt/freebsd-dist/base.txz root@fb:/mnt # tar jxf /opt/freebsd-dist/kernel.txz
後は、バイナリーを展開。それから、少々強引だけど、cp /etc/{master.passwd,passwd} /mnt/etc して、userを登録。rootユーザーさ え動作すれば、後はbsdinstallで個別の設定は、どうにでもなる、かな? bsdinstallに面白いターゲットを発見(どうでもいい事ですが)。
jail destination Sets up a new chroot system at destination, suitable for use with jail(8). Behavior is generally similar to auto, except that disk partitioning and network setup are skipped and a kernel is not installed into the new system.
jailがすっかり根付いてますなあ。それと富豪な人向けにzfs。これソラリス 由来。暗号化も御茶の子さいさい。暗号化と言えば、KADOKAWAさんの所、攻撃 受けて、勝手に暗号化されちゃったんですかね。
ああ忘れる所だった。最後にumountした後、mdconfig -d -u 0 を実行して、 開放を忘れない事。
vi /mnt/boot/loader.conf
boot_multicols="yes" boot_serial="yes" comconsole_speed="9600" console="comconsole,vidconsole"
を登録。シリアルコンソールから利用できる様に設定。これでVGAな端末と縁 が切れるはず。
qemu-system-i386 -m 256 -nographic -no-fd-bootchk -s \ -net nic -net user,hostfwd=tcp::2022-:22 \ -hda disk.img
起動は、こんな設定だ。
CPU: QEMU Virtual CPU version 2.5+ (2401.24-MHz 686-class CPU) Origin="GenuineIntel" Id=0x663 Family=0x6 Model=0x6 Stepping=3 Features=0x781abfd<FPU,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,PGE,CMOV,PAT,MMX,FXSR,SSE,SSE2> Features2=0x80000001<SSE3,HV> Hypervisor: Origin = "TCGTCGTCGTCG" real memory = 268304384 (255 MB) avail memory = 233918464 (223 MB) : ada0: <QEMU HARDDISK 2.5+> ATA-7 device ada0: Serial Number QM00001 ada0: 16.700MB/s transfers (WDMA2, PIO 8192bytes) ada0: 2048MB (4194304 512 byte sectors) cd0 at ata1 bus 0 scbus1 target 0 lun 0 cd0: <QEMU QEMU DVD-ROM 2.5+> Removable CD-ROM SCSI device cd0: Serial Number QM00003 cd0: 16.700MB/s transfers (WDMA2, ATAPI 12bytes, PIO 65534bytes) cd0: Attempt to query device size failed: NOT READY, Medium not present Loader variables: : Manual root filesystem specification: <fstype>:<device> [options] Mount <device> using filesystem <fstype> and with the specified (optional) option list. eg. ufs:/dev/da0s1a zfs:zroot/ROOT/default cd9660:/dev/cd0 ro (which is equivalent to: mount -t cd9660 -o ro /dev/cd0 /) ? List valid disk boot devices . Yield 1 second (for background tasks) <empty line> Abort manual input
あらら、/etc/fstabを忘れているっぽいぞ。それから、デバイス・ファイルも ね。ああ、デバイス・ファイルは自動生成してくれるからイジルナ。
root@qemu:~ # cat /etc/fstab # Device Mountpoint FStype Options Dump Pass# /dev/ada0s1a / ufs rw 1 1 /dev/ada0s1b none swap sw 0 0
これで、無事に動いた。多少のワーニングは出てくるけど、これだけ動けば、 gdbのターゲットとしては十分でしょう。
sakae@qemu:~ $ df -h Filesystem Size Used Avail Capacity Mounted on /dev/ada0s1a 1.7G 1.0G 570M 64% / devfs 1.0K 0B 1.0K 0% /dev
portsとか余計な物を入れないと、こんなもんだ。そして、下記はtopの冒頭部 分。
last pid: 859; load averages: 0.90, 0.55, 0.40 up 0+00:17:55 07:54:12 12 processes: 1 running, 11 sleeping CPU: 1.1% user, 0.0% nice, 2.2% system, 1.9% interrupt, 94.8% idle Mem: 5036K Active, 1036K Inact, 34M Wired, 17M Buf, 184M Free Swap: 200M Total, 200M Free
256Mもメモリーが有れば余裕ですよ。まあ、余計なプロセスが動いていないか らねぇ。
それから、一応 ssh -p 2022 localhost して、qemu側のFreeBSDに接続できる 事を確認したよ。
Linux in FreeBSD
注目のリナのエミュレーション機能を調べてみる。その前に、デフォのDiskに 余裕が無いので、/usr/ports一式を、増設したDiskに引越しする事にした。 引越しは、0123にお任せじゃなくて、下記の定番な方法で実施。
root@fb:/usr # tar cf - ./ports | (cd /opt; tar xpf -)
跡地を開放してから、リンクを貼ったよ。
sakae@fb:~ $ df -h Filesystem Size Used Avail Capacity Mounted on /dev/ada0s1a 11G 7.1G 2.7G 72% / devfs 1.0K 0B 1.0K 0% /dev tmpfs 384M 3.6M 380M 1% /tmp /dev/ada1 12G 4.0G 6.7G 37% /opt
これで少しはバランスが回復したかな。
第10章 Linux® バイナリ互換機能 リナの様に振る舞う方法が解説されてた。32Bit用には、CentOS 7が、64Bit 用には、Rocky Linux 9が提供されてるそうだ。
sakae@fb:~ $ pkg search linux-c7 linux-c7-7.9.2009_1 Meta-port for all things CentOS 7.9.2009 linux-c7-alsa-lib-1.1.8 Advanced Linux Sound Architecture libraries (Linux CentOS 7.9.2009) : linux-c7-xcb-util-keysyms-0.4.0_1 Port of Xlib's XImage and XShmImage functions (Linux CentOS 7.9.2009) linux-c7-xorg-libs-7.7_11 Xorg libraries (Linux CentOS 7.9.2009) linux-c7-zlib-devel-1.2.7 Zlib headers (Linux CentOS 7.9.2009)
確かに提供されてけど、品揃えがX関係に偏っているぞ。無理して入れても、 持て余しそうなんで、横目で眺めるだけにする。Rockyの方は、どうなんでしょ うかね? ArchLinuxを既にインストールしてるから、入れる事は無いでしょう。
kernel.debug
qemu/FreeBSDの用意が出来たので、母艦のFreeBSDに有るkernel.debugを使っ てみる。準備として、
sakae@fb:/usr/lib/debug/boot/kernel $ cat .gdbinit target remote :1234
を入れ、qemuのdebug支援機構とgdbが通信できる様にしておく。それでは、 qemu/FreeBSDを起動しておく。それから、母艦で
sakae@fb:/usr/lib/debug/boot/kernel $ gdb -q kernel.debug Reading symbols from kernel.debug... warning: remote target does not support file transfer, attempting to access files from local filesystem. warning: Unable to find dynamic linker breakpoint function. GDB will be unable to debug shared library initializers and track explicitly loaded dynamic code. acpi_cpu_c1 () at /usr/src/sys/x86/x86/cpu_machdep.c:245 245 } (gdb) b sys_chroot Breakpoint 1 at 0x10fd9cf: file /usr/src/sys/kern/vfs_syscalls.c, line 976. (gdb) c Continuing.
root@qemu:~sakae # jail -c path=/home/sakae/MINE command=/bin/csh # exit exit
何の反応も有りませんでした。jailでは、chrootが使用されていないと結論付 けてもいいかな。ちょいと悔しいので、同類項で試してみます。
(gdb) b sys_chdir Breakpoint 2 at 0x10fd826: file /usr/src/sys/kern/vfs_syscalls.c, line 933. (gdb) c Continuing. Breakpoint 2, sys_chdir (td=0xccefb40, uap=0xccefdd8) at /usr/src/sys/kern/vfs_syscalls.c:933 933 return (kern_chdir(td, uap->path, UIO_USERSPACE)); (gdb) bt #0 sys_chdir (td=0xccefb40, uap=0xccefdd8) at /usr/src/sys/kern/vfs_syscalls.c:933 #1 0x0143d9bf in syscallenter (td=<optimized out>) at /usr/src/sys/i386/i386/../../kern/subr_syscall.c:188 #2 syscall (frame=0xcb9dce8) at /usr/src/sys/i386/i386/trap.c:1161 #3 0xffc03479 in ?? () #4 0x0000003b in ?? () #5 0x0000003b in ?? () #6 0x2067a020 in ?? () #7 0xffbfeab0 in ?? ()
ここまで調査できれば、後はユーザーランドでgdbを振り回すだけで十分だな。 たまにはOpenBSDに火を入れてみるか。
chroot/chdir
chroot /tmp/MINE を題材にカーネル側を散策する。
ob$ gdb -q bsd.gdb Reading symbols from bsd.gdb... acpicpu_idle () at /usr/src/sys/dev/acpi/acpicpu.c:1207 1207 break; (gdb) b sys_chroot Breakpoint 1 at 0xd02fffea: file /usr/src/sys/kern/vfs_syscalls.c, line 804. (gdb) c Continuing. Breakpoint 1, sys_chroot (p=0xd149d34c, v=0xf1b21134, retval=0xf1b2112c) at /usr/src/sys/kern/vfs_syscalls.c:804 804 } */ *uap = v; (gdb) bt #0 sys_chroot (p=0xd149d34c, v=0xf1b21134, retval=0xf1b2112c) at /usr/src/sys/kern/vfs_syscalls.c:804 #1 0xd068ba01 in mi_syscall (p=0xd149d34c, code=61, indirect=-1, callp=0xd0d0f3bc <sysent+732>, argp=0xf1b21134, retval=0xf1b2112c) at /usr/src/sys/sys/syscall_mi.h:110 #2 0xd068b604 in syscall (frame=0xf1b21170) at /usr/src/sys/arch/i386/i386/trap.c:574 #3 0xd071a135 in Xsyscall_untramp () #4 0xf1b21170 in ?? () #5 0x1be0bcaf in ?? () Backtrace stopped: previous frame inner to this frame (corrupt stack?)
gdbしてると、視野が狭くなるので、ソースを眺めつつ、これはと思う所を集 中攻撃するのが、良いと思える。いわゆる、木を見て森を見ず を避けるのが 賢明だ。
NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, SCARG(uap, path), p); if ((error = change_dir(&nd, p)) != 0) return (error); if (fdp->fd_rdir != NULL) { /* * A chroot() done inside a changed root environment does * an automatic chdir to avoid the out-of-tree experience. */
例えば、こんな下りがある。NDINITってマクロだろうと想像がつく。展開して、
どうなってるか見ておきたい。だって、コードの流れとして、pathを検索して、
その結果が、ndの中に格納され、それを使って、 change_dir
してると想像
できるから。
こういう時は、TAGSを利用して追跡するに限る。namei.h
#define NDINIT(ndp, op, flags, segflp, namep, p) \ ndinitat(ndp, op, flags, segflp, AT_FDCWD, namep, p)
この関数は検索用の構造体をイニシャライズしてた。本物は
/* * Common routine for chroot and chdir. */ static int change_dir(struct nameidata *ndp, struct proc *p) : if ((error = namei(ndp)) != 0) return (error); vp = ndp->ni_vp;
どうやらnameiが肝みたい。それから、fdpって変数も現実を反映するのに大事。
これも、 sys_chroot
の冒頭付近で宣言されてる。
struct filedesc { struct file **fd_ofiles; /* [f/w,m] file structures for * open files */ char *fd_ofileflags; /* [f] per-process open file flags */ struct vnode *fd_cdir; /* [K] current directory */ struct vnode *fd_rdir; /* [K] root directory */ :
プロセス毎に、chdir,rootdirを保持してるのね。vnodeってのも複雑な構造体 になってるぞ。もう完全にバイナリーな世界なんで、デコードするには、TAGS を十分に駆使して、あちことを飛び回らないといけない。正直難儀な事です。
GPT-4o
言葉は世界を拡張するーミニ読書感想『言語の力』(ビオリカ・マリアンさん)
KADOKAWAさんの所が、復旧してなかったので、読書感想のノートを参照させて いただきます。
GPTが発達した現代。苦労して英語なんか学ぶ必要が有るんか? そんな疑問に、 バイリンガル、マルチリンガルな人の効用が解説されてます。
マルチな人は、収入も多いそうだ。言語って言ったら、C語とかも、そうだか らね。だったら、オイラーは自信を持ってマルチリンガルだな。
普通の人が毛嫌いする、括弧言語なんて、大好物だもの。