EN JA
EXECVE(2)
EXECVE(2) FreeBSD System Calls Manual EXECVE(2)

名称

execve, fexecveファイルを実行する

ライブラリ

Standard C Library (libc, -lc)

書式

#include < unistd.h>

int
execve( const char *path, char *const argv[], char *const envp[]);

int
fexecve( int fd, char *const argv[], char *const envp[]);

解説

execve() システムコールは、呼び出しプロセスを新しいプロセスに変換します。新しいプロセスは new process file と呼ばれる通常のファイルに基づいて構成されます。このファイルの名前は path によって指定されます。 fexecve() システムコールは、実行されるファイルが、 path の代わりにファイル記述子 fd によって決定されることを除いて、 execve() と同等です。このファイルは実行可能オブジェクトファイル、またはインタプリタ用のデータのファイルです。実行可能オブジェクトファイルは、識別ヘッダにデータのページが続いたもので構成されます。このデータは、初期プログラム (テキスト) と初期値ありデータのページを表します。追加のページはヘッダの指定によって 0 データで初期化される場合があります。 elf(5) および a.out(5) を参照してください。

インタプリタファイルは次の形式の行で開始します。

#! interpreter [ arg]

インタプリタファイルが execve されるとき、システムは実際には指定の interpreterexecve します。オプションの arg が指定されている場合、それは interpreter の 1番目の引数になり、元々の execve で指定されたファイルの名前は 2 番目の引数になります。それ以外では execve で指定されたファイルの名前が 1番目の引数になります。元々の引数はシフトされて後続の引数になります。 0 番目の引数は指定された interpreter に設定されます。

引数 argv は、ヌル文字で終わる文字ポインタの配列を指すポインタです。各文字ポインタはヌル文字で終わる文字列を指します。これらの文字列は、新しいプロセスから参照できる引数リストを構成します。少なくとも 1 つの引数が配列内に存在している必要があります。慣習では、最初の要素が実行されたプログラムの名前になるはずです (たとえば、 path の最後の構成要素)。

引数 envp も、ヌル文字で終わる文字ポインタの配列を指すポインタです。各文字ポインタはヌル文字で終わる文字列を指します。この配列を指すポインタは、通常、グローバル変数 environ に保存されます。これらの文字列は、引数としてコマンドへ直接渡されない情報を新しいプロセスに渡します ( environ(7) を参照)。

呼び出しプロセスイメージ内でオープンされているファイル記述子は、新しいプロセスイメージの中でもオープンされたままです。しかし、close-on-exec フラグが設定されているものは例外です。 ( close(2)fcntl(2) を参照)。オープンされたままの記述子は execve() の影響を受けません。 execve() が呼び出された時に標準の記述子 (0, 1 そして / または 2) がクローズされ、 ID 設定の結果、そのプロセスが特権を得た場合には、それらの記述子は自動的にオープンされます。特権を持っているかどうかに関わらず、どのプログラムも execve() の呼び出しの前後で、これらの記述子がクローズしたままとなると仮定すべきではありません。

呼び出しプロセスで無視するように設定されたシグナルは、新しいプロセス内でも無視されるように設定されます。呼び出しプロセスイメージ内で捕捉されるように設定されたシグナルは、新しいプロセスイメージ内でデフォルトのアクションに設定されます。ブロックされたシグナルは、シグナルアクションの変化とは無関係にブロックされたままになります。シグナルスタックは未定義にリセットされます (詳細については sigaction(2) を参照してください)。

新しいプロセスイメージファイルにユーザ ID 設定モードビットが設定されている場合 ( chmod(2) を参照)、新しいプロセスイメージの実効ユーザ ID は、新しいプロセスイメージファイルの所有者 ID に設定されます。新しいプロセスイメージファイルにグループ ID 設定モードビットが設定されている場合、新しいプロセスイメージの実効グループ ID は新しいプロセスイメージファイルのグループ ID に設定されます (実効グループ ID はグループリストの最初の要素です)。新しいプロセスの実ユーザ ID、実グループ ID、およびその他のグループ ID は、呼び出しプロセスイメージと同じになります。ユーザ ID 設定およびグループ ID 設定処理の後、実効ユーザ ID は退避ユーザ ID として記録され、実効グループ ID は退避グループ IDとして記録されます。これらの値は、後で実効 ID を変更するのに使用できます ( setuid(2) を参照)。

該当するファイルシステムで nosuid オプションが有効な場合、または新しいプロセスファイルがインタプリタファイルの場合、ID 設定ビットは意味を持ちません。実効 ID が変更された場合、システムコールのトレースは無効になります。

また、新しいプロセスは呼び出しプロセスから次の属性を継承します。

プロセス ID getpid(2) を参照
親プロセス ID getppid(2) を参照
プロセスグループ ID getpgrp(2) を参照
アクセスグループ getgroups(2) を参照
作業ディレクトリ chdir(2) を参照
ルートディレクトリ chroot(2) を参照
制御端末 termios(4) を参照
リソースの使用状況 getrusage(2) を参照
インターバルタイマ getitimer(2) を参照
リソースの使用制限 getrlimit(2) を参照
ファイルモードマスク umask(2) を参照
シグナルマスク sigaction(2), sigprocmask(2) を参照

プログラムが、 execve() システムコールの結果として実行されるとき、次のように記述されます:

main(argc, argv, envp) 
int argc; 
char **argv, **envp;

ここで、 argcargv の要素数 (``arg count'') であり、 argv は、引数自身を指す文字ポインタの配列を指します。

fexecve() は、 fd のファイルオフセットを無視します。実行パーミッションは、 fexecve() によってチェックされるので、ファイル記述子 fd は、 O_EXEC フラグでオープンされている必要はありません。しかしながら、実行されるファイルが、exec を行うためにプロセスの準備のための読み込みパーミッションを拒否するなら、 fdfexecve() に供給する唯一の方法は、 fd をオープンするとき、 O_EXEC フラグを使用することです。書き込みのために実行されるファイルをオープンできないことに注意してください。

戻り値

execve() システムコールは現在のプロセスイメージを新しいプロセスイメージで上書きするので、処理が成功した呼び出しには戻るプロセスがありません。 execve() が呼び出しプロセスに返ってくる場合はエラーが起きています。戻り値は -1 で、エラーを示すためにグローバル変数 errno が設定されます

エラー

次の場合、 execve() システムコールは処理に失敗し、呼び出しプロセスに戻ります:
[ ENOTDIR]
パスの構成要素中にディレクトリ以外のものが含まれています。
[ ENAMETOOLONG]
パス名の構成要素が 255 文字を越えているか、またはパス名全体が 1023 文字を越えています。
[ ENOEXEC]
インタプリトされるスクリプトを呼び出すとき、 #! 接頭辞と終わり改行を含んで、最初の行の長さが、 MAXSHELLCMDLEN 文字を越えています。
[ ENOENT]
新しいプロセスファイルが存在しません。
[ ELOOP]
パス名を変換するときに検出されたシンボリックリンクが多すぎます。
[ EACCES]
指定されたパスには、検索が許可されていないディレクトリが含まれています
[ EACCES]
新しいプロセスファイルが通常のファイルではありません。
[ EACCES]
新しいプロセスファイルは、実行が許可されていません。
[ ENOEXEC]
新しいプロセスファイルに適切なアクセス許可がありますが、ヘッダのマジック番号が無効です。
[ ETXTBSY]
新しいプロセスファイルは純粋な手続き (共有テキスト) ファイルで、現時点で他のプロセスによって書き込み用にオープンされています。
[ ENOMEM]
新しいプロセスは、許された ( getrlimit(2)) で課された最大値以上の仮想メモリを必要とします。
[ E2BIG]
新しいプロセスの引数リストのバイト数がシステムの課した上限を越えています。この上限は、 sysctl(3) の MIB 変数 KERN_ARGMAX により指定されます。
[ EFAULT]
新しいプロセスファイルは、ヘッダ内のサイズ値で示されるほど長くはありません。
[ EFAULT]
path, argv, または envp 引数が正しくないアドレスを指しています。
[ EIO]
ファイルシステムから読み込む間に入出力エラーが発生しました。

さらに、 fexecve() は、失敗して、次の場合に呼び出しプロセスに返ります:

[ EBADF]
fd 引数が、実行のためにオープンされている有効なファイル記述子ではありません。

規格

execve() システムコールは、特定の状況において記述子 0, 1 そして/または 2 を再度オープンする他は、 IEEE Std 1003.1-2001 (“POSIX.1”) に適合しています。将来規格が更新される際には、このような動作を要求することが期待されており、権限を持たないプロセスに対しても、これがデフォルトとなるかもしれません。インタプリトされるプログラムの実行をサポートしているのは、拡張です。 fexecve() システムコールは、The Open Group Extended API Set 2 仕様に適合しています。

歴史

execve() システムコールは 4.2BSD で登場しました。 fexecve() システムコールは FreeBSD 8.0 で登場しました。

警告

スーパユーザでないものに対して setuid されたプログラムが、実 uid が ``root'' の時に実行された場合、プログラムは部分的にスーパユーザの権限を持ちます。

fexecve() を通して解釈されたプログラムを実行するとき、カーネルは、インタプリタへの 2 番目の引数としての /dev/fd/n を供給します、ここで n は、 fexecve() への fd 引数に渡されるファイル記述子です。この解釈が正しく動作するように、 fdescfs(5) ファイルシステムは、 /dev/fd にマウントさられるものとします。

September 21, 2010 FreeBSD