Index: sys/amd64/linux/linux_dummy.c =================================================================== --- sys/amd64/linux/linux_dummy.c +++ sys/amd64/linux/linux_dummy.c @@ -134,7 +134,6 @@ /* Linux 3.15: */ DUMMY(kexec_file_load); /* Linux 3.17: */ -DUMMY(memfd_create); DUMMY(seccomp); /* Linux 3.18: */ DUMMY(bpf); Index: sys/amd64/linux32/linux32_dummy.c =================================================================== --- sys/amd64/linux32/linux32_dummy.c +++ sys/amd64/linux32/linux32_dummy.c @@ -138,7 +138,6 @@ DUMMY(sched_setattr); DUMMY(sched_getattr); /* Linux 3.17: */ -DUMMY(memfd_create); DUMMY(seccomp); /* Linux 3.18: */ DUMMY(bpf); Index: sys/arm64/linux/linux_dummy.c =================================================================== --- sys/arm64/linux/linux_dummy.c +++ sys/arm64/linux/linux_dummy.c @@ -132,7 +132,6 @@ DUMMY(sched_setattr); DUMMY(sched_getattr); /* Linux 3.17: */ -DUMMY(memfd_create); DUMMY(seccomp); /* Linux 3.18: */ DUMMY(bpf); Index: sys/compat/linux/linux_file.h =================================================================== --- sys/compat/linux/linux_file.h +++ sys/compat/linux/linux_file.h @@ -113,6 +113,9 @@ #define LINUX_F_SETPIPE_SZ (LINUX_F_SPECIFIC_BASE + 7) #define LINUX_F_GETPIPE_SZ (LINUX_F_SPECIFIC_BASE + 8) +#define LINUX_F_ADD_SEALS (LINUX_F_SPECIFIC_BASE + 9) +#define LINUX_F_GET_SEALS (LINUX_F_SPECIFIC_BASE + 10) + #define LINUX_F_GETLKP 36 #define LINUX_F_SETLKP 37 #define LINUX_F_SETLKPW 38 Index: sys/compat/linux/linux_file.c =================================================================== --- sys/compat/linux/linux_file.c +++ sys/compat/linux/linux_file.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -1296,6 +1297,16 @@ case LINUX_F_DUPFD_CLOEXEC: return (kern_fcntl(td, args->fd, F_DUPFD_CLOEXEC, args->arg)); + + /* + * Our F_SEAL_* values match Linux one for maximum compatibility. So we + * only needed to account for different values for fcntl(2) commands. + */ + case LINUX_F_GET_SEALS: + return (kern_fcntl(td, args->fd, F_GET_SEALS, 0)); + + case LINUX_F_ADD_SEALS: + return (kern_fcntl(td, args->fd, F_ADD_SEALS, args->arg)); } return (EINVAL); @@ -1537,3 +1548,46 @@ return (kern_posix_fallocate(td, args->fd, args->offset, args->len)); } + +#define LINUX_MEMFD_PREFIX "memfd:" + +int +linux_memfd_create(struct thread *td, struct linux_memfd_create_args *args) +{ + char memfd_name[LINUX_NAME_MAX + 1]; + int error, flags, shmflags, oflags; + + /* + * This is our clever trick to avoid the heap allocation to copy in the + * uname. We don't really need to go this far out of our way, but it + * does keep the rest of this function fairly clean as they don't have + * to worry about cleanup on the way out. + */ + error = copyinstr(args->uname_ptr, + memfd_name + sizeof(LINUX_MEMFD_PREFIX) - 1, + LINUX_NAME_MAX - sizeof(LINUX_MEMFD_PREFIX) - 1, NULL); + if (error != 0) { + if (error == ENAMETOOLONG) + error = EINVAL; + return (error); + } + + memcpy(memfd_name, LINUX_MEMFD_PREFIX, sizeof(LINUX_MEMFD_PREFIX) - 1); + flags = args->flags; + if ((flags & ~(MFD_CLOEXEC | MFD_ALLOW_SEALING | MFD_HUGETLB | + MFD_HUGE_MASK)) != 0) + return (EINVAL); + /* Size specified but no HUGETLB. */ + if ((flags & MFD_HUGE_MASK) != 0 && (flags & MFD_HUGETLB) == 0) + return (EINVAL); + /* We don't actually support HUGETLB. */ + if ((flags & MFD_HUGETLB) != 0) + return (ENOSYS); + oflags = O_RDWR; + shmflags = 0; + if ((flags & MFD_CLOEXEC) != 0) + oflags |= O_CLOEXEC; + if ((flags & MFD_ALLOW_SEALING) != 0) + shmflags |= SHM_ALLOW_SEALING; + return (kern_shm_open2(td, SHM_ANON, oflags, 0, shmflags, memfd_name)); +} Index: sys/i386/linux/linux_dummy.c =================================================================== --- sys/i386/linux/linux_dummy.c +++ sys/i386/linux/linux_dummy.c @@ -134,7 +134,6 @@ DUMMY(sched_setattr); DUMMY(sched_getattr); /* Linux 3.17: */ -DUMMY(memfd_create); DUMMY(seccomp); /* Linux 3.18: */ DUMMY(bpf);