バイナリラッパ以外のラッパ

某MLにて話題にしたので、まとめ。


LIDSなどでBusyBoxを使う際に、シンボリックリンクやハードリンクでは、アプレットごとにアクセス制御を設定することができません。BusyBoxの概要やバイナリラッパでの解決法など、詳しくは次を参照してください。


BusyBoxでは、/bin/busyboxにリンクを張って使うことが多いですが、Usageにもあるように

busybox [function] [arguments]...

という使いかたもできます。たとえば、

busybox ls

とやれば、lsとして動くわけです。


で、あるときなんとなくexecveのmanページを見ていたら、

 書式
        #include 
 
        int execve(const char *filename, char *const argv,
                   char *const envp);
 
 説明
        execve() は、filename によって指定されたプログラムを実
        行する。 filename は、バイナリ実行形式か 、"#!  inter-
        preter [arg]" という形式の行で始まるスクリプトでなけれ
        ばならない。後者の場合、interpreter は適切な実行ファイ
        ルのパス名でなければならず、それ自身がスクリプトであっ
        てはならない。そしてそれは interpreter [arg]  filename
        の形で呼び出される。

と書かれていました。それだったら

#!/bin/busybox

と一行書いたファイルを実行形式にして、例えば/bin/lsとしてセーブしておけば、lsを実行したときに

/bin/busybox ls

と動作してくれるのではないかなぁ、などと思って、/bin/busyboxと"#!/bin/busybox"と書いた/bin/lsを配置し実行してみましたが、

 # ls
 busybox: applet not found
 # 

そんなに単純ではありません。


これは、filenameにはスクリプトのフルパス名が入るため、

/bin/busybox /bin/ls

と実行されてしまうためです。ということで、BusyBoxの方で、フルパス名に対応できるよう修正し、実行してみます。

 # cat /bin/ls
 #!/bin/busybox
 # ls -l /bin/l*
 -rwxr-xr-x    1 root     root        18128 Jan 11 00:06 /bin/link
 -rwxr-xr-x    1 root     root        29840 Jan 11 00:06 /bin/ln
 -rwxr-xr-x    1 root     root        79412 Sep 29 20:27 /bin/loadkeys
 -rwxr-xr-x    1 root     root        25756 Feb  9 21:43 /bin/login
 -rwxr-xr-x    1 root     root           15 Feb 21 04:47 /bin/ls
 -rwxr-xr-x    1 root     root        93560 Jan 11 00:06 /bin/ls.orig
 # 


バイナリラッパでは、アーキテクチャごとにアセンブラコードを書く必要がありましたが、このいわゆる「スクリプトラッパ」では、その必要がなく、また15バイトで済みます。


ただし、問題として例えば

# cat

と実行したときに、psコマンドでプロセスを見ると

/bin/busybox /bin/cat

と表示され、見にくいです。

あとLIDSではACL_DISCOVERYモードでアクセス違反のログを取得しようとした場合、全てbusyboxの違反となってしまうので、ポリシーを構築するのに、ログを参考にすることができなくなってしまいます。
(ということで、LIDSではこのスクリプトラッパは使いませんでした。LIDSのログ出力方法に手を加える必要があるでしょう)

別の案

ちなみに、#!/bin/busyboxじゃなくても、例えばcatの場合、

#!/bin/sh
/bin/busybox cat $*

としたら、BusyBoxにパッチを当てる必要ないよねぇ、という案もありましたが、


/bin/shはどうするの?


ということになりました。/bin/shBusyBox使いたいですし。
#!/bin/busyboxの方は、スクリプトをコピーするだけでインストールも簡単だし、呼出コストも少なそうだし。

スクリプトラッパ対応パッチ

パッチは以下の通り。BusyBoxのバージョン1.4.1用です。

 diff -Naru busybox-1.4.1/applets/busybox.c busybox-1.4.1.script/applets/busybox.c
 --- busybox-1.4.1/applets/busybox.c	2007-01-25 06:34:50.000000000 +0900
 +++ busybox-1.4.1.script/applets/busybox.c	2007-02-20 10:09:58.000000000 +0900
 @@ -104,7 +104,7 @@
  
  	if (argc == 1 || !strcmp(argv[1], "--help") ) {
  		if (argc > 2) {
 -			applet_name = argv[2];
 +			applet_name = bb_get_last_path_component(argv[2]);
  			run_applet_by_name(applet_name, 2, argv);
  		} else {
  			const struct BB_applet *a;
 @@ -140,7 +140,7 @@
  			puts("\n");
  			return 0;
  		}
 -	} else run_applet_by_name(argv[1], argc - 1, argv + 1);
 +	} else run_applet_by_name(bb_get_last_path_component(argv[1]), argc - 1, argv + 1);
  
  	bb_error_msg_and_die("applet not found");
  }

インストーラ込みのパッチは、気分が向いたらそのうち作りますね〜。


追記:スクリプトラッパでは、シェルスクリプトでうまく動かない場面があります。