Page MenuHomeFreeBSD

D21393.id62537.diff
No OneTemporary

D21393.id62537.diff

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

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)

Event Timeline