スクリプトファイルの起動(補足)
Rev.1を表示中。最新版はこちら。
スクリプトファイルの起動で、シェルスクリプトはカーネルが起動する。としていましたが、さらに調べてみると、シェルスクリプトはシェル自身が起動しているようです。fedora16ですが、lsmodすると、それらしいモジュールがinsされていません。search_binary_handlerにて動的にinsしているのかな?[root@localhost kitamura]# lsmod | grep binfmt binfmt_misc 17207 1search_binary_handle()は、formatsをヘッドとするリスト登録されているstruct linux_binfmtをチェックし、なければ、対応するフォーマットのモジュールをinsする事で、再度リストを捜査していました。
CONFIG_MODULESの時(でないとlkmが利用できない。)、動的にモジュールをinsします。1回目の走査の結果が、ENOEXEC(該当するフォーマットが無い)時、request_moduleマクロで動的にモジュールをinsします。
ただし、先頭の4バイトがタブ/改行およびANKでない。事が条件です。従ってスクリプトファイルのようなテキストファイルでは、insされないと言う事です。
なお、insされるモジュール名は、2バイト目からの2バイトの16進数を、binfmt-に追加したものになります。
int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) { unsigned int depth = bprm->recursion_depth; int try,retval; struct linux_binfmt *fmt; pid_t old_pid; retval = security_bprm_check(bprm); if (retval) return retval; retval = audit_bprm(bprm); if (retval) return retval; rcu_read_lock(); old_pid = task_pid_nr_ns(current, task_active_pid_ns(current->parent)); rcu_read_unlock(); retval = -ENOENT; for (try=0; try<2; try++) { read_lock(&binfmt_lock); list_for_each_entry(fmt, &formats, lh) { int (*fn)(struct linux_binprm *, struct pt_regs *) = fmt->load_binary; if (!fn) continue; if (!try_module_get(fmt->module)) continue; read_unlock(&binfmt_lock); retval = fn(bprm, regs); bprm->recursion_depth = depth; if (retval >= 0) { if (depth == 0) { UTRACE_HOOK(current, EXEC, report_exec(fmt, bprm, regs)); ptrace_event(PTRACE_EVENT_EXEC, old_pid); } put_binfmt(fmt); allow_write_access(bprm->file); if (bprm->file) fput(bprm->file); bprm->file = NULL; current->did_exec = 1; proc_exec_connector(current); return retval; } read_lock(&binfmt_lock); put_binfmt(fmt); if (retval != -ENOEXEC || bprm->mm == NULL) break; if (!bprm->file) { read_unlock(&binfmt_lock); return retval; } } read_unlock(&binfmt_lock); #ifdef CONFIG_MODULES if (retval != -ENOEXEC || bprm->mm == NULL) { break; } else { #define printable(c) (((c)=='\t') || ((c)=='\n') || (0x20<=(c) && (c)<=0x7e)) if (printable(bprm->buf[0]) && printable(bprm->buf[1]) && printable(bprm->buf[2]) && printable(bprm->buf[3])) break; /* -ENOEXEC */ if (try) break; /* -ENOEXEC */ request_module("binfmt-%04x", *(unsigned short *)(&bprm->buf[2])); } #else break; #endif } return retval; }
補足
request_moduleマクロは、call_usermodehelper_fns()をコールする事で、"/sbin/modprobeコマンドをカーネル下で実行しています。シェルスクリプトは、先頭の#!行を削除しても、動作してくれるようです。