chroot

Table of Contents

chroot

前回の最後に、MINE関連で、chrootなんてのが出てきたので、やってみる。

root@fb:~ # chroot -u sakae /home/sakae/MINE /bin/sh
chroot: /bin/sh: No such file or directory

chrootは、change root directory の略で、指定したdirをroot(根)にして下 さいって指令。管理者だけが実行できる。うえの例では、ついでにユーザーを sakaeにして、shellを起動してって依頼してる。

んが、エラーだ。何故だ? ソース嫁。これがOSSの醍醐味。 /usr/src/usr.sbin/chroot/chroot.c

if (chdir(argv[0]) == -1 || chroot(".") == -1)
        err(1, "%s", argv[0]);
if (user && setuid(uid) == -1)
        err(1, "setuid");
if (argv[1]) {
        execvp(argv[1], &argv[1]);
        err(1, "%s", argv[1]);
}

最初にchdirしちゃうんだな。それから、指定したユーザーに変身し、最後に /bin/shを起動と言う流れ。でも、移動先には、shellが不在だったんでエラー。

sakae@fb:~ $ mkdir MINE/bin
sakae@fb:~ $ cp /bin/sh MINE/bin/

ならば、空っぽを解消してあげよう。

root@fb:~ # chroot -u sakae /home/sakae/MINE /bin/sh
ELF interpreter /libexec/ld-elf.so.1 not found, error 2
Abort

Linux似のFreeBSDは、こうなるから困るんだよなあ。色々関連品を揃えてあげ ないと、動かない。

まあ、刑務所の中は、色々と不自由ですから。ホリエモンの刑務所なう、とか サンピンで刑務所わず になるとかの著書を読むと、中々面白いぞ。まだの人 は、塀の中に入った時に慌てないように、事前学習をお勧めします。

ああ、サンピンってのは、刑期が 1/3 ぐらいになると、仮釈放の可能性が出 てくる事を言うらしいです。態度が悪かったりすると、この特典が無いそうです。

OpenBSDだと

ob$ doas chroot -u sakae /home/sakae/MINE /bin/sh
/bin/sh: No controlling tty (open /dev/tty: No such file or directory)
/bin/sh: warning: won't have full job control
ob$ pwd
/
ob$ ls
/bin/sh: ls: not found
ob$ echo * bin/*
bin bin/sh

文句を言われつつも、shが動作した。FreeBSDとは決定的に違うな。この違い は、shがダイナミックリンクにはってるか、スタチィクリンクかによる。安全 設計が一番大事と考えるOpenBSDは、重要なコマンドをスタチィクリンクにし てるんだ。

もし、FreeBSDで、libc.soとかld-elf.so.1等が破損してしまうと、shさえも 起動できない大惨事になってしまう。いわば、弁慶の泣き所、アキレス腱、蜂 の一突き、を承知の上で使う事になる。その場合は、レスキューCDをお忘れな く。

このchrootだけど、どんな所で利用されてるの? ざっと見、sshdとかhttpdと かの砂場として利用されてるみたい。いわゆる、中で騒ぎが起きても、それが 外側に影響しないようにって使い方だ。

tcpdump/privsep.c

if (!nochroot) {
        if (chroot(pw->pw_dir) == -1)
                err(1, "unable to chroot");
        if (chdir("/") == -1)
                err(1, "unable to chdir");
}

/* drop to _tcpdump */
if (setgroups(1, &pw->pw_gid) == -1)
        err(1, "setgroups() failed");
if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) == -1)
        err(1, "setresgid() failed");
if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) == -1)
        err(1, "setresuid() failed");

こんな風に、特権の一部を剥奪して、安全側に振っている。

Linuxのchroot

リナ方面はどうよ? 一応ArchLinuxで確かめてみる。

[root@arch sakae]# chroot --userspec=sakae /home/sakae/MINE
chroot: invalid user
[root@arch sakae]# chroot --userspec=1000 /home/sakae/MINE
chroot: failed to run command ‘/bin/bash’: No such file or directory

ユーザー名は名前で良いはずなんだけどな。ソース嫁は省略して数値指定しま す。で、デフォだとbashを要求するんか。

[root@arch sakae]# chroot --userspec=1000 /home/sakae/MINE
chroot: failed to run command ‘/bin/bash’: No such file or directory
[root@arch sakae]# echo $?
127

/bin/bashをコピーしただけだと、エラー。ちゃんとエラー・ステータスも同 様な事を言ってる。

[sakae@arch ~]$ ldd /bin/bash
        linux-vdso.so.1 (0x000072dc9b4fa000)
        libreadline.so.8 => /usr/lib/libreadline.so.8 (0x000072dc9b375000)
        libc.so.6 => /usr/lib/libc.so.6 (0x000072dc9b189000)
        libncursesw.so.6 => /usr/lib/libncursesw.so.6 (0x000072dc9b11a000)
        /lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x000072dc9b4fc000)

しょうがないので、/bin/bashが要求するものを確認して、必要なライブラリィー 類を配置した。

[sakae@arch ~]$ tree MINE/
MINE/
├── bin
│   └── bash
└── usr
    ├── lib
    │   ├── libc.so.6
    │   ├── libncursesw.so.6
    │   └── libreadline.so.8
    └── lib64
        └── ld-linux-x86-64.so.2

でもエラーですよ。しょうがないので、

[root@arch sakae]# strace chroot  /home/sakae/MINE
 :
chroot("/home/sakae/MINE")              = 0
chdir("/")                              = 0
execve("/bin/bash", ["/bin/bash", "-i"], 0x7ffd4a1e40c0 /* 16 vars */) = -1 ENOENT (No such file or directory)

大好きなgdbの代わりにstraceしてみた。やはり/bin/bashが無いとな。 これ以上はgdbを使わないと無理か。 ググったら、 chroot 使い方 こういう人も居たんだけどね。

chrootで学ぶ環境構築時のポイント

Linux kernel オイラーも泣かされました。手を出さない方が無難と思うぞ。 ならば、FreeBSDかな。こいつでリナを使った気になりましょう。

FreeBSDでchroot

既に答が出ちゃってる感が有るけど、/tmp/MINEを頂点にして、chrootしてみ る。

root@fb:/tmp # chroot /tmp/MINE
chroot: /bin/csh: No such file or directory

FreeBSDのデフォのshはcshです。

sakae@fb:/tmp $ mkdir MINE/bin MINE/lib
sakae@fb:/tmp $ cp /bin/csh MINE/bin/
sakae@fb:/tmp $ ldd MINE/bin/csh
MINE/bin/csh:
        libncursesw.so.9 => /lib/libncursesw.so.9 (0x20040000)
        libcrypt.so.5 => /lib/libcrypt.so.5 (0x200a8000)
        libc.so.7 => /lib/libc.so.7 (0x200ca000)
sakae@fb:/tmp $ cp /lib/libncursesw.so.9 /lib/libcrypt.so.5 /lib/libc.so.7 MINE/lib

目につく物をコピーしたよ。

root@fb:/tmp # chroot /tmp/MINE
ELF interpreter /libexec/ld-elf.so.1 not found, error 2
Abort

隠れインタープリタが必要なのか。

sakae@fb:/tmp $ mkdir MINE/libexec
sakae@fb:/tmp $ cp /libexec/ld-elf.so.1 MINE/libexec/

dirを追加で掘って、インタープリタを埋め込む。

root@fb:/tmp # chroot /tmp/MINE
csh: The terminal database could not be opened.
csh: using dumb terminal settings.
# echo *
bin lib libexec
# exit
exit
root@fb:/tmp #

端末のデータベースがオープン出来ないので、馬鹿端末とかですって。一応 echoを使って簡易的なlsを実行。

端末DBって何? man csh したら出てくるかと思ったら、そういう超基本なの は説明がなかった。しょうがないので、ソース嫁。

sakae@fb:/usr/src/contrib/tcsh $ grep 'terminal database' *.c
ed.screen.c:            "%s: The terminal database could not be opened.\n"), progname);

この次あたりの行に、dumb端末を使うよとのメッセージも有り楽勝で、DBファ イルまで辿りつけるかと思ったら、甘かった。ここは、定石通り、 ktrace/kdumpするしか無いだろう。

sakae@fb:/tmp $ ktrace csh
sakae@fb:/tmp % kdump >LOG
sakae@fb:/tmp % grep NAMI LOG
   :
  9951 csh      NAMI  "/home/sakae/.tcshrc"
  9951 csh      NAMI  "/home/sakae/.cshrc"
  9951 csh      NAMI  "/home/sakae/.history"
  9951 csh      NAMI  "/home/sakae/.termcap.db"
  9951 csh      NAMI  "/home/sakae/.termcap"
  9951 csh      NAMI  "/usr/share/misc/termcap.db"

NAMIはファイル名から、ファイルの情報を引き出す手続だ(openまでやってく れるっぽい)。これを見ると、ファイルの要求度合いが一目瞭然だ。

sakae@fb:/tmp $ tree MINE/
MINE/
├── bin
│   └── csh
├── lib
│   ├── libc.so.7
│   ├── libcrypt.so.5
│   └── libncursesw.so.9
├── libexec
│   └── ld-elf.so.1
└── usr
    └── share
        └── misc
            └── termcap.db

結局、こういう配置で、ちゃんとcshが起動した。凝った事をやろうとすると、 また別の怒りを買うかも知れないけれど。

termcap

termcapってのは、何処で定義されてる? 予想では、libncurseあたりかな。 だって、/usr/share/miscなんてのが出てるんだから、これはもうシステム・ ワイドな場所ですよ。そこから演繹すれば、専門のライブラリィーに行き付く。 /usr/src/lib/ncurses/ncurses/pathnames.h

#define _PATH_DEF       ".termcap /usr/share/misc/termcap /etc/termcap.small"
#define _PATH_DEF_SEC   "/usr/share/misc/termcap"

このパスを利用してる関数を洗い出して、そこに飛んでくるか確認。

(gdb) bt
#0  _nc_read_termcap_entry (name=0x2049a270 "tmux", tp=0x2076d14c)
    at /usr/src/lib/ncurses/ncurses/termcap.c:115
#1  0x204ec8e1 in _nc_read_entry2 (name=0x2049a270 "tmux",
    filename=0xffbfd914 "tmux", tp=0x2076d14c)
    at /usr/src/contrib/ncurses/ncurses/tinfo/read_entry.c:874
#2  0x204e4a63 in _nc_setup_tinfo (tn=0x2049a270 "tmux", tp=0x2076d14c)
    at /usr/src/contrib/ncurses/ncurses/tinfo/lib_setup.c:488
#3  _nc_setupterm (tname=<optimized out>, Filedes=2, errret=0xffbfdd50,
    reuse=1) at /usr/src/contrib/ncurses/ncurses/tinfo/lib_setup.c:759
#4  0x204e5048 in tgetent_sp (sp=0x0, bufp=0x483024 <GetTermCaps.bp> "",
    name=0x20733045 "tmux")
    at /usr/src/contrib/ncurses/ncurses/tinfo/lib_termcap.c:110
#5  0x204e5623 in tgetent (bufp=0x483024 <GetTermCaps.bp> "",
    name=0x20733045 "tmux")
    at /usr/src/contrib/ncurses/ncurses/tinfo/lib_termcap.c:227
#6  0x0044e95c in GetTermCaps () at /usr/src/contrib/tcsh/ed.screen.c:1432
#7  0x004480e4 in ed_Init () at /usr/src/contrib/tcsh/ed.init.c:317
#8  0x00415666 in main (argc=<optimized out>, argv=0xffbfebd4)
    at /usr/src/contrib/tcsh/sh.c:1378

これで道筋は判明した。トレースを良く眺めると、ちゃんとライブラリィーの 中まで分け入っている。リナでここまでやろうとすると、とんでもない苦労を 強いられるんだろうね。

で、今回の立役者である、ktrace/kdumpが、どう実装されてるか、軽く探って みたい。もはや手当たりの趣だ。

ktrace/kdump

これ、リナで言うstraceね。ログを採取するktraceと、取得したログをデコー ドして表示してくれるkdumpと言うように、セットになっている。

今回は、上で大活躍したMAMIがどうなっているかを中心に調べてみる。ならば、 kdumpを先にみれ。

/usr/src/usr.bin/kdump/kdump.c

dumpheader(struct ktr_header *kth, u_int sv_flags)
         :
        switch (kth->ktr_type) {
        case KTR_SYSCALL:
                type = "CALL";
                break;
        case KTR_SYSRET:
                type = "RET ";
                break;
        case KTR_NAMEI:
                type = "NAMI";
                break;

こんな表題を文字列にするルーチンが有って、後は、それらを使って表示して るだけだ。 尚、ここには、linux.cなんていう思わせぶりなファイルが置いてあった。多 分リナをエミュレーションモードで使ってる場合の対応でしょう。FreeBSDに は、半分リナの血が混っています。と言ったら恐い人からマサカリが飛んでき そうであります。まあ、あの、リナ中心主義な技評に FreeBSD 14.1がリリース こんな記事が出るぐらいですから、当たらずとも遠 からずと思うのであります。

/usr/src/usr.bin/ktrace/ktrace.c

if (argc > 0) {
        if (ktrace(tracefile, ops, trpoints, getpid()) < 0)
                err(1, "%s", tracefile);
        execvp(*argv, argv);
        err(1, "exec of '%s' failed", *argv);
}

ホー、主役はktraceと言うシステムコール。どんな情報が欲しいかも指定 できるとな。ktrace(2)

The trpoints argument specifies the trace points of interest.  The
defined trace points are:

      KTRFAC_SYSCALL        Trace system calls.
      KTRFAC_SYSRET         Trace return values from system calls.
      KTRFAC_NAMEI          Trace name lookup operations.
      :

舞台は反転して、御代の国、違った、カーネル側になります。

sakae@fb:/sys/kern $ grep NAMEI -l *.c
kern_ktrace.c
uipc_shm.c
vfs_cache.c
vfs_lookup.c

vfs_lookup.c なんていう、いかにもなファイルを点検。

#ifdef KTRACE
        if (KTRPOINT(td, KTR_NAMEI)) {
                ktrnamei(cnp->cn_pnbuf);
        }
#endif

こんなんで、情報を記憶してるんでしょう。ここから先は、OpenBSDにお任せ かな。だって、FreeBSD用のカーネル観光環境が。用意されてないからね。

kernel.debug

ちょっと実稼動させてるFreeBSD 13.3で、kernel.debugの状況を視察しておく。

sakae@fb:/usr/lib/debug/boot/kernel $ ls -l kern*
-r--r--r--  1 root  wheel     22844 Mar  2 12:29 kern_testfrwk.ko.debug
-r--r--r--  1 root  wheel  71122496 Mar  2 11:34 kernel.debug

debug用にカーネルとそのモジュール軍が用意されてるんだな。

sakae@fb:/usr/lib/debug/boot/kernel $ gdb -q kernel.debug
Reading symbols from kernel.debug...
(gdb) b sys_chroot
Breakpoint 1 at 0x10fd9cf: file /usr/src/sys/kern/vfs_syscalls.c, line 976.

うん、ちゃんとdebug用のインフォメーションも内蔵されてた。折角システム コールの場所を提示してきたんで、人間debuggerを起動してみるか。

sakae@fb:/usr/lib/debug/boot/kernel $ emacs +976 /sys/kern/vfs_syscalls.c
int
sys_chroot(struct thread *td, struct chroot_args *uap)
{
        struct nameidata nd;
        struct proc *p;
        int error;

=>      error = priv_check(td, PRIV_VFS_CHROOT);
        if (error != 0) {
                p = td->td_proc;
                PROC_LOCK(p);
                if (unprivileged_chroot == 0 ||
                    (p->p_flag2 & P2_NO_NEW_PRIVS) == 0) {
                        PROC_UNLOCK(p);
                        return (error);
                }
                PROC_UNLOCK(p);
        }

脳内chroot /sys/kern/ してみたよ。gdbがポイントした場所は、カーソル が有る所(=>)だったよ。最初の実行文に対応するのね。

それからカーネル内では、proc == thread って風に扱かわれているのね。ま あ、ともかくkernel.debugが使える事が判明した。

ならば、13.3を14.1に上げて、qemuでgdb観光できる様にしようかな。そうす ると、それ様に4Gぐらいは追加で必要だな。

sakae@fb:~ $ df -h
Filesystem      Size    Used   Avail Capacity  Mounted on
/dev/ada0s1a     11G    8.2G    1.6G    84%    /

今のDISK容量12Gでは手狭になる事請け合いなんで、広い場所を確保して、そ こに移住だな。そのうちやってみよう。

ああ、検討事項がもう一つ有った。リナのエミュレーション機能を入れるかど うかだ。 /usr/ports/emulators を参照すると

linux_base-c7:
Makefile                pkg-descr               pkg-plist.amd64
distinfo                pkg-plist.aarch64       pkg-plist.i386

linux_base-rl9:
Makefile                distinfo                pkg-plist.aarch64
Makefile.version        pkg-descr               pkg-plist.amd64

CentOS7かRocky Linux 9だな。

This port contains packages from a near-minimal installation of CentOS 7
Linux.  These packages, in conjunction with the Linux kernel module,
form the basis of the Linux compatibility environment. It is designed to
provide a nice user experience by using the FreeBSD configuration for
corresponding Linux stuff where possible. Because of this any work which
needs to chroot into the Linux base may not work as expected (no fallthrough
to the FreeBSD config possible).

ここにも、chrootが顔を出しているな。これがchrootの威力を発揮する場面で すよ。そして、更には、、、

jail

豪華な刑務所です。現実には、刑務所(ジェイル)と拘置所(プリズン)が有る訳 です。アプルの監獄(iPadとか)の縛りから自由になりたい一心で、ジェイル ブレーク(脱獄)が過去には行なわれた事があります。その関係で、心ある人は、ジェ イルブレークにあこがれたでしょう。今は、穴が塞がれて、脱獄はほとんど不 可能らしいです。

オイラーも初めてipadを手にした時、自由にアプリを設置できなかったり、デー タの保管に検閲が有ったりで、その面で、非常にガッガリした記憶が有ります よ。

jail 仮想 OS 技術による管理者教育環境の構築

jailによるセキュアサーバー環境

正直、使う事は無いだろうけど、ソースが有るなら覗き見したい。chrootは使 われているか? jail(8)したら設定ファイルの説明が出てたので、きっとパー サーの助けを借りているだろう。

sakae@fb:/usr/src/usr.sbin/jail $ ls
Makefile                jail.8                  jailp.h
Makefile.depend         jail.c                  jailparse.y
command.c               jail.conf.5             state.c
config.c                jaillex.l               tests/

一目で、パーサー使ってた。次は、chroot

sakae@fb:/usr/src/usr.sbin/jail $ grep chroot *.[ch]
command.c:              /* jail_attach won't chdir along with its chroot. */

コメントには思わせぶりな文言が有るけど。。ならばライブラリィーの中に埋 没してないか?

sakae@fb:/usr/src/usr.sbin/jail $ ldd /usr/sbin/jail
/usr/sbin/jail:
        libjail.so.1 => /lib/libjail.so.1 (0x20040000)
        libkvm.so.7 => /lib/libkvm.so.7 (0x20048000)
        libutil.so.9 => /lib/libutil.so.9 (0x2005c000)
        libc.so.7 => /lib/libc.so.7 (0x20073000)
        libelf.so.2 => /lib/libelf.so.2 (0x20241000)

libjailが怪しそうってんで、期待を込めて調べてみたが外れくじだった。期待を込めて、単勝馬券を買って、それが紙屑になった悲惨な場面だな。

次なる手は、jail族を列挙して、関連を探すか。

sakae@fb:/usr/src/usr.sbin/jail $ man -k jail
 :
jail(8) - manage system jails
jexec(8) - execute a command inside an existing jail
jls(8) - list jails

jexecに望みを繋いだが、期待した走りは得られず。これはもう、ちゃんとし た刑務所を構築して、内部オペレーションを監査するしかないか。

複数バージョンのFreeBSDをJailで共有させる方法

こちらを読んでも、ちと実験は大変そう。そのうちにトライだな。

ChatGPT

最近、XXXのアンソロジィーと言う小説分野に凝っている。アンソロジィーと 言うのは、笑点でやってる大喜利の事だ。何かお題を出して、それをテーマに (短編)小説を発表する事。回答者は、大体7人ぐらい。お題の例として、和菓 子とかペットとかスカートとか洋々。思わぬ視点での発表が有ったりして、飽 きない。

そんなアンソロジィーのひとつとして、元気象庁の方が発表されたものがあっ た。明確にアンソロジィーと銘打っていなくても、十津川警部と七枚の切符み たいに、七が付いた題名の本は、アンソロジィー形式の本である可能性が高い。

以下は、この本に収録されていた短編。偉大なる旅を扱った小説家の西村京太 郎氏に捧げられた、追悼のアンソロジィーだ。 鉄壁のアリバイが有り、犯人が逮捕できない。これを打破したのは、気象 庁から地方の災害対策課に出向してた主人公。

彼女は、山頂で殺人を犯した犯人が、短時間のうちに下山してアリバイを捏造 したのをみ破ります。山頂からカイトに身を託して、鳥のように下山したんだ ろうと。ならば、たまたま近くに設置されてた、 ウィンドプロファイラ が、この事実を捉えているんではなかろうか。

初めて知りましたよ。プロファイラーの原理を。1.3Gの電波を使っているそう です。電波レンズ搭載型対流圏ウィンドプロファイラ レーダー(W P R L Q - 7 )の開発

こういう技術の延長上に眼底の断層表示が有るんではなかろうか? とっかか りを聞いてみる。

Q: 眼科の診断装置について尋ねます。眼底3次元解析と請求書にあったのですが、網膜の断層写真がでてました。撮影時に強烈なフラッシュが炊かれてました。これで断層が再現できる原理を詳しく説明してください。

A: 眼底3次元解析(OCT: Optical Coherence Tomography、光干渉断層計)は、網膜の高解像度の断層画像を取得するための技術です。この技術により、網膜の内部構造を詳細に観察することができます。OCTの動作原理について説明します。

### OCTの基本原理

  1. 干渉計の使用: OCTは光干渉計を使用して組織の内部構造を画像化します。これは、光の干渉現象を利用して物質の内部を非侵襲的に観察する技術です。
  2. 低コヒーレンス干渉: OCTでは、低コヒーレンス光源(通常は超短パルスレーザーや超輝度LED)が使われます。この光源は、非常に短い時間(高い時間分解能)でコヒーレントな光を発生させます。
  3. 光の分割と反射: 光源からの光はビームスプリッターによって二つに分割されます。一方は参照アームへ、もう一方はサンプルアーム(眼底)へ向かいます。眼底から反射された光と参照アームの光が再度ビームスプリッターで合流します。
  4. 干渉パターンの検出: 合流した二つの光は干渉パターンを形成します。この干渉パターンは、光が眼底内部の異なる深さから反射されたタイミングに基づいて変化します。干渉パターンを検出することで、光が反射された深さ情報を得ることができます。
  5. 断層画像の再構築: 得られた干渉データを解析することで、網膜の断層画像が再構築されます。この過程では、光の反射強度と深さ情報が用いられ、網膜の各層の詳細な構造が高解像度で表示されます。

### 強烈なフラッシュの役割

撮影時の強烈なフラッシュについてですが、OCTの光源は非常に短時間に強い光を発することで、高い時間分解能を持つ画像を取得します。この光は網膜に反射し、その反射光を利用して断層画像が再構築されます。

強いフラッシュを使用する理由は以下の通りです:

  1. 高解像度画像の取得: 短い時間で強い光を使用することで、高解像度かつ精細な画像を取得することが可能です。
  2. 動きの影響の最小化: 短時間での撮影により、眼球の動きや瞬きなどによる影響を最小限に抑えます。
  3. 高いシグナル対ノイズ比: 強い光は反射信号を増強し、ノイズに対する信号の比率(シグナル対ノイズ比)を向上させ、よりクリアな画像を得ることができます。

このようにして、OCTは網膜の詳細な断層画像を提供し、診断や治療計画の立案に役立ちます。

OCT (光干渉断層撮影)

OCTとは

光干渉断層計

眼底用光干渉断層計の進歩


This year's Index

Home