summaryrefslogtreecommitdiff
path: root/sys/kern
diff options
context:
space:
mode:
authorTed Unangst <tedu@cvs.openbsd.org>2020-01-26 04:28:19 +0000
committerTed Unangst <tedu@cvs.openbsd.org>2020-01-26 04:28:19 +0000
commitf5c18e2f48a884a57cc75cb6facefce5d36ae8a5 (patch)
tree8c86beb3b5872e7e5fe8a3f099fe8d75d51ab086 /sys/kern
parentce600af14e882093a73a516f601c1daded11c224 (diff)
add a new __tmpfd system call that creates a new unnamed file in /tmp.
intended for shm/fd passing, but for programs that may otherwise like filesystem access. ok beck deraadt kettenis
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/syscalls.master4
-rw-r--r--sys/kern/vfs_syscalls.c86
2 files changed, 87 insertions, 3 deletions
diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master
index 3d823d74e0b..984ddb42193 100644
--- a/sys/kern/syscalls.master
+++ b/sys/kern/syscalls.master
@@ -1,4 +1,4 @@
-; $OpenBSD: syscalls.master,v 1.202 2020/01/21 15:20:47 visa Exp $
+; $OpenBSD: syscalls.master,v 1.203 2020/01/26 04:28:18 tedu Exp $
; $NetBSD: syscalls.master,v 1.32 1996/04/23 10:24:21 mycroft Exp $
; @(#)syscalls.master 8.2 (Berkeley) 1/13/94
@@ -307,7 +307,7 @@
161 STD { int sys_getfh(const char *fname, fhandle_t *fhp); }
162 OBSOL ogetdomainname
163 OBSOL osetdomainname
-164 UNIMPL ouname
+164 STD { int sys___tmpfd(int flags); }
165 STD { int sys_sysarch(int op, void *parms); }
166 UNIMPL
167 UNIMPL
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
index 6a3de4e47fe..88d61acb322 100644
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vfs_syscalls.c,v 1.340 2020/01/18 08:40:19 visa Exp $ */
+/* $OpenBSD: vfs_syscalls.c,v 1.341 2020/01/26 04:28:18 tedu Exp $ */
/* $NetBSD: vfs_syscalls.c,v 1.71 1996/04/23 10:29:02 mycroft Exp $ */
/*
@@ -1222,6 +1222,90 @@ out:
}
/*
+ * Open a new created file (in /tmp) suitable for mmaping.
+ */
+int
+sys___tmpfd(struct proc *p, void *v, register_t *retval)
+{
+ struct sys___tmpfd_args /* {
+ syscallarg(int) flags;
+ } */ *uap = v;
+ struct filedesc *fdp = p->p_fd;
+ struct file *fp;
+ struct vnode *vp;
+ int oflags = SCARG(uap, flags);
+ int flags, cloexec, cmode;
+ int indx, error;
+ unsigned int i;
+ struct nameidata nd;
+ char path[64];
+ static const char *letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-";
+
+ /* most flags are hardwired */
+ oflags = O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW | (oflags & O_CLOEXEC);
+
+ cloexec = (oflags & O_CLOEXEC) ? UF_EXCLOSE : 0;
+
+ fdplock(fdp);
+ if ((error = falloc(p, &fp, &indx)) != 0)
+ goto out;
+ fdpunlock(fdp);
+
+ flags = FFLAGS(oflags);
+
+ arc4random_buf(path, sizeof(path));
+ memcpy(path, "/tmp/", 5);
+ for (i = 5; i < sizeof(path) - 1; i++)
+ path[i] = letters[(unsigned char)path[i] & 63];
+ path[sizeof(path)-1] = 0;
+
+ cmode = 0600;
+ NDINITAT(&nd, 0, KERNELPATH, UIO_SYSSPACE, AT_FDCWD, path, p);
+ if ((error = vn_open(&nd, flags, cmode)) != 0) {
+ fdplock(fdp);
+ if (error == ERESTART)
+ error = EINTR;
+ fdremove(fdp, indx);
+ closef(fp, p);
+ goto out;
+ }
+ vp = nd.ni_vp;
+ fp->f_flag = flags & FMASK;
+ fp->f_type = DTYPE_VNODE;
+ fp->f_ops = &vnops;
+ fp->f_data = vp;
+ VOP_UNLOCK(vp);
+ *retval = indx;
+ fdplock(fdp);
+ fdinsert(fdp, indx, cloexec, fp);
+ FRELE(fp, p);
+
+ /* unlink it */
+ /* XXX
+ * there is a wee race here, although it is mostly inconsequential.
+ * perhaps someday we can create a file like object without a name...
+ */
+ NDINITAT(&nd, DELETE, KERNELPATH | LOCKPARENT | LOCKLEAF, UIO_SYSSPACE,
+ AT_FDCWD, path, p);
+ if ((error = namei(&nd)) != 0) {
+ printf("can't unlink temp file! %d\n", error);
+ error = 0;
+ } else {
+ vp = nd.ni_vp;
+ uvm_vnp_uncache(vp);
+ error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
+ if (error) {
+ printf("error removing vop: %d\n", error);
+ error = 0;
+ }
+ }
+
+out:
+ fdpunlock(fdp);
+ return (error);
+}
+
+/*
* Get file handle system call
*/
int