Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F154227179
D21393.id62537.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
24 KB
Referenced Files
None
Subscribers
None
D21393.id62537.diff
View Options
Index: Makefile.inc1
===================================================================
--- Makefile.inc1
+++ Makefile.inc1
@@ -947,7 +947,8 @@
# Syscall stubs rewritten in C and obsolete MD assembly implementations
# Date SVN Rev Syscalls
# 20180604 r334626 brk sbrk
-.for f in brk sbrk
+# 20190916 r35XXXX shm_open
+.for f in brk sbrk shm_open
@if [ -e "${OBJTOP}/lib/libc/.depend.${f}.o" ] && \
egrep -qw '${f}\.[sS]' ${OBJTOP}/lib/libc/.depend.${f}.o; then \
echo "Removing stale dependencies for ${f} syscall wrappers"; \
Index: lib/libc/include/libc_private.h
===================================================================
--- lib/libc/include/libc_private.h
+++ lib/libc/include/libc_private.h
@@ -391,6 +391,7 @@
struct __wrusage *, struct __siginfo *);
__ssize_t __sys_write(int, const void *, __size_t);
__ssize_t __sys_writev(int, const struct iovec *, int);
+int __sys_shm_open2(const char *, int, __mode_t, int, const char *);
int __libc_sigaction(int, const struct sigaction *,
struct sigaction *) __hidden;
Index: lib/libc/sys/Makefile.inc
===================================================================
--- lib/libc/sys/Makefile.inc
+++ lib/libc/sys/Makefile.inc
@@ -46,6 +46,7 @@
SRCS+= brk.c
SRCS+= pipe.c
+SRCS+= shm_open.c
SRCS+= vadvise.c
SRCS+= compat-stub.c
@@ -475,7 +476,8 @@
setuid.2 seteuid.2 \
setuid.2 setgid.2
MLINKS+=shmat.2 shmdt.2
-MLINKS+=shm_open.2 shm_unlink.2
+MLINKS+=shm_open.2 memfd_create.3 \
+ shm_open.2 shm_unlink.2
MLINKS+=sigwaitinfo.2 sigtimedwait.2
MLINKS+=stat.2 fstat.2 \
stat.2 fstatat.2 \
Index: lib/libc/sys/Symbol.map
===================================================================
--- lib/libc/sys/Symbol.map
+++ lib/libc/sys/Symbol.map
@@ -409,6 +409,7 @@
fhreadlink;
getfhat;
funlinkat;
+ memfd_create;
};
FBSDprivate_1.0 {
Index: lib/libc/sys/shm_open.2
===================================================================
--- lib/libc/sys/shm_open.2
+++ lib/libc/sys/shm_open.2
@@ -28,11 +28,11 @@
.\"
.\" $FreeBSD$
.\"
-.Dd January 20, 2017
+.Dd September 24, 2019
.Dt SHM_OPEN 2
.Os
.Sh NAME
-.Nm shm_open , shm_unlink
+.Nm memfd_create , shm_open , shm_unlink
.Nd "shared memory object operations"
.Sh LIBRARY
.Lb libc
@@ -41,6 +41,8 @@
.In sys/mman.h
.In fcntl.h
.Ft int
+.Fn memfd_create "const char *name" "unsigned int flags"
+.Ft int
.Fn shm_open "const char *path" "int flags" "mode_t mode"
.Ft int
.Fn shm_unlink "const char *path"
@@ -139,14 +141,64 @@
.Fn shm_unlink
system call removes a shared memory object named
.Fa path .
+.Pp
+The
+.Fn memfd_create
+function creates an anonymous shared memory object, identical to that created
+by
+.Fn shm_open
+when
+.Dv SHM_ANON
+is specified.
+Newly created objects start off with a size of zero.
+The size of the new object must be adjusted via
+.Xr ftruncate 2 .
+.Pp
+The
+.Fa name
+argument must not be
+.Dv NULL ,
+but it may be an empty string.
+The length of the
+.Fa name
+argument may not exceed
+.Dv NAME_MAX
+minus six characters for the prefix
+.Dq memfd: ,
+which will be prepended.
+The
+.Fa name
+argument is intended solely for debugging purposes and will never be used by the
+kernel to identify a memfd.
+Names are therefore not required to be unique.
+.Pp
+The following
+.Fa flags
+may be specified to
+.Fn memfd_create :
+.Bl -tag -width MFD_ALLOW_SEALING
+.It Dv MFD_CLOEXEC
+Set
+.Dv FD_CLOEXEC
+on the resulting file descriptor.
+.It Dv MFD_ALLOW_SEALING
+Allow adding seals to the resulting file descriptor using the
+.Dv F_ADD_SEALS
+.Xr fcntl 2
+command.
+.It Dv MFD_HUGETLB
+This flag is currently unsupported.
+.El
.Sh RETURN VALUES
If successful,
+.Fn memfd_create
+and
.Fn shm_open
-returns a non-negative integer,
+both return a non-negative integer,
and
.Fn shm_unlink
returns zero.
-Both functions return -1 on failure, and set
+All three functions return -1 on failure, and set
.Va errno
to indicate the error.
.Sh COMPATIBILITY
@@ -220,6 +272,33 @@
errx(EX_IOERR, "%s: pwrite length mismatch", __func__);
.Ed
.Sh ERRORS
+.Fn memfd_create
+fails with these error codes for these conditions:
+.Bl -tag -width Er
+.It Bq Er EBADF
+The
+.Fa name
+argument was NULL.
+.It Bq Er EINVAL
+The
+.Fa name
+argument was too long.
+.Pp
+An invalid or unsupported flag was included in
+.Fa flags .
+.It Bq Er EMFILE
+The process has already reached its limit for open file descriptors.
+.It Bq Er ENFILE
+The system file table is full.
+.It Bq Er ENOSYS
+In
+.Fa memfd_create ,
+.Dv MFD_HUGETLB
+was specified in
+.Fa flags ,
+and this system does not support forced hugetlb mappings.
+.El
+.Pp
.Fn shm_open
fails with these error codes for these conditions:
.Bl -tag -width Er
@@ -290,6 +369,11 @@
.Xr sendfile 2
.Sh STANDARDS
The
+.Fn memfd_create
+function is expected to be compatible with the Linux system call of the same
+name.
+.Pp
+The
.Fn shm_open
and
.Fn shm_unlink
@@ -297,6 +381,11 @@
.St -p1003.1b-93 .
.Sh HISTORY
The
+.Fn memfd_create
+function appeared in
+.Fx 13.0 .
+.Pp
+The
.Fn shm_open
and
.Fn shm_unlink
Index: lib/libc/sys/shm_open.c
===================================================================
--- /dev/null
+++ lib/libc/sys/shm_open.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2019 Kyle Evans <kevans@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice(s), this list of conditions and the following disclaimer as
+ * the first lines of this file unmodified other than the possible
+ * addition of one or more copyright notices.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice(s), this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/syscall.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "libc_private.h"
+
+__weak_reference(shm_open, _shm_open);
+__weak_reference(shm_open, __sys_shm_open);
+
+/* XXX TODO */
+#define SHM_OPEN2_OSREL 1300048
+
+#define MEMFD_NAME_PREFIX "memfd:"
+
+int
+shm_open(const char *path, int flags, mode_t mode)
+{
+
+ if (__getosreldate() >= SHM_OPEN2_OSREL)
+ return (__sys_shm_open2(path, flags | O_CLOEXEC, mode, 0,
+ NULL));
+
+ /*
+ * Fallback to shm_open(2) on older kernels. The kernel will enforce
+ * O_CLOEXEC in this interface, unlike the newer shm_open2 which does
+ * not enforce it. The newer interface allows memfd_create(), for
+ * instance, to not have CLOEXEC on the returned fd.
+ */
+ return (syscall(SYS_freebsd12_shm_open, path, flags, mode));
+}
+
+/*
+ * The path argument is passed to the kernel, but the kernel doesn't currently
+ * do anything with it. Linux exposes it in linprocfs for debugging purposes
+ * only, but our kernel currently will not do the same.
+ */
+int
+memfd_create(const char *name, unsigned int flags)
+{
+ char memfd_name[NAME_MAX + 1];
+ size_t namelen;
+ int oflags, shmflags;
+
+ if (name == NULL)
+ return (EBADF);
+ namelen = strlen(name);
+ if (namelen + sizeof(MEMFD_NAME_PREFIX) - 1 > NAME_MAX)
+ return (EINVAL);
+ if ((flags & ~(MFD_CLOEXEC | MFD_ALLOW_SEALING | MFD_HUGETLB |
+ MFD_HUGE_MASK)) != 0)
+ return (EINVAL);
+ /* HUGETLB set with no size specified. */
+ if ((flags & MFD_HUGETLB) != 0 && (flags & 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);
+
+ /* We've already validated that we're sufficiently sized. */
+ snprintf(memfd_name, NAME_MAX + 1, "%s%s", MEMFD_NAME_PREFIX, name);
+ oflags = O_RDWR;
+ shmflags = 0;
+ if ((flags & MFD_CLOEXEC) != 0)
+ oflags |= O_CLOEXEC;
+ if ((flags & MFD_ALLOW_SEALING) != 0)
+ shmflags |= SHM_ALLOW_SEALING;
+ return (__sys_shm_open2(SHM_ANON, oflags, 0, shmflags, memfd_name));
+}
Index: sys/compat/freebsd32/syscalls.master
===================================================================
--- sys/compat/freebsd32/syscalls.master
+++ sys/compat/freebsd32/syscalls.master
@@ -13,7 +13,7 @@
; case where the event exists, but we don't want auditing, the
; event should be #defined to AUE_NULL in audit_kevents.h.
; type one of STD, OBSOL, UNIMPL, COMPAT, COMPAT4, COMPAT6,
-; COMPAT7, COMPAT11, NODEF, NOARGS, NOPROTO, NOSTD
+; COMPAT7, COMPAT11, COMPAT12, NODEF, NOARGS, NOPROTO, NOSTD
; The COMPAT* options may be combined with one or more NO*
; options separated by '|' with no spaces (e.g. COMPAT|NOARGS)
; name pseudo-prototype of syscall routine
@@ -31,6 +31,7 @@
; COMPAT7 included on COMPAT_FREEBSD7 #ifdef (FreeBSD 7 compat)
; COMPAT10 included on COMPAT_FREEBSD10 #ifdef (FreeBSD 10 compat)
; COMPAT11 included on COMPAT_FREEBSD11 #ifdef (FreeBSD 11 compat)
+; COMPAT12 included on COMPAT_FREEBSD12 #ifdef (FreeBSD 12 compat)
; OBSOL obsolete, not included in system, only specifies name
; UNIMPL not implemented, placeholder only
; NOSTD implemented but as a lkm that can be statically
@@ -909,8 +910,8 @@
uint32_t length1, uint32_t length2); }
#endif
481 AUE_THR_KILL2 NOPROTO { int thr_kill2(pid_t pid, long id, int sig); }
-482 AUE_SHMOPEN NOPROTO { int shm_open(const char *path, int flags, \
- mode_t mode); }
+482 AUE_SHMOPEN COMPAT12|NOPROTO { int shm_open( \
+ const char *path, int flags, mode_t mode); }
483 AUE_SHMUNLINK NOPROTO { int shm_unlink(const char *path); }
484 AUE_NULL NOPROTO { int cpuset(cpusetid_t *setid); }
#ifdef PAD64_REQUIRED
@@ -1153,5 +1154,8 @@
570 AUE_SYSCTL STD { int freebsd32___sysctlbyname(const char *name, \
size_t namelen, void *old, uint32_t *oldlenp, \
void *new, size_t newlen); }
+571 AUE_SHMOPEN NOPROTO { int shm_open2( \
+ const char *path, int flags, mode_t mode, \
+ int shmflags, const char *name); }
; vim: syntax=off
Index: sys/kern/capabilities.conf
===================================================================
--- sys/kern/capabilities.conf
+++ sys/kern/capabilities.conf
@@ -655,6 +655,7 @@
## shm_open(2) is scoped so as to allow only access to new anonymous objects.
##
shm_open
+shm_open2
##
## Allow I/O-related file descriptors, subject to capability rights.
Index: sys/kern/syscalls.master
===================================================================
--- sys/kern/syscalls.master
+++ sys/kern/syscalls.master
@@ -2578,7 +2578,7 @@
int sig
);
}
-482 AUE_SHMOPEN STD {
+482 AUE_SHMOPEN COMPAT12 {
int shm_open(
_In_z_ const char *path,
int flags,
@@ -3194,6 +3194,15 @@
_In_reads_bytes_opt_(newlen) void *new,
size_t newlen);
}
+571 AUE_SHMOPEN STD {
+ int shm_open2(
+ _In_z_ const char *path,
+ int flags,
+ mode_t mode,
+ int shmflags,
+ _In_z_ const char *name
+ );
+ }
; Please copy any additions and changes to the following compatability tables:
; sys/compat/freebsd32/syscalls.master
Index: sys/kern/uipc_shm.c
===================================================================
--- sys/kern/uipc_shm.c
+++ sys/kern/uipc_shm.c
@@ -905,13 +905,15 @@
}
/* System calls. */
+#ifdef COMPAT_FREEBSD12
int
-sys_shm_open(struct thread *td, struct shm_open_args *uap)
+freebsd12_shm_open(struct thread *td, struct freebsd12_shm_open_args *uap)
{
return (kern_shm_open(td, uap->path, uap->flags | O_CLOEXEC, uap->mode,
NULL, F_SEAL_SEAL));
}
+#endif
int
sys_shm_unlink(struct thread *td, struct shm_unlink_args *uap)
@@ -1317,3 +1319,36 @@
CTLFLAG_RD | CTLFLAG_MPSAFE | CTLTYPE_OPAQUE,
NULL, 0, sysctl_posix_shm_list, "",
"POSIX SHM list");
+
+int
+kern_shm_open2(struct thread *td, const char *path, int flags, mode_t mode,
+ int shmflags, const char *name __unused)
+{
+ int initial_seals;
+
+ if ((shmflags & ~SHM_ALLOW_SEALING) != 0)
+ return (EINVAL);
+
+ initial_seals = F_SEAL_SEAL;
+ if ((shmflags & SHM_ALLOW_SEALING) != 0)
+ initial_seals &= ~F_SEAL_SEAL;
+ return (kern_shm_open(td, path, flags, 0, NULL, initial_seals));
+}
+
+/*
+ * This version of the shm_open() interface leaves CLOEXEC behavior up to the
+ * caller, and libc will enforce it for the traditional shm_open() call. This
+ * allows other consumers, like memfd_create(), to opt-in for CLOEXEC. This
+ * interface also includes a 'name' argument that is currently unused, but could
+ * potentially be exported later via some interface for debugging purposes.
+ * From the kernel's perspective, it is optional. Individual consumers like
+ * memfd_create() may require it in order to be compatible with other systems
+ * implementing the same function.
+ */
+int
+sys_shm_open2(struct thread *td, struct shm_open2_args *uap)
+{
+
+ return (kern_shm_open2(td, uap->path, uap->flags, uap->mode,
+ uap->shmflags, uap->name));
+}
Index: sys/sys/mman.h
===================================================================
--- sys/sys/mman.h
+++ sys/sys/mman.h
@@ -176,6 +176,36 @@
* Anonymous object constant for shm_open().
*/
#define SHM_ANON ((char *)1)
+
+/*
+ * shmflags for shm_open2()
+ */
+#define SHM_ALLOW_SEALING 0x00000001
+
+/*
+ * Flags for memfd_create().
+ */
+#define MFD_ALLOW_SEALING 0x00000001
+#define MFD_CLOEXEC 0x00000002
+
+/* UNSUPPORTED */
+#define MFD_HUGETLB 0x00000004
+
+#define MFD_HUGE_MASK 0xFC000000
+#define MFD_HUGE_SHIFT 26
+#define MFD_HUGE_64KB (16 << MFD_HUGE_SHIFT)
+#define MFD_HUGE_512KB (19 << MFD_HUGE_SHIFT)
+#define MFD_HUGE_1MB (20 << MFD_HUGE_SHIFT)
+#define MFD_HUGE_2MB (21 << MFD_HUGE_SHIFT)
+#define MFD_HUGE_8MB (23 << MFD_HUGE_SHIFT)
+#define MFD_HUGE_16MB (24 << MFD_HUGE_SHIFT)
+#define MFD_HUGE_32MB (25 << MFD_HUGE_SHIFT)
+#define MFD_HUGE_256MB (28 << MFD_HUGE_SHIFT)
+#define MFD_HUGE_512MB (29 << MFD_HUGE_SHIFT)
+#define MFD_HUGE_1GB (30 << MFD_HUGE_SHIFT)
+#define MFD_HUGE_2GB (31 << MFD_HUGE_SHIFT)
+#define MFD_HUGE_16GB (34 << MFD_HUGE_SHIFT)
+
#endif /* __BSD_VISIBLE */
/*
@@ -285,6 +315,9 @@
int shm_open(const char *, int, mode_t);
int shm_unlink(const char *);
#endif
+#if __BSD_VISIBLE
+int memfd_create(const char *, unsigned int);
+#endif
__END_DECLS
#endif /* !_KERNEL */
Index: sys/sys/syscallsubr.h
===================================================================
--- sys/sys/syscallsubr.h
+++ sys/sys/syscallsubr.h
@@ -251,6 +251,8 @@
struct timezone *tzp);
int kern_shm_open(struct thread *td, const char *userpath, int flags,
mode_t mode, struct filecaps *fcaps, int initial_seals);
+int kern_shm_open2(struct thread *td, const char *path, int flags,
+ mode_t mode, int shmflags, const char *name);
int kern_shmat(struct thread *td, int shmid, const void *shmaddr,
int shmflg);
int kern_shmctl(struct thread *td, int shmid, int cmd, void *buf,
Index: tests/sys/kern/Makefile
===================================================================
--- tests/sys/kern/Makefile
+++ tests/sys/kern/Makefile
@@ -9,6 +9,7 @@
ATF_TESTS_C+= kern_copyin
ATF_TESTS_C+= kern_descrip_test
ATF_TESTS_C+= kill_zombie
+ATF_TESTS_C+= memfd_test
ATF_TESTS_C+= ptrace_test
TEST_METADATA.ptrace_test+= timeout="15"
ATF_TESTS_C+= reaper
Index: tests/sys/kern/memfd_test.c
===================================================================
--- /dev/null
+++ tests/sys/kern/memfd_test.c
@@ -0,0 +1,276 @@
+/*-
+ * Copyright (c) 2019 Kyle Evans <kevans@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/fcntl.h>
+#include <sys/mman.h>
+
+#include <atf-c.h>
+#include <errno.h>
+#include <unistd.h>
+
+ATF_TC_WITHOUT_HEAD(basic);
+ATF_TC_BODY(basic, tc)
+{
+ int fd;
+ char buf[8];
+
+ ATF_REQUIRE((fd = memfd_create("...", 0)) != -1);
+
+ /* File size should be initially 0 */
+ ATF_REQUIRE(write(fd, buf, sizeof(buf)) == 0);
+
+ /* ftruncate(2) must succeed without seals */
+ ATF_REQUIRE(ftruncate(fd, sizeof(buf) - 1) == 0);
+
+ ATF_REQUIRE(write(fd, buf, sizeof(buf)) == sizeof(buf) - 1);
+
+ close(fd);
+}
+
+ATF_TC_WITHOUT_HEAD(cloexec);
+ATF_TC_BODY(cloexec, tc)
+{
+ int fd_nocl, fd_cl;
+
+ ATF_REQUIRE((fd_nocl = memfd_create("...", 0)) != -1);
+ ATF_REQUIRE((fd_cl = memfd_create("...", MFD_CLOEXEC)) != -1);
+
+ ATF_REQUIRE((fcntl(fd_nocl, F_GETFD) & FD_CLOEXEC) == 0);
+ ATF_REQUIRE((fcntl(fd_cl, F_GETFD) & FD_CLOEXEC) != 0);
+
+ close(fd_nocl);
+ close(fd_cl);
+}
+
+ATF_TC_WITHOUT_HEAD(disallowed_sealing);
+ATF_TC_BODY(disallowed_sealing, tc)
+{
+ int fd;
+
+ ATF_REQUIRE((fd = memfd_create("...", 0)) != -1);
+ ATF_REQUIRE(fcntl(fd, F_GET_SEALS) == F_SEAL_SEAL);
+ ATF_REQUIRE(fcntl(fd, F_ADD_SEALS, F_SEAL_WRITE) == -1);
+ ATF_REQUIRE(errno == EPERM);
+
+ close(fd);
+}
+
+#define BUF_SIZE 1024
+
+ATF_TC_WITHOUT_HEAD(write_seal);
+ATF_TC_BODY(write_seal, tc)
+{
+ int fd;
+ char *addr, buf[BUF_SIZE];
+
+ ATF_REQUIRE((fd = memfd_create("...", MFD_ALLOW_SEALING)) != -1);
+ ATF_REQUIRE(ftruncate(fd, BUF_SIZE) == 0);
+
+ /* Write once, then we'll seal it and try again */
+ ATF_REQUIRE(write(fd, buf, BUF_SIZE) == BUF_SIZE);
+ ATF_REQUIRE(lseek(fd, 0, SEEK_SET) == 0);
+
+ addr = mmap(0, BUF_SIZE, (PROT_READ | PROT_WRITE), MAP_PRIVATE, fd, 0);
+ ATF_REQUIRE(addr != MAP_FAILED);
+ ATF_REQUIRE(munmap(addr, BUF_SIZE) == 0);
+
+ ATF_REQUIRE(fcntl(fd, F_ADD_SEALS, F_SEAL_WRITE) == 0);
+
+ ATF_REQUIRE(write(fd, buf, BUF_SIZE) == -1);
+ ATF_REQUIRE(errno == EPERM);
+
+ ATF_REQUIRE(mmap(0, BUF_SIZE, (PROT_READ | PROT_WRITE), MAP_SHARED,
+ fd, 0) == MAP_FAILED);
+ ATF_REQUIRE(errno == EPERM);
+
+ close(fd);
+}
+
+ATF_TC_WITHOUT_HEAD(mmap_write_seal);
+ATF_TC_BODY(mmap_write_seal, tc)
+{
+ int fd;
+ char *addr, *paddr, *raddr;
+
+ ATF_REQUIRE((fd = memfd_create("...", MFD_ALLOW_SEALING)) != -1);
+ ATF_REQUIRE(ftruncate(fd, BUF_SIZE) == 0);
+
+ /* Map it, both shared and privately */
+ addr = mmap(0, BUF_SIZE, (PROT_READ | PROT_WRITE), MAP_SHARED, fd, 0);
+ ATF_REQUIRE(addr != MAP_FAILED);
+ paddr = mmap(0, BUF_SIZE, (PROT_READ | PROT_WRITE), MAP_PRIVATE, fd, 0);
+ ATF_REQUIRE(paddr != MAP_FAILED);
+ raddr = mmap(0, BUF_SIZE, PROT_READ, MAP_SHARED, fd, 0);
+ ATF_REQUIRE(raddr != MAP_FAILED);
+
+ /* Now try to seal it before unmapping */
+ ATF_REQUIRE(fcntl(fd, F_ADD_SEALS, F_SEAL_WRITE) == -1);
+ ATF_REQUIRE(errno == EBUSY);
+
+ ATF_REQUIRE(munmap(addr, BUF_SIZE) == 0);
+
+ ATF_REQUIRE(fcntl(fd, F_ADD_SEALS, F_SEAL_WRITE) == 0);
+
+ ATF_REQUIRE(munmap(paddr, BUF_SIZE) == 0);
+ ATF_REQUIRE(munmap(raddr, BUF_SIZE) == 0);
+ ATF_REQUIRE(mmap(0, BUF_SIZE, (PROT_READ | PROT_WRITE), MAP_SHARED,
+ fd, 0) == MAP_FAILED);
+ ATF_REQUIRE(errno == EPERM);
+ paddr = mmap(0, BUF_SIZE, (PROT_READ | PROT_WRITE), MAP_PRIVATE, fd, 0);
+ ATF_REQUIRE(paddr != MAP_FAILED);
+ raddr = mmap(0, BUF_SIZE, PROT_READ, MAP_SHARED, fd, 0);
+ ATF_REQUIRE(raddr != MAP_FAILED);
+ ATF_REQUIRE(munmap(raddr, BUF_SIZE) == 0);
+ ATF_REQUIRE(munmap(paddr, BUF_SIZE) == 0);
+
+ close(fd);
+}
+
+static int
+memfd_truncate_test(int initial_size, int dest_size, int seals)
+{
+ int err, fd;
+
+ ATF_REQUIRE((fd = memfd_create("...", MFD_ALLOW_SEALING)) != -1);
+ ATF_REQUIRE(ftruncate(fd, initial_size) == 0);
+
+ ATF_REQUIRE(fcntl(fd, F_ADD_SEALS, seals) == 0);
+
+ err = ftruncate(fd, dest_size);
+ if (err != 0)
+ err = errno;
+ close(fd);
+ return (err);
+}
+
+ATF_TC_WITHOUT_HEAD(truncate_seals);
+ATF_TC_BODY(truncate_seals, tc)
+{
+
+ ATF_REQUIRE(memfd_truncate_test(4, 8, F_SEAL_GROW) == EPERM);
+ ATF_REQUIRE(memfd_truncate_test(8, 4, F_SEAL_SHRINK) == EPERM);
+ ATF_REQUIRE(memfd_truncate_test(8, 4, F_SEAL_GROW) == 0);
+ ATF_REQUIRE(memfd_truncate_test(4, 8, F_SEAL_SHRINK) == 0);
+
+ ATF_REQUIRE(memfd_truncate_test(4, 8, F_SEAL_GROW | F_SEAL_SHRINK) ==
+ EPERM);
+ ATF_REQUIRE(memfd_truncate_test(8, 4, F_SEAL_GROW | F_SEAL_SHRINK) ==
+ EPERM);
+ ATF_REQUIRE(memfd_truncate_test(4, 4, F_SEAL_GROW | F_SEAL_SHRINK) ==
+ 0);
+}
+
+ATF_TC_WITHOUT_HEAD(get_seals);
+ATF_TC_BODY(get_seals, tc)
+{
+ int fd;
+ int seals;
+
+ ATF_REQUIRE((fd = memfd_create("...", MFD_ALLOW_SEALING)) != -1);
+ ATF_REQUIRE(fcntl(fd, F_GET_SEALS) == 0);
+
+ ATF_REQUIRE(fcntl(fd, F_ADD_SEALS, F_SEAL_WRITE | F_SEAL_GROW) == 0);
+ seals = fcntl(fd, F_GET_SEALS);
+ ATF_REQUIRE(seals == (F_SEAL_WRITE | F_SEAL_GROW));
+
+ close(fd);
+}
+
+ATF_TC_WITHOUT_HEAD(dup_seals);
+ATF_TC_BODY(dup_seals, tc)
+{
+ char buf[8];
+ int fd, fdx;
+ int seals;
+
+ ATF_REQUIRE((fd = memfd_create("...", MFD_ALLOW_SEALING)) != -1);
+ ATF_REQUIRE((fdx = dup(fd)) != -1);
+ ATF_REQUIRE(fcntl(fd, F_GET_SEALS) == 0);
+
+ ATF_REQUIRE(fcntl(fd, F_ADD_SEALS, F_SEAL_WRITE | F_SEAL_GROW) == 0);
+ seals = fcntl(fd, F_GET_SEALS);
+ ATF_REQUIRE(seals == (F_SEAL_WRITE | F_SEAL_GROW));
+
+ seals = fcntl(fdx, F_GET_SEALS);
+ ATF_REQUIRE(seals == (F_SEAL_WRITE | F_SEAL_GROW));
+
+ /* Make sure the seal's actually being applied at the inode level */
+ ATF_REQUIRE(write(fdx, buf, sizeof(buf)) == -1);
+ ATF_REQUIRE(errno == EPERM);
+
+ ATF_REQUIRE(mmap(0, BUF_SIZE, (PROT_READ | PROT_WRITE), MAP_SHARED,
+ fdx, 0) == MAP_FAILED);
+ ATF_REQUIRE(errno == EPERM);
+
+ close(fd);
+ close(fdx);
+}
+
+ATF_TC_WITHOUT_HEAD(immutable_seals);
+ATF_TC_BODY(immutable_seals, tc)
+{
+ int fd;
+
+ ATF_REQUIRE((fd = memfd_create("...", MFD_ALLOW_SEALING)) != -1);
+
+ ATF_REQUIRE(fcntl(fd, F_ADD_SEALS, F_SEAL_SEAL) == 0);
+ ATF_REQUIRE(fcntl(fd, F_ADD_SEALS, F_SEAL_GROW) == -1);
+ ATF_REQUIRE_MSG(errno == EPERM,
+ "Added unique grow seal after restricting seals");
+
+ close(fd);
+
+ /*
+ * Also check that adding a seal that already exists really doesn't
+ * do anything once we're sealed.
+ */
+ ATF_REQUIRE((fd = memfd_create("...", MFD_ALLOW_SEALING)) != -1);
+
+ ATF_REQUIRE(fcntl(fd, F_ADD_SEALS, F_SEAL_GROW | F_SEAL_SEAL) == 0);
+ ATF_REQUIRE(fcntl(fd, F_ADD_SEALS, F_SEAL_GROW) == -1);
+ ATF_REQUIRE_MSG(errno == EPERM,
+ "Added duplicate grow seal after restricting seals");
+ close(fd);
+}
+
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, basic);
+ ATF_TP_ADD_TC(tp, cloexec);
+ ATF_TP_ADD_TC(tp, disallowed_sealing);
+ ATF_TP_ADD_TC(tp, write_seal);
+ ATF_TP_ADD_TC(tp, mmap_write_seal);
+ ATF_TP_ADD_TC(tp, truncate_seals);
+ ATF_TP_ADD_TC(tp, get_seals);
+ ATF_TP_ADD_TC(tp, dup_seals);
+ ATF_TP_ADD_TC(tp, immutable_seals);
+ return (atf_no_error());
+}
Index: usr.bin/kdump/kdump.c
===================================================================
--- usr.bin/kdump/kdump.c
+++ usr.bin/kdump/kdump.c
@@ -1246,7 +1246,8 @@
ip++;
narg--;
break;
- case SYS_shm_open:
+#ifdef SYS_freebsd12_shm_open
+ case SYS_freebsd12_shm_open:
print_number(ip, narg, c);
putchar(',');
print_mask_arg(sysdecode_open_flags, ip[0]);
@@ -1255,6 +1256,7 @@
ip += 2;
narg -= 2;
break;
+#endif
case SYS_minherit:
print_number(ip, narg, c);
print_number(ip, narg, c);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Apr 28, 6:40 AM (17 h, 9 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
32256251
Default Alt Text
D21393.id62537.diff (24 KB)
Attached To
Mode
D21393: [3/3] Add linux-compatible memfd_create
Attached
Detach File
Event Timeline
Log In to Comment