После выполнения fcntl(memfd, F_ADD_SEALS, F_SEAL_WRITE);
вызовы типа mmap(NULL, 4096, PROT_READ, MAP_SHARED, memfd, 0);
завершаются с ошибкой EPERM
. Основываясь на man 2 fcntl
, я понимаю, что F_SEAL_WRITE
состоит в том, что он предотвращает только общие записи, доступные для записи. Точно так же, если я выполняю fcntl, когда у меня есть такая карта памяти только для чтения, она завершится с ошибкой EBUSY
, как я ожидаю, если бы карта была доступна для записи. Почему это происходит?
MCVE:
#include <unistd.h>
#include <fcntl.h>
#include <sys/syscall.h>
#include <sys/mman.h>
int main(void) {
void *buf;
int memfd = syscall(SYS_memfd_create, "foo", 2 /* MFD_ALLOW_SEALING */);
ftruncate(memfd, 4096);
buf = mmap(NULL, 4096, PROT_READ, MAP_SHARED, memfd, 0);
fcntl(memfd, 1033 /* F_ADD_SEALS */, 8 /* F_SEAL_WRITE */); // will fail
munmap(buf, 4096);
fcntl(memfd, 1033 /* F_ADD_SEALS */, 8 /* F_SEAL_WRITE */);
buf = mmap(NULL, 4096, PROT_READ, MAP_SHARED, memfd, 0); // will fail
return 0;
}
При запуске под strace
(в Linux 4.4.0-135-generic из Ubuntu 16.04) он выдает следующее:
memfd_create("foo", MFD_ALLOW_SEALING) = 3
ftruncate(3, 4096) = 0
mmap(NULL, 4096, PROT_READ, MAP_SHARED, 3, 0) = 0x7fd9a9865000
fcntl(3, F_ADD_SEALS, F_SEAL_WRITE) = -1 EBUSY (Device or resource busy)
munmap(0x7fd9a9865000, 4096) = 0
fcntl(3, F_ADD_SEALS, F_SEAL_WRITE) = 0
mmap(NULL, 4096, PROT_READ, MAP_SHARED, 3, 0) = -1 EPERM (Operation not permitted)