execve - システムコールの説明 - Linux コマンド集 一覧表
名前
execve - プログラムを実行する
書式
#include <unistd.h>
int execve(const char *
filename
, char *const
argv
[],
char *const
envp
[]);
説明
execve
() は、filename
によって指定されたプログラムを実行する。
filename
は、バイナリ実行形式か、"#! interpreter
[arg]"
という形式の行で始まるスクリプトでなければならない。
後者の場合、interpreter は適切な実行ファイルのパス名でなければならず、
それ自身がスクリプトであってはならない。そしてそれは
interpreter
[arg] filename
の形で呼び出される。
argv
は新しいプログラムに渡される引き数文字列の配列である。
envp
は文字列の配列であり、伝統的に key=value
の形式を
しており、新しいプログラムの環境変数として渡される。
argv
と envp
の両方とも NULL ポインタで終っている
必要がある。引き数配列と環境変数は呼び出されたプログラムの main 関数を
int main(int argc, char *argv[], char *envp[])
のように定義することによってアクセス可能になる。
成功した場合、execve
() は返らない。
そして、呼び出し元のプロセスの text, data, bss, スタックは、
読み込まれたプログラムによって上書きされる。
呼び出されたプログラムは、呼び出し元の PID および
exec 時クローズ (close-on-exec) の設定されていないすべての
ファイル・ディスクリプタを継承する。
呼び出し元プロセスの保留シグナルは解除される。呼び出し元のプログラムで
設定されたシグナル捕獲時の動作はデフォルト動作に戻される。
SIGCHLD シグナルが SIG_IGN に設定されている場合は SIG_DFL にリセット
されるかもしれないし、されないかもしれない。
もし元のプログラムが ptrace されていると、execve
() が成功した後に
そのプログラムに SIGTRAP
が送られる。
filename
で指定されたプログラムファイルに set-user-ID ビットが
設定されており、呼び出したプロセスが ptrace されていない場合、
呼び出したプロセスの実効 (effective) ユーザ ID は
プログラムファイルの所有者 (owner) に変更される。
同様に、プログラムファイルに set-group-ID ビットが設定されていた場合、
呼び出したプロセスの有効グループ ID は
プログラムファイルのグループに変更される。
プロセスの実効ユーザ ID は保存 (saved) set-user-ID にコピーされる。
同様に、実効グループ ID は保存 set-group-ID にコピーされる。
このコピーは、set-user-ID / set-group-ID 許可ビットにより発生する
実効 ID の変更後に行われる。
実行ファイルが動的リンクされた a.out 実行形式で、共有ライブラリの
スタブを含むものだった場合、実行の開始時に Linux の
ダイナミック・リンカ
ld.so
(8) が呼び出され、必要な共有ライブラリをメモリに読み込んでリンクを行う。
実行ファイルがダイナミック・リンクされた ELF 実行形式だった場合、
PT_INTERP セグメントに指定されたインタプリタが必要な
共有ライブラリ (shared library) を読み込むのに使用される。
通常使用されるインタプリタは Linux libc version 5 をリンクしたバイナリ
の場合には /lib/ld-linux.so.1
が、GNU libc version 2 をリンクした
バイナリの場合には /lib/ld-linux.so.2
が使用される。
返り値
成功すると execve () は返らない。エラーの場合は -1 を返し、 errno を適当に設定する。
エラー
- E2BIG
- 環境変数 ( envp )と引き数リスト ( argv )の合計バイト数が大き過ぎる。
- EACCES
- filename やスクリプトインタプリタ名の構成要素に検索許可 (search permission) が与えられていない ( path_resolution (2)も参照すること)。
- EACCES
- ファイルもしくはスクリプトのインタプリタが通常ファイル (regular file) でない。
- EACCES
- ファイルやスクリプトや ELF インタプリタに 実行許可 (execute permission) が与えられていない。
- EACCES
- ファイル・システムが noexec でマウントされている。
- EFAULT
- filename がアクセス可能なアドレス空間の外を指している。
- EINVAL
- ELF 実行形式で複数の PT_INTERP セグメントが存在する。 (すなわち複数のインタプリタを指定した。)
- EIO
- I/O エラーが発生した。
- EISDIR
- ELF インタプリタがディレクトリだった。
- ELIBBAD
- ELF インタプリタが理解できるフォーマットでなかった。
- ELOOP
- filename やスクリプトや ELF のインタプリタを解決する際に遭遇した シンボリック・リンクが多過ぎる。
- EMFILE
- そのプロセスがオープンできるファイル数の上限まで既にオープンしている。
- ENAMETOOLONG
- filename が長過ぎる。
- ENFILE
- そのシステムでオープンできるファイル数の制限に達した。
- ENOENT
- ファイル filename かスクリプトや ELF のインタプリタが存在しない。
- ENOEXEC
- 実行ファイルが理解できない形式であるか、違うアーキテクチャのものか、 その他のフォーマット・エラーにより実行ができなかった。
- ENOMEM
- カーネルに十分なメモリがない。
- ENOTDIR
- filename やスクリプトや ELF のインタプリタの構成要素がディレクトリでない。
- EPERM
- ファイル・システムが nosuid でマウントされ、ユーザがスーパーユーザでなく、 ファイルに SUID あるいは SGID ビットが設定されている。
- EPERM
- プロセスがトレースされ、ユーザがスーパーユーザでなく、 ファイルに SUID あるいは SGID ビットが設定されている。
- ETXTBSY
- 実行ファイルを書き込み用にオープンしているプロセスがある。
準拠
SVr4, 4.3BSD, POSIX.1-2001. POSIX.1-2001 には #! 動作についての記述はないが、 他は互換性がある。
注意
SUID プロセスと SGID プロセスは ptrace
() できない。
Linux はスクリプトの SUID と SGID ビットを無視する。
ファイルシステムを
nosuid
でマウントした場合に SUID/SGID 実行ファイルをどの様に扱うかは、
Linux カーネルのバージョンによって異なる:
あるバージョンでは、すでに必要な権限を持っている場合を除いて、
その実行を拒否する (そして EPERM を返す)。別のあるバージョンでは
SUID/SGID ビットのみを無視し
exec
()は成功する。
#! 実行形式のシェル・スクリプトの1行目には最大 127 文字が許されている。
履歴
Unix V6 では exec ()コールの引き数リストは 0 で終端され、 main の引き数リストは -1 で終端されていた。 そのため、 main の引き数リストは、その後の exec ()コールには直接使用できなかった。 Unix V7 以降では、ともに NULL で終端される。