Page MenuHomeFreeBSD

D21393.id62169.diff
No OneTemporary

D21393.id62169.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/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
@@ -234,6 +235,7 @@
listen.2 \
lseek.2 \
madvise.2 \
+ memfd_create.2 \
mincore.2 \
minherit.2 \
mkdir.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 {
@@ -916,6 +917,7 @@
_setuid;
__sys_setuid;
_shm_open;
+ _shm_open2;
__sys_shm_open;
_shm_unlink;
__sys_shm_unlink;
Index: lib/libc/sys/memfd_create.2
===================================================================
--- /dev/null
+++ lib/libc/sys/memfd_create.2
@@ -0,0 +1,107 @@
+.\" SPDX-License-Identifier: BSD-2-Clause
+.\"
+.\" Copyright (c) 2019 Kyle Evans <kevans@FreeBSD.org>
+.\"
+.\" 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.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd August 24, 2019
+.Dt MEMFD_CREATE 2
+.Os
+.Sh NAME
+.Nm memfd_create
+.Nd Create anonymous shared memory object
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/mman.h
+.Ft int
+.Fo memfd_create
+.Fa "const char *name"
+.Fa "unsigned int flags"
+.Fc
+.Sh DESCRIPTION
+The
+.Fn memfd_create
+system call
+creates an anonymous shared memory object, identical to that created by
+.Xr shm_open 2
+when
+.Dv SHM_ANON
+is specified.
+Newly created objects start off with a size of zero.
+The size of the object can be adjusted via
+.Xr ftruncate 2 .
+.Pp
+The
+.Fa name
+argument is currently unused.
+The following
+.Fa flags
+may be specified:
+.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 .
+.It Dv MFD_HUGETLB
+This flag is currently unsupported.
+.El
+.Sh RETURN VALUES
+If successful,
+.Fn memfd_create
+returns the file descriptor for the opened file; otherwise the value \-1 is
+returned and the global variable
+.Va errno
+is set to indicate the error.
+.Fn memfd_
+.Sh ERRORS
+In addition to the errors returned by
+.Xr shm_open 2 ,
+.Fn memfd_create
+will return
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Any flags not listed above were specified.
+.It Bq Er ENOSYS
+.Dv MFD_HUGETLB
+has been specified, and this system does not support forced hugetlb mappings.
+.El
+.Sh SEE ALSO
+.Xr fcntl 2 ,
+.Xr ftruncate 2 ,
+.Xr shm_open 2
+.Sh STANDARDS
+The
+.Fn memfd_create
+system call is expected to be compatible with the Linux system call of
+the same name.
+.Sh HISTORY
+The
+.Fn memfd_create
+function appeared in
+.Fx 13.0 .
Index: lib/libc/sys/shm_open.c
===================================================================
--- /dev/null
+++ lib/libc/sys/shm_open.c
@@ -0,0 +1,99 @@
+/*
+ * 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 <unistd.h>
+
+#include <stdio.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
+
+extern int _shm_open2(const char *path, int flags, mode_t mode,
+ int shmflags);
+
+int
+shm_open(const char *path, int flags, mode_t mode)
+{
+
+ if (__getosreldate() >= SHM_OPEN2_OSREL)
+ return (_shm_open2(path, flags | O_CLOEXEC, mode, 0));
+
+ /*
+ * 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 currently unused. Linux exposes it in linprocfs for
+ * debugging purposes only, but our kernel currently will not do the same.
+ */
+int
+memfd_create(const char *path __unused, unsigned int flags)
+{
+ int oflags, shmflags;
+
+ 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);
+
+ oflags = O_RDWR;
+ shmflags = 0;
+ if ((flags & MFD_CLOEXEC) != 0)
+ oflags |= O_CLOEXEC;
+ if ((flags & MFD_ALLOW_SEALING) != 0)
+ shmflags |= SHM_ALLOW_SEALING;
+ return (_shm_open2(SHM_ANON, oflags, 0, shmflags));
+}
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); }
; 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,14 @@
_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
+ );
+ }
; 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
@@ -904,13 +904,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)
@@ -1316,3 +1318,26 @@
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)
+{
+ 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));
+}
+
+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));
+}
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);
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());
+}

File Metadata

Mime Type
text/plain
Expires
Wed, Apr 29, 2:11 PM (9 h, 14 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
32351134
Default Alt Text
D21393.id62169.diff (22 KB)

Event Timeline