Manpages

名 前

memfd_create − 無 名 フ ァ イ ル (anonymous file) を 作 成 す る

書 式

#include <sys/memfd.h>

int memfd_create(const char *name, unsigned int flags);

説 明

memfd_create() は 、 無 名 フ ァ イ ル (anonymous file) を 作 成 し 、 そ の フ ァ イ ル を 参 照 す る フ ァ イ ル デ ィ ス ク リ プ タ ー を 返 す 。 こ の フ ァ イ ル は 通 常 の フ ァ イ ル と 同 様 に 振 る 舞 い 、 変 更 、 切 り 詰 め (truncate)、 メ モ リ ー マ ッ プ な ど を 行 う こ と が で き る 。 し か し 、 通 常 の フ ァ イ ル と は 違 い 、 こ の フ ァ イ ル は RAM 上 に 置 か れ 、 格 納 さ れ る ス ト レ ー ジ は 揮 発 性 で あ る 。 こ の フ ァ イ ル へ の 参 照 が す べ て な く な る と 、 フ ァ イ ル は 自 動 的 に 解 放 さ れ る 。 こ の フ ァ イ ル が 置 か れ る ペ ー ジ に は 無 名 メ モ リ ー (anonymous memory) が 使 用 さ れ る 。 し た が っ て 、 memfd_create() で 作 成 さ れ た フ ィ ア ル は 、 他 の 無 名 メ モ リ ー の 割 り 当 て (MAP_ANONYMOUS フ ラ グ 付 き の mmap(2) を 使 っ て 割 り 当 て ら れ た 無 名 メ モ リ ー な ど ) と 同 じ 動 作 を す る 。 フ ァ イ ル の 初 期 サ イ ズ は 0 に 設 定 さ れ る 。 呼 び 出 し の 後 に 、 ftruncate(2) を 使 っ て フ ァ イ ル サ イ ズ を 設 定 す べ き で あ る (代 わ り に 、 write(2) や 同 様 の 関 数 を 呼 び 出 し て フ ァ イ ル に デ ー タ を 書 き 込 む こ と も で き る )。

name に 指 定 さ れ た 名 前 は フ ァ イ ル 名 と し て 使 用 さ れ 、 デ ィ レ ク ト リ /proc/self/fd/ で 対 応 す る シ ン ボ リ ッ ク リ ン ク の リ ン ク 先 と し て 表 示 さ れ る 。 表 示 さ れ る 名 前 の 前 に は 常 に memfd: が 付 き 、 こ の 名 前 は デ バ ッ グ 用 途 と し て の み 機 能 す る 。 名 前 は フ ァ イ ル デ ィ ス ク リ プ タ ー の 動 作 に は 影 響 せ ず 、 複 数 の フ ァ イ ル が 同 じ 名 前 を 持 っ て も 副 作 用 は な い 。 以 下 の 値 を ビ ッ ト 論 理 和 で flags に 指 定 し て 、 memfd_create() の 動 作 を 変 更 で き る 。
MFD_CLOEXEC
新 し い フ ァ イ ル デ ィ ス ク リ プ タ ー に close−on−exec (FD_CLOEXEC) フ ラ グ を セ ッ ト す る 。 こ れ が 有 用 な 理 由 に つ い て は open(2)O_CLOEXEC フ ラ グ の 説 明 を 参 照 の こ と 。
MFD_ALLOW_SEALING
こ の フ ァ イ ル に 対 し て sealing 操 作 を 許 可 す る 。 fcntl(2)F_ADD_SEALSF_GET_SEALS 操 作 の 議 論 を 参 照 。 下 記 の 「 注 意 」 も 参 照 。 初 期 の seal 集 合 は 空 と な る 。 こ の フ ラ グ を 指 定 し な か っ た 場 合 、 初 期 の seal 集 合 は F_SEAL_SEAL と な り 、 こ れ は こ の フ ァ イ ル に は 他 の seal を セ ッ ト で き な い こ と と い う こ と で あ る 。

flags の 未 使 用 の ビ ッ ト は 0 で な け れ ば な ら な い 。 返 り 値 と し て memfd_create() は 、 作 成 し た フ ァ イ ル を 参 照 す る の に 使 用 で き る 新 し い フ ァ イ ル デ ィ ス ク リ プ タ ー を 返 す 。 こ の フ ァ イ ル デ ィ ス ク リ プ タ ー は 読 み 書 き 両 用 (O_RDWR) で オ ー プ ン さ れ 、 O_LARGEFILE が こ の フ ァ イ ル デ ィ ス ク リ プ タ ー に セ ッ ト さ れ る 。

fork(2)execve(2) に 関 し て は 、 memfd_create() で 作 成 し た フ ァ イ ル デ ィ ス ク リ プ タ ー に つ い て も 通 常 の 動 作 が 適 用 さ れ る 。 フ ァ イ ル デ ィ ス ク リ プ タ ー の コ ピ ー は fork(2) で 生 成 さ れ る 子 プ ロ セ ス に 継 承 さ れ 、 同 じ フ ァ イ ル を 参 照 す る 。 close−on−exec フ ラ グ が セ ッ ト さ れ て い な い 限 り 、 execve(2) の 前 後 で フ ァ イ ル デ ィ ス ク リ プ タ ー は 保 持 さ れ る 。

返 り 値

成 功 の 場 合 、 memfd_create() は 新 し い フ ァ イ ル デ ィ ス ク リ プ タ ー を 返 す 。 エ ラ ー の 場 合 、 −1 を 返 し 、 errno に エ ラ ー を 示 す 値 を 設 定 す る 。

エ ラ ー

EFAULT

name の ア ド レ ス が 無 効 な メ モ リ ー を 指 し て い る 。

EINVAL

サ ポ ー ト さ れ て い な い 値 が い ず れ か の 引 き 数 で 指 定 さ れ た 。 flags に 未 知 の ビ ッ ト が 含 ま れ て い た か 、 name が 長 過 ぎ た 。
EMFILE

オ ー プ ン さ れ て い る フ ァ イ ル デ ィ ス ク リ プ タ ー の プ ロ セ ス 単 位 の 上 限 に 達 し た 。

ENFILE シ ス テ ム 全 体 で オ ー プ ン さ れ て い る フ ァ イ ル の 総 数 が 上 限 に 達 し た 。

ENOMEM 新 し い 無 名 フ ァ イ ル を 作 成 す る の に 十 分 な メ モ リ ー が な か っ た 。

バ ー ジ ョ ン

memfd_create() シ ス テ ム コ ー ル は Linux 3.17 で 初 め て 登 場 し た 。 GNU C ラ イ ブ ラ リ で の サ ポ ー ト は 検 討 中 で あ る 。

準 拠

memfd_create() シ ス テ ム コ ー ル は Linux 固 有 で あ る 。

注 意

memfd_create() シ ス テ ム コ ー ル は 、 手 動 で tmpfs フ ァ イ ル シ ス テ ム を マ ウ ン ト し て 、 そ の フ ァ イ ル シ ス テ ム に フ ァ イ ル を オ ー プ ン す る と い う 操 作 の 、 簡 単 な 代 替 手 段 を 提 供 し て い る 。 memfd_create() の 主 な 目 的 は 、 fcntl(2) が 提 供 す る file−sealing API で 使 用 で き る 、 フ ァ イ ル と そ れ に 関 連 付 け ら れ る フ ァ イ ル デ ィ ス ク リ プ タ ー を 作 成 す る こ と で あ る 。

memfd_create() シ ス テ ム コ ー ル は 、 file sealing な し で も 用 途 が あ る (こ れ が 明 示 的 に MFD_ALLOW_SEALING フ ラ グ が 要 求 さ れ な い 限 り 、 file−sealing が 無 効 に な る 理 由 で あ る )。 特 に 、 フ ァ イ ル シ ス テ ム に 実 際 に フ ァ イ ル を 残 す 意 図 が な い 場 合 、 tmp に フ ァ イ ル を 作 成 し た り open(2) O_TMPFILE を 使 っ た り す る 際 の 代 替 手 段 と し て 使 用 で き る 。

file sealing
file sealing が な い 場 合 、 共 有 メ モ リ ー 経 由 で 通 信 す る プ ロ セ ス は 、 互 い に 信 頼 す る か 、 信 頼 し て い な い 相 手 が 共 有 メ モ リ ー 領 域 を 問 題 が あ る 方 法 で 操 作 す る 可 能 性 に 対 処 す る た め の 対 策 を 講 じ な け れ ば な ら な い 。 例 え ば 、 信 頼 し て い な い 相 手 は 、 い つ で も 共 有 メ モ リ ー の 内 容 を 変 更 し た り 、 共 有 メ モ リ ー 領 域 を 縮 小 し た り す る 可 能 性 が あ る 。 前 者 の 場 合 は 、 ロ ー カ ル プ ロ セ ス で は 、 デ ー タ の 確 認 時 点 と 使 用 時 点 の 競 合 条 件 の 問 題 が 起 こ り 得 る (通 常 は こ の 問 題 へ の 対 処 は 共 有 メ モ リ ー 領 域 か ら デ ー タ を こ ぴ ー し て か ら デ ー タ を 確 認 、 使 用 す る こ と で あ る )。 後 者 の 場 合 は 、 ロ ー カ ル プ ロ セ ス で は 、 共 有 メ モ リ ー 領 域 の 存 在 し な く な っ た 場 所 に ア ク セ ス し よ う と し た 際 に シ グ ナ ル SIGBUS が 発 生 す る 可 能 性 が あ る (こ の 可 能 性 に 対 処 す る に は シ グ ナ ル SIGBUS に 対 し て ハ ン ド ラ ー を 使 用 す る 必 要 が あ る )。 信 頼 し て い な い 相 手 へ の 対 処 に よ り 、 共 有 メ モ リ ー を 利 用 す る コ ー ド に 余 計 な 複 雑 性 が 増 す こ と に な る 。 メ モ リ ー sealing に よ り 余 計 な 複 雑 性 を な く す こ と が で き る 。 相 手 が 望 ま な い 方 法 で 共 有 メ モ リ ー を 変 更 で き な い こ と を 知 っ て い る こ と で 、 プ ロ セ ス は 安 全 に 動 作 で き る よ う に な る 。

sealing 機 構 の 使 い 方 の 例 は 以 下 の と お り で あ る 。

1. 最 初 の プ ロ セ ス は

memfd_create() を 使 っ て tmpfs フ ァ イ ル を 作 成 す る 。

memfd_create() は こ れ 以 降 の ス テ ッ プ で 使 用 す る フ ァ イ ル デ ィ ス ク リ プ タ ー を 返 す 。

2. 最 初 の プ ロ セ ス は

ftruncate(2) を 使 っ て 直 前 の ス テ ッ プ で 作 成 し た フ ァ イ

ル の サ イ ズ を 変 更 し 、 mmap(2) を 使 っ て そ の フ ァ イ ル を マ ッ ピ ン グ し 、 共 有 メ モ リ ー に 所 望 の デ ー タ を 配 置 す る 。

3. 最 初 の プ ロ セ ス は 、 こ の フ ァ イ ル に 対 す る 今 後 の 変 更 を 制 限 す る た め に 、

fcntl(2)F_ADD_SEALS 操 作 を 使 っ て 、 そ の フ ァ イ ル に seal を い く つ か 設 定 す る 。 (seal F_SEAL_WRITE を 設 定 す る 場 合 、 直 前 の ス テ ッ プ で 作 成 し た 書 き 込 み 可 能 な 共 有 マ ッ ピ ン グ を ま ず ア ン マ ッ プ す る 必 要 が 出 て く る 。 )

4. 二 つ 目 の プ ロ セ ス は

tmpfs フ ァ イ ル の フ ァ イ ル デ ィ ス ク リ プ タ ー を 入 手

し 、 そ の フ ァ イ ル を マ ッ プ す る 。 以 下 に 示 す 方 法 を 使 用 す る こ と が で き る 。

*

memfd_create() を 呼 び 出 し た プ ロ セ ス は 、 得 ら れ た フ ァ イ ル デ ィ ス ク リ プ タ ー を 二 つ 目 の プ ロ セ ス に UNIX ド メ イ ン ソ ケ ッ ト 経 由 で 渡 す こ と が で き る (unix(7) と cmsg(3) を 参 照 )。 そ れ か ら 、 二 つ 目 の プ ロ セ ス は mmap(2) を 使 っ て フ ァ イ ル を マ ッ プ す る 。

*

二 つ 目 の プ ロ セ ス を fork(2) を 使 っ て 作 成 す る 。 そ う す る と 、 自 動 的 に フ ァ イ ル デ ィ ス ク リ プ タ ー と マ ッ ピ ン グ が 継 承 さ れ る 。 (こ の 方 法 と 次 の 方 法 で は 、 二 つ の プ ロ セ ス 間 で 自 然 な 信 頼 関 係 が 存 在 す る こ と に な る 。 な ぜ な ら 、 二 つ の プ ロ セ ス は 同 じ ユ ー ザ ー ID。 の 元 で 実 行 さ れ て い る か ら で あ る 。 し た が っ て 、 file sealing は 通 常 は 不 要 で あ ろ う 。 )

*

二 つ 目 の プ ロ セ ス は /proc/<pd>/fd/<fd> を オ ー プ ン す る 。 <pid> は 最 初 の プ ロ セ ス (memfd_create() を 呼 び 出 し た プ ロ セ ス ) の PID で 、 <fd> は 最 初 の プ ロ セ ス で の memfd_create() の 呼 び 出 し で 返 さ れ た フ ァ イ ル デ ィ ス ク リ プ タ ー 番 号 で あ る 。 そ れ か ら こ の フ ァ イ ル を mmap(2) を 使 っ て マ ッ ピ ン グ す る 。

5. 二 つ

目 の プ ロ セ ス は fcntl(2)F_GET_SEALS 操 作 を 使 っ て 、 そ の フ ァ イ ル に 適 用 さ れ て い る seal の ビ ッ ト マ ス ク を 取 得 す る 。 こ の ビ ッ ト マ ス ク を 調 べ て 、 フ ァ イ ル の 変 更 に 関 し て ど の よ う な 制 限 が 適 用 さ れ て い る か を 知 る こ と が で き る 。 (F_SEAL_SEAL seal が そ れ ま で に 適 用 さ れ て い な い 限 り は ) 必 要 で あ れ ば 、 二 つ 目 の プ ロ セ ス は さ ら に seal を 設 定 し て 追 加 の 制 限 を か け る こ と が で き る 。

以 下 で は memfd_create() と file sealing API の 使 用 例 を 示 す サ ン プ ル プ ロ グ ラ ム を 2 つ と り あ げ る 。 最 初 の プ ロ グ ラ ム t_memfd_create.c は 、 memfd_create() を 使 っ て tmpfs フ ァ イ ル を 作 成 し 、 そ の フ ァ イ ル の サ イ ズ を 設 定 し 、 メ モ リ ー に マ ッ ピ ン グ し 、 要 求 さ れ た 場 合 に は そ の フ ァ イ ル に seal を 設 定 す る 。 こ の プ ロ グ ラ ム は 最 大 で 3 つ の コ マ ン ド ラ イ ン 引 き 数 を 取 り 、 最 初 の 2 つ は 必 須 で あ る 。 最 初 の 引 き 数 は フ ァ イ ル に 関 連 付 け ら れ る 名 前 で 、 2 番 目 の 引 き 数 は フ ァ イ ル に 設 定 さ れ る サ イ ズ で あ る 。 省 略 可 能 な 3 番 目 の 引 き 数 は 、 こ の フ ァ イ ル に 設 定 す る seal を 指 定 す る 文 字 列 で あ る 。

2 つ め の プ ロ グ ラ ム t_get_seals.c を 使 う と 、 memfd_create() を 使 っ て 作 成 さ れ た 既 存 の フ ァ イ ル を オ ー プ ン し 、 そ の フ ァ イ ル に 適 用 さ れ て い る seal の 集 合 を 調 査 で き る 。 以 下 の シ ェ ル の セ ッ シ ョ ン は こ れ ら の プ ロ グ ラ ム の 使 用 例 を 示 し た も の で あ る 。 ま ず tmpfs フ ァ イ ル を 作 成 し 、 そ の フ ァ イ ル に seal を い く つ か 設 定 し て い る 。

$ ./t_memfd_create my_memfd_file 4096 sw &
[1] 11775
PID: 11775; fd: 3; /proc/11775/fd/3 こ の 時 点 で は 、 t_memfd_create プ ロ グ ラ ム は バ ッ ク グ ラ ウ ン ド で 動 作 し 続 け る 。 も う 一 つ の プ ロ グ ラ ム か ら 、 memfd_create() が オ ー プ ン し た デ ィ ス ク リ プ タ ー に 対 応 す る /proc/PID/fd フ ァ イ ル を オ ー プ ン す る こ と で 、 memfd_create() で 作 成 さ れ た フ ァ イ ル の フ ァ イ ル デ ィ ス ク リ プ タ ー を 取 得 で き る 。 そ の パ ス 名 を 使 っ て 、 /proc/PID/fd シ ン ボ リ ッ ク リ ン ク の 内 容 を 調 査 し 、 t_get_seals プ ロ グ ラ ム を 使 っ て そ の フ ァ イ ル に 設 定 さ れ て い る seal を 見 る こ と が で き る 。

$ readlink /proc/11775/fd/3
/memfd:my_memfd_file (deleted)
$ ./t_get_seals /proc/11775/fd/3
Existing seals: WRITE SHRINK プ ロ グ ラ ム の ソ ー ス : t_memfd_create.c

#include <sys/memfd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>

#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \ }
while (0)

int
main(int argc, char *argv[])
{
int fd;
unsigned int seals;
char *addr;
char *name, *seals_arg;
ssize_t len;

if (argc < 3) {
fprintf(stderr, "%s name size [seals]\n", argv[0]);
fprintf(stderr, "\t'seals' can contain any of the "
"following characters:\n");
fprintf(stderr, "\t\tg − F_SEAL_GROW\n");
fprintf(stderr, "\t\ts − F_SEAL_SHRINK\n");
fprintf(stderr, "\t\tw − F_SEAL_WRITE\n");
fprintf(stderr, "\t\tS − F_SEAL_SEAL\n");
exit(EXIT_FAILURE); }

name = argv[1];
len = atoi(argv[2]);
seals_arg = argv[3];

/* Create an anonymous file in tmpfs; allow seals to be
placed on the file */

fd = memfd_create(name, MFD_ALLOW_SEALING);
if (fd == −1)
errExit("memfd_create");

/* Size the file as specified on the command line */

if (ftruncate(fd, len) == −1)
errExit("truncate");

printf("PID: %ld; fd: %d; /proc/%ld/fd/%d\n",
(long) getpid(), fd, (long) getpid(), fd);

/* Code to map the file and populate the mapping with data
omitted */

/* If a 'seals' command−line argument was supplied, set some
seals on the file */

if (seals_arg != NULL) {
seals = 0;

if (strchr(seals_arg, 'g') != NULL)
seals |= F_SEAL_GROW;
if (strchr(seals_arg, 's') != NULL)
seals |= F_SEAL_SHRINK;
if (strchr(seals_arg, 'w') != NULL)
seals |= F_SEAL_WRITE;
if (strchr(seals_arg, 'S') != NULL)
seals |= F_SEAL_SEAL;

if (fcntl(fd, F_ADD_SEALS, seals) == −1)
errExit("fcntl"); }

/* Keep running, so that the file created by memfd_create()
continues to exist */

pause();

exit(EXIT_SUCCESS); } プ ロ グ ラ ム の ソ ー ス : t_get_seals.c
#include <sys/memfd.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \ }
while (0)

int
main(int argc, char *argv[])
{
int fd;
unsigned int seals;

if (argc != 2) {
fprintf(stderr, "%s /proc/PID/fd/FD\n", argv[0]);
exit(EXIT_FAILURE); }

fd = open(argv[1], O_RDWR);
if (fd == −1)
errExit("open");

seals = fcntl(fd, F_GET_SEALS);
if (seals == −1)
errExit("fcntl");

printf("Existing seals:");
if (seals & F_SEAL_SEAL)
printf(" SEAL");
if (seals & F_SEAL_GROW)
printf(" GROW");
if (seals & F_SEAL_WRITE)
printf(" WRITE");
if (seals & F_SEAL_SHRINK)
printf(" SHRINK");
printf("\n");

/* Code to map the file and access the contents of the
resulting mapping omitted */

exit(EXIT_SUCCESS); }

関 連 項 目

fcntl(2), ftruncate(2), mmap(2), shmget(2), shm_open(3)

こ の 文 書 に つ い て

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