FEXECVE(3)

名前
fexecve - ファイルディスクリプターで指定されたプログラムを実行する

書式
#include <unistd.h>

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

    glibc 向けの機能検査マクロの要件 (feature_test_macros(7) 参照):

fexecve():
    glibc 2.10 以降:
        _POSIX_C_SOURCE >= 200809L
    glibc 2.10 より前:
        _GNU_SOURCE

説明
fexecve() performs the same task as execve(2), with the difference that the file to be executed is specified via a file descriptor, fd, rather than via a pathname. The file descriptor fd must be opened read-only (O_RDONLY) or with the O_PATH flag and the caller must have permission to execute the file that it refers to.

返り値
fexecve() は呼び出しに成功した場合、戻ることはない。 エラーの場合、返り値 -1 で関数が返り、 errno が適切に設定される。

エラー
エラーは execve(2) と同じだが、以下のエラーが追加になっている:

EINVAL
    fd が有効なファイルディスクリプターでない。または argv が NULL である。または envp が NULL である。

ENOENT
    The close-on-exec flag is set on fd, and fd refers to a script. See BUGS.

ENOSYS
    The kernel does not provide the execveat(2) system call, and the /proc filesystem could not be accessed.

バージョン
fexecve() は glibc 2.3.2 以降で実装されている。

属性
この節で使用されている用語の説明については、 attributes(7) を参照。
インターフェース | 属性 | 値
fexecve() | Thread safety | MT-Safe

準拠
POSIX.1-2008. この関数は POSIX.1-2001 では規定されておらず、 他のシステムで広く利用できるわけではない。 POSIX.1-2008 で規定されている。

注意
On Linux with glibc versions 2.26 and earlier, fexecve() is implemented using the proc(5) filesystem, so /proc needs to be mounted and available at the time of the call. Since glibc 2.27, if the underlying kernel supports the execveat(2) system call, then fexecve() is implemented using that system call, with the benefit that /proc does not need to be mounted.

fexecve() の裏にある考えは、呼び出し元が、ファイルを実行する前に実行ファイルの内容を検査 (チェックサムを確認) できるようにすることである。単に、ファイルをオープンして内容のチェックサムを検査し、それから execve(2) を行うのは十分ではない。なぜなら、2 つのステップの間で、ファイル名や、パス名のディレクトリの前の方が入れ換えられる可能性があるからだ (例えば、シンボリックリンクのリンク先を変更するなど)。fexecve() は、チェックサムの検査と fexecve() の呼び出しの間で、ファイルの内容を変更できる可能性があるという問題への対策にはならない。この問題に対する対応策は、確実に、ファイルのアクセス許可を設定し、悪意のあるユーザーがファイルを変更できないようにすることである。

fexecve() を使用する際の理にかなった方法は、 fd に close-on-exec フラグをセットし、 実行するプログラムを通じてそのファイルディスクリプターが外部にもれないようにすることである。 この方法は 2 つの理由から理にかなっている。 1 つ目は、 これにより不必要にファイルディスクリプターが消費されるのを防ぐことができる (実行されるプログラムは普通プログラム自身が参照するファイルを参照する必要はない)。 2 つ目は、 fexecve() が再帰的に使用された場合、 close-on-exec フラグを利用することで、 再帰の各ステップで新しいプログラムに一つ余計にファイルディスクリプターが渡されることによる、 ファイルディスクリプターの枯渇を防ぐことができる (ただし「バグ」を参照)。

バグ
fd がスクリプトを参照していて (つまり、 最初の行に文字 #! で始まるスクリプトインタープリターの指示がある実行テキストファイルである)、 fd に close-on-exec フラグがセットされていた場合、 fexecve() はエラー ENOENT で失敗する。 このエラーが起こるのは、 スクリプトインタープリターが実行される時点までに、 close-on-exec フラグにより fd がすでにクローズされてしまっているからである。 そのため、 スクリプトを参照する場合には、 close-on-exec フラグを fd にセットすることはできず、 「注意」の節で説明されている問題が起こり得る。

関連項目
execve(2), execveat(2)

この文書について
この man ページは Linux man-pages プロジェクトのリリース 5.10 の一部である。プロジェクトの説明とバグ報告に関する情報は https://www.kernel.org/doc/man-pages/ に書かれている。