diff options
author | Ted Unangst <tedu@cvs.openbsd.org> | 2020-01-26 04:28:19 +0000 |
---|---|---|
committer | Ted Unangst <tedu@cvs.openbsd.org> | 2020-01-26 04:28:19 +0000 |
commit | f5c18e2f48a884a57cc75cb6facefce5d36ae8a5 (patch) | |
tree | 8c86beb3b5872e7e5fe8a3f099fe8d75d51ab086 /sys/kern | |
parent | ce600af14e882093a73a516f601c1daded11c224 (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.master | 4 | ||||
-rw-r--r-- | sys/kern/vfs_syscalls.c | 86 |
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 |