From: claudio Date: Sun, 9 Jan 2022 10:28:07 +0000 (+0000) Subject: Add an UNVEIL_USERSET flag which is set when a unveil node is added via X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=2abaea44e751d3c2558b628869322dd0ce33b3eb;p=openbsd Add an UNVEIL_USERSET flag which is set when a unveil node is added via unveil(2). It is not set for nodes that are added as a result of a file being added via unveil(2). Use this flag to test if backtracking should be done or not. Also introduce UNVEIL_MASK which checks if any user flags are set and is used to properly return EACCES vs ENOENT. This fixes a problem where unveil("/", "r") & unveil("/usr/bin/id", "rx") cause an error when read accessing "/usr/bin". It also makes sure that unveil(path, "") will return ENOENT for any access of anything under path. Reported by and OK semarie@ --- diff --git a/sys/kern/kern_unveil.c b/sys/kern/kern_unveil.c index 801c210c113..50a043e63d5 100644 --- a/sys/kern/kern_unveil.c +++ b/sys/kern/kern_unveil.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_unveil.c,v 1.51 2021/09/09 13:02:36 claudio Exp $ */ +/* $OpenBSD: kern_unveil.c,v 1.52 2022/01/09 10:28:07 claudio Exp $ */ /* * Copyright (c) 2017-2019 Bob Beck @@ -345,7 +345,7 @@ unveil_parsepermissions(const char *permissions, u_char *perms) size_t i = 0; char c; - *perms = 0; + *perms = UNVEIL_USERSET; while ((c = permissions[i++]) != '\0') { switch (c) { case 'r': @@ -708,11 +708,13 @@ unveil_check_final(struct proc *p, struct nameidata *ni) if (ni->ni_vp != NULL && ni->ni_vp->v_type == VDIR) { /* We are matching a directory terminal component */ uv = unveil_lookup(ni->ni_vp, pr, NULL); - if (uv == NULL) { + if (uv == NULL || (uv->uv_flags & UNVEIL_USERSET) == 0) { #ifdef DEBUG_UNVEIL printf("unveil: %s(%d) no match for vnode %p\n", pr->ps_comm, pr->ps_pid, ni->ni_vp); #endif + if (uv != NULL) + ni->ni_unveil_match = uv; goto done; } if (!unveil_flagmatch(ni, uv->uv_flags)) { @@ -722,7 +724,7 @@ unveil_check_final(struct proc *p, struct nameidata *ni) pr->ps_comm, pr->ps_pid, ni->ni_vp); #endif pr->ps_acflag |= AUNVEIL; - if (uv->uv_flags & UNVEIL_USERSET) + if (uv->uv_flags & UNVEIL_MASK) return EACCES; else return ENOENT; @@ -764,12 +766,15 @@ unveil_check_final(struct proc *p, struct nameidata *ni) #endif /* * If dir has user set restrictions fail with - * EACCES. Otherwise, use any covering match - * that we found above this dir. + * EACCES or ENOENT. Otherwise, use any covering + * match that we found above this dir. */ if (uv->uv_flags & UNVEIL_USERSET) { pr->ps_acflag |= AUNVEIL; - return EACCES; + if (uv->uv_flags & UNVEIL_MASK) + return EACCES; + else + return ENOENT; } /* start backtrack from this node */ ni->ni_unveil_match = uv; @@ -820,7 +825,10 @@ done: pr->ps_comm, pr->ps_pid, uv->uv_vp); #endif pr->ps_acflag |= AUNVEIL; - return EACCES; + if (uv->uv_flags & UNVEIL_MASK) + return EACCES; + else + return ENOENT; } #ifdef DEBUG_UNVEIL printf("unveil: %s(%d) check cover for vnode %p, uv_cover %zd\n", diff --git a/sys/sys/namei.h b/sys/sys/namei.h index 7c7e7c937ca..7e52ed0284e 100644 --- a/sys/sys/namei.h +++ b/sys/sys/namei.h @@ -1,4 +1,4 @@ -/* $OpenBSD: namei.h,v 1.48 2021/09/02 12:35:23 claudio Exp $ */ +/* $OpenBSD: namei.h,v 1.49 2022/01/09 10:28:07 claudio Exp $ */ /* $NetBSD: namei.h,v 1.11 1996/02/09 18:25:20 christos Exp $ */ /* @@ -268,6 +268,7 @@ struct nchstats { #define UNVEIL_WRITE 0x02 #define UNVEIL_CREATE 0x04 #define UNVEIL_EXEC 0x08 -#define UNVEIL_USERSET 0x0F +#define UNVEIL_USERSET 0x10 +#define UNVEIL_MASK 0x0F #endif /* !_SYS_NAMEI_H_ */