Remove the unveil current directory pointer from struct process. Instead
authorclaudio <claudio@openbsd.org>
Fri, 16 Jul 2021 07:59:38 +0000 (07:59 +0000)
committerclaudio <claudio@openbsd.org>
Fri, 16 Jul 2021 07:59:38 +0000 (07:59 +0000)
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
sys/kern/vfs_lookup.c
sys/kern/vfs_syscalls.c
sys/sys/proc.h

index 6e11896..51610c4 100644 (file)
@@ -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 <beck@openbsd.org>
@@ -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;
        }
 
        /*
index 34345bb..94943da 100644 (file)
@@ -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
index e2681bb..3a5db48 100644 (file)
@@ -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);
index 15459cc..4dbc097 100644 (file)
@@ -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 */