スクリプトファイルの起動(補足)
スクリプトファイルの起動で、シェルスクリプトはカーネルが起動する。としていましたが、さらに調べてみると、シェルスクリプトはシェル自身が起動しているようです。fedora16ですが、lsmodすると、それらしいモジュールがinsされていません。search_binary_handlerにて動的にinsしているのかな?
CONFIG_MODULESの時(でないとlkmが利用できない。)、動的にモジュールをinsします。1回目の走査の結果が、ENOEXEC(該当するフォーマットが無い)時、request_moduleマクロで動的にモジュールをinsします。
ただし、先頭の4バイトがタブ/改行およびANKでない。事が条件です。従ってスクリプトファイルのようなテキストファイルでは、insされないと言う事です。
なお、insされるモジュール名は、2バイト目からの2バイトの16進数を、binfmt-に追加したものになります。
シェルスクリプトは、先頭の#!行を削除しても、動作してくれるようです。カーネルが起動するなら、このような事はできません。
[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をカーネル下で実行しています。シェルスクリプトは、先頭の#!行を削除しても、動作してくれるようです。カーネルが起動するなら、このような事はできません。





