diff options
author | Claudio Jeker <claudio@cvs.openbsd.org> | 2021-06-29 07:55:30 +0000 |
---|---|---|
committer | Claudio Jeker <claudio@cvs.openbsd.org> | 2021-06-29 07:55:30 +0000 |
commit | 26bd1341c023f571fc1825fbae68003a263de2ab (patch) | |
tree | 24000035da78d1d21cdf824188cf1f7ed355606d /sys/kern/kern_unveil.c | |
parent | 18206aaa9ce27202c769d4bcaae795d8a5e1ac7c (diff) |
Adjust unveil_find_cover() to return -1 if the root vnode is passed in.
This helps unveil_add_vnode() to properly re-evaluate unveils when
"/" is added to the list.
Because of this adjust unveil_covered() to check for the root as well
so that in that case the unveil uv is returned instead of NULL. Traversing
up from the root returns the root. This check is not really needed since
namei has its own root check and shortcuts for root vnodes.
OK semarie@
Diffstat (limited to 'sys/kern/kern_unveil.c')
-rw-r--r-- | sys/kern/kern_unveil.c | 25 |
1 files changed, 16 insertions, 9 deletions
diff --git a/sys/kern/kern_unveil.c b/sys/kern/kern_unveil.c index 536208c6678..b541c9ca2f7 100644 --- a/sys/kern/kern_unveil.c +++ b/sys/kern/kern_unveil.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_unveil.c,v 1.44 2021/06/24 07:21:59 semarie Exp $ */ +/* $OpenBSD: kern_unveil.c,v 1.45 2021/06/29 07:55:29 claudio Exp $ */ /* * Copyright (c) 2017-2019 Bob Beck <beck@openbsd.org> @@ -274,7 +274,7 @@ unveil_copy(struct process *parent, struct process *child) /* * Walk up from vnode dp, until we find a matching unveil, or the root vnode - * returns -1 if no unveil to be found above dp. + * returns -1 if no unveil to be found above dp or if dp is the root vnode. */ ssize_t unveil_find_cover(struct vnode *dp, struct proc *p) @@ -287,7 +287,7 @@ unveil_find_cover(struct vnode *dp, struct proc *p) root = p->p_fd->fd_rdir ? p->p_fd->fd_rdir : rootvnode; vp = dp; - do { + while (vp != root) { struct componentname cn = { .cn_nameiop = LOOKUP, .cn_flags = ISLASTCN | ISDOTDOT | RDONLY, @@ -343,7 +343,7 @@ unveil_find_cover(struct vnode *dp, struct proc *p) } vp = parent; parent = NULL; - } while (vp != root); + } return ret; } @@ -666,13 +666,20 @@ unveil_flagmatch(struct nameidata *ni, u_char flags) return 1; } - +/* + * When traversing up towards the root figure out the proper unveil for + * the parent directory. + */ struct unveil * -unveil_covered(struct unveil *uv, struct vnode *dvp, struct process *pr) { +unveil_covered(struct unveil *uv, struct vnode *dvp, struct proc *p) +{ if (uv && uv->uv_vp == dvp) { + /* if at the root, chrooted or not, return the current uv */ + if (dvp == (p->p_fd->fd_rdir ? p->p_fd->fd_rdir : rootvnode)) + return uv; if (uv->uv_cover >=0) { - KASSERT(uv->uv_cover < pr->ps_uvvcount); - return &pr->ps_uvpaths[uv->uv_cover]; + KASSERT(uv->uv_cover < p->p_p->ps_uvvcount); + return &p->p_p->ps_uvpaths[uv->uv_cover]; } return NULL; } @@ -758,7 +765,7 @@ unveil_check_component(struct proc *p, struct nameidata *ni, struct vnode *dp) /* * adjust unveil match as necessary */ - uv = unveil_covered(ni->ni_unveil_match, dp, pr); + uv = unveil_covered(ni->ni_unveil_match, dp, p); /* clear the match when we DOTDOT above it */ if (ni->ni_unveil_match && |