fexecve -
ファイルディスクリプターで指定されたプログラムを実行する
#include <unistd.h>
int fexecve(int fd, char *const argv[], char *const envp[]);
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/
に書かれている。