From dd490a11d064b10ac8c098e27515b9150ef4c257 Mon Sep 17 00:00:00 2001 From: claudio Date: Fri, 16 Jul 2021 07:59:38 +0000 Subject: [PATCH] Remove the unveil current directory pointer from struct process. Instead pass in the vnode to unveil_start_relative() like it is done for *at() syscalls. This fixes an issue with fchdir() that actually did not correctly reset this pointer when changing the working directory. OK beck@ --- sys/kern/kern_unveil.c | 47 +++++++---------------------------------- sys/kern/vfs_lookup.c | 5 ++--- sys/kern/vfs_syscalls.c | 4 +--- sys/sys/proc.h | 3 +-- 4 files changed, 12 insertions(+), 47 deletions(-) diff --git a/sys/kern/kern_unveil.c b/sys/kern/kern_unveil.c index 6e118966ade..51610c4e436 100644 --- a/sys/kern/kern_unveil.c +++ b/sys/kern/kern_unveil.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_unveil.c,v 1.47 2021/07/15 06:57:02 claudio Exp $ */ +/* $OpenBSD: kern_unveil.c,v 1.48 2021/07/16 07:59:38 claudio Exp $ */ /* * Copyright (c) 2017-2019 Bob Beck @@ -198,7 +198,6 @@ unveil_destroy(struct process *ps) sizeof(struct unveil)); ps->ps_uvvcount = 0; ps->ps_uvpaths = NULL; - ps->ps_uvpcwd = NULL; } void @@ -237,9 +236,6 @@ unveil_copy(struct process *parent, struct process *child) to->uv_cover = from->uv_cover; } child->ps_uvvcount = parent->ps_uvvcount; - if (parent->ps_uvpcwd) - child->ps_uvpcwd = child->ps_uvpaths + - (parent->ps_uvpcwd - parent->ps_uvpaths); child->ps_uvdone = parent->ps_uvdone; } @@ -541,15 +537,6 @@ unveil_add(struct proc *p, struct nameidata *ndp, const char *permissions) #endif done: - pr->ps_uvpcwd = unveil_lookup(p->p_fd->fd_cdir, pr, NULL); - if (pr->ps_uvpcwd == NULL) { - ssize_t i; - - i = unveil_find_cover(p->p_fd->fd_cdir, p); - if (i >= 0) - pr->ps_uvpcwd = &pr->ps_uvpaths[i]; - } - return ret; } @@ -642,36 +629,18 @@ unveil_start_relative(struct proc *p, struct nameidata *ni, struct vnode *dp) { struct process *pr = p->p_p; struct unveil *uv = NULL; + ssize_t uvi; if (pr->ps_uvpaths == NULL) return; - if (dp != NULL) { - ssize_t uvi; - /* - * XXX - * This is a non AT_FDCWD relative lookup starting - * from a file descriptor. As such, we can't use the - * saved current working directory unveil. We walk up - * and find what we are covered by. - */ - uv = unveil_lookup(dp, pr, NULL); - if (uv == NULL) { - uvi = unveil_find_cover(dp, p); - if (uvi >= 0) { - KASSERT(uvi < pr->ps_uvvcount); - uv = &pr->ps_uvpaths[uvi]; - } + uv = unveil_lookup(dp, pr, NULL); + if (uv == NULL) { + uvi = unveil_find_cover(dp, p); + if (uvi >= 0) { + KASSERT(uvi < pr->ps_uvvcount); + uv = &pr->ps_uvpaths[uvi]; } - } else { - /* - * Check saved cwd unveil match. - * - * Since ps_uvpcwd is set on chdir (UNVEIL_READ) we - * don't need to go up any further as in the above - * case. - */ - uv = pr->ps_uvpcwd; } /* diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c index 34345bbb417..94943dad1e1 100644 --- a/sys/kern/vfs_lookup.c +++ b/sys/kern/vfs_lookup.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vfs_lookup.c,v 1.84 2021/03/20 11:26:07 semarie Exp $ */ +/* $OpenBSD: vfs_lookup.c,v 1.85 2021/07/16 07:59:38 claudio Exp $ */ /* $NetBSD: vfs_lookup.c,v 1.17 1996/02/09 19:00:59 christos Exp $ */ /* @@ -213,7 +213,7 @@ namei(struct nameidata *ndp) } else if (ndp->ni_dirfd == AT_FDCWD) { dp = fdp->fd_cdir; vref(dp); - unveil_start_relative(p, ndp, NULL); + unveil_start_relative(p, ndp, dp); unveil_check_component(p, ndp, dp); } else { struct file *fp = fd_getfile(fdp, ndp->ni_dirfd); @@ -523,7 +523,6 @@ dirloop: * Handle "..": two special cases. * 1. If at root directory (e.g. after chroot) * or at absolute root directory - * or we are under unveil restrictions * then ignore it so can't get out. * 2. If this vnode is the root of a mounted * filesystem, then replace it with the diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index e2681bb8010..3a5db48992e 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vfs_syscalls.c,v 1.351 2021/07/08 13:33:05 claudio Exp $ */ +/* $OpenBSD: vfs_syscalls.c,v 1.352 2021/07/16 07:59:38 claudio Exp $ */ /* $NetBSD: vfs_syscalls.c,v 1.71 1996/04/23 10:29:02 mycroft Exp $ */ /* @@ -339,7 +339,6 @@ checkdirs(struct vnode *olddp) vref(newdp); fdp->fd_rdir = newdp; } - pr->ps_uvpcwd = NULL; } if (rootvnode == olddp) { free_count++; @@ -791,7 +790,6 @@ sys_chdir(struct proc *p, void *v, register_t *retval) nd.ni_unveil = UNVEIL_READ; if ((error = change_dir(&nd, p)) != 0) return (error); - p->p_p->ps_uvpcwd = nd.ni_unveil_match; old_cdir = fdp->fd_cdir; fdp->fd_cdir = nd.ni_vp; vrele(old_cdir); diff --git a/sys/sys/proc.h b/sys/sys/proc.h index 15459cc3db7..4dbc097f242 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -1,4 +1,4 @@ -/* $OpenBSD: proc.h,v 1.313 2021/06/15 18:42:23 claudio Exp $ */ +/* $OpenBSD: proc.h,v 1.314 2021/07/16 07:59:38 claudio Exp $ */ /* $NetBSD: proc.h,v 1.44 1996/04/22 01:23:21 christos Exp $ */ /*- @@ -229,7 +229,6 @@ struct process { u_int64_t ps_wxcounter; struct unveil *ps_uvpaths; /* unveil vnodes and names */ - struct unveil *ps_uvpcwd; /* pointer to unveil of cwd, NULL if none */ ssize_t ps_uvvcount; /* count of unveil vnodes held */ size_t ps_uvncount; /* count of unveil names allocated */ int ps_uvdone; /* no more unveil is permitted */ -- 2.20.1