-/* $OpenBSD: kern_unveil.c,v 1.52 2022/01/09 10:28:07 claudio Exp $ */
+/* $OpenBSD: kern_unveil.c,v 1.53 2022/01/11 07:31:50 semarie Exp $ */
/*
* Copyright (c) 2017-2019 Bob Beck <beck@openbsd.org>
};
/* #define DEBUG_UNVEIL */
+#ifdef DEBUG_UNVEIL
+#define DPRINTF(x...) do { printf(x); } while (0)
+#else
+#define DPRINTF(x...)
+#endif
#define UNVEIL_MAX_VNODES 128
#define UNVEIL_MAX_NAMES 128
ret++;
}
rw_exit_write(&uv->uv_lock);
-#ifdef DEBUG_UNVEIL
- printf("deleted %d names\n", ret);
-#endif
+
+ DPRINTF("deleted %d names\n", ret);
return ret;
}
unvname_delete(unvn);
return 0;
}
-#ifdef DEBUG_UNVEIL
- printf("added name %s underneath vnode %p\n", name, uv->uv_vp);
-#endif
+
+ DPRINTF("added name %s underneath vnode %p\n", name, uv->uv_vp);
return 1;
}
rw_enter_read(&uv->uv_lock);
-#ifdef DEBUG_UNVEIL
- printf("unveil_namelookup: looking up name %s (%p) in vnode %p\n",
- name, name, uv->uv_vp);
-#endif
+ DPRINTF("%s: looking up name %s (%p) in vnode %p\n",
+ __func__, name, name, uv->uv_vp);
KASSERT(uv->uv_vp != NULL);
rw_exit_read(&uv->uv_lock);
-#ifdef DEBUG_UNVEIL
- if (ret == NULL)
- printf("unveil_namelookup: no match for name %s in vnode %p\n",
- name, uv->uv_vp);
- else
- printf("unveil_namelookup: matched name %s in vnode %p\n",
- name, uv->uv_vp);
-#endif
+ DPRINTF("%s: %s name %s in vnode %p\n", __func__,
+ (ret == NULL) ? "no match for" : "matched",
+ name, uv->uv_vp);
return ret;
}
/* skip any vnodes zapped by unveil_removevnode */
if (vp != NULL) {
vp->v_uvcount--;
-#ifdef DEBUG_UNVEIL
- printf("unveil: %s(%d): removing vnode %p uvcount %d "
+
+ DPRINTF("unveil: %s(%d): removing vnode %p uvcount %d "
"in position %ld\n",
ps->ps_comm, ps->ps_pid, vp, vp->v_uvcount, i);
-#endif
vrele(vp);
}
ps->ps_uvncount -= unveil_delete_names(uv);
* This corner case should not happen because
* we have not set LOCKPARENT in the flags
*/
- printf("vnode %p PDIRUNLOCK on error\n", vp);
+ DPRINTF("vnode %p PDIRUNLOCK on error\n", vp);
vrele(vp);
}
break;
{
#if 0
if (((~(*flags)) & nflags) != 0) {
-#ifdef DEBUG_UNVEIL
- printf("Flags escalation %llX -> %llX\n", *flags, nflags);
-#endif
+ DPRINTF("Flags escalation %llX -> %llX\n", *flags, nflags);
return 1;
}
#endif
* unrestrict it.
*/
if (directory_add) {
-#ifdef DEBUG_UNVEIL
- printf("unveil: %s(%d): updating directory vnode %p"
+ DPRINTF("unveil: %s(%d): updating directory vnode %p"
" to unrestricted uvcount %d\n",
pr->ps_comm, pr->ps_pid, vp, vp->v_uvcount);
-#endif
+
if (!unveil_setflags(&uv->uv_flags, flags))
ret = EPERM;
else
struct unvname *tname;
if ((tname = unveil_namelookup(uv,
ndp->ni_cnd.cn_nameptr)) != NULL) {
-#ifdef DEBUG_UNVEIL
- printf("unveil: %s(%d): changing flags for %s"
+ DPRINTF("unveil: %s(%d): changing flags for %s"
"in vnode %p, uvcount %d\n",
pr->ps_comm, pr->ps_pid, tname->un_name, vp,
vp->v_uvcount);
-#endif
+
if (!unveil_setflags(&tname->un_flags, flags))
ret = EPERM;
else
if (directory_add) {
uv->uv_flags = flags;
ret = 0;
-#ifdef DEBUG_UNVEIL
- printf("unveil: %s(%d): added unrestricted directory vnode %p"
+
+ DPRINTF("unveil: %s(%d): added unrestricted directory vnode %p"
", uvcount %d\n",
pr->ps_comm, pr->ps_pid, vp, vp->v_uvcount);
-#endif
goto done;
}
pr->ps_uvncount++;
ret = 0;
-#ifdef DEBUG_UNVEIL
- printf("unveil: %s(%d): added name %s beneath %s vnode %p,"
+ DPRINTF("unveil: %s(%d): added name %s beneath %s vnode %p,"
" uvcount %d\n",
pr->ps_comm, pr->ps_pid, ndp->ni_cnd.cn_nameptr,
uv->uv_flags ? "unrestricted" : "restricted",
vp, vp->v_uvcount);
-#endif
done:
return ret;
unveil_flagmatch(struct nameidata *ni, u_char flags)
{
if (flags == 0) {
-#ifdef DEBUG_UNVEIL
- printf("All operations forbidden for 0 flags\n");
-#endif
+ DPRINTF("All operations forbidden for 0 flags\n");
return 0;
}
if (ni->ni_unveil & UNVEIL_READ) {
if ((flags & UNVEIL_READ) == 0) {
-#ifdef DEBUG_UNVEIL
- printf("unveil lacks UNVEIL_READ\n");
-#endif
+ DPRINTF("unveil lacks UNVEIL_READ\n");
return 0;
}
}
if (ni->ni_unveil & UNVEIL_WRITE) {
if ((flags & UNVEIL_WRITE) == 0) {
-#ifdef DEBUG_UNVEIL
- printf("unveil lacks UNVEIL_WRITE\n");
-#endif
+ DPRINTF("unveil lacks UNVEIL_WRITE\n");
return 0;
}
}
if (ni->ni_unveil & UNVEIL_EXEC) {
if ((flags & UNVEIL_EXEC) == 0) {
-#ifdef DEBUG_UNVEIL
- printf("unveil lacks UNVEIL_EXEC\n");
-#endif
+ DPRINTF("unveil lacks UNVEIL_EXEC\n");
return 0;
}
}
if (ni->ni_unveil & UNVEIL_CREATE) {
if ((flags & UNVEIL_CREATE) == 0) {
-#ifdef DEBUG_UNVEIL
- printf("unveil lacks UNVEIL_CREATE\n");
-#endif
+ DPRINTF("unveil lacks UNVEIL_CREATE\n");
return 0;
}
}
* Store this match for later use. Flags are checked at the end.
*/
if (uv) {
-#ifdef DEBUG_UNVEIL
- printf("unveil: %s(%d): relative unveil at %p matches",
+ DPRINTF("unveil: %s(%d): relative unveil at %p matches",
pr->ps_comm, pr->ps_pid, uv);
-#endif
+
ni->ni_unveil_match = uv;
}
}
if (uv != NULL) {
/* update match */
ni->ni_unveil_match = uv;
-#ifdef DEBUG_UNVEIL
- printf("unveil: %s(%d): component directory match for "
+
+ DPRINTF("unveil: %s(%d): component directory match for "
"vnode %p\n", pr->ps_comm, pr->ps_pid, dp);
-#endif
}
}
return (0);
if (ni->ni_cnd.cn_flags & BYPASSUNVEIL) {
-#ifdef DEBUG_UNVEIL
- printf("unveil: %s(%d): BYPASSUNVEIL.\n",
+ DPRINTF("unveil: %s(%d): BYPASSUNVEIL.\n",
pr->ps_comm, pr->ps_pid);
-#endif
+
return (0);
}
/* We are matching a directory terminal component */
uv = unveil_lookup(ni->ni_vp, pr, NULL);
if (uv == NULL || (uv->uv_flags & UNVEIL_USERSET) == 0) {
-#ifdef DEBUG_UNVEIL
- printf("unveil: %s(%d) no match for vnode %p\n",
+ DPRINTF("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)) {
-#ifdef DEBUG_UNVEIL
- printf("unveil: %s(%d) flag mismatch for directory"
+ DPRINTF("unveil: %s(%d) flag mismatch for directory"
" vnode %p\n",
pr->ps_comm, pr->ps_pid, ni->ni_vp);
-#endif
+
pr->ps_acflag |= AUNVEIL;
if (uv->uv_flags & UNVEIL_MASK)
return EACCES;
}
/* directory and flags match, success */
-#ifdef DEBUG_UNVEIL
- printf("unveil: %s(%d): matched directory \"%s\" at vnode %p\n",
+ DPRINTF("unveil: %s(%d): matched directory \"%s\" at vnode %p\n",
pr->ps_comm, pr->ps_pid, ni->ni_cnd.cn_nameptr,
uv->uv_vp);
-#endif
+
return (0);
}
/* Otherwise, we are matching a non-terminal component */
uv = unveil_lookup(ni->ni_dvp, pr, NULL);
if (uv == NULL) {
-#ifdef DEBUG_UNVEIL
- printf("unveil: %s(%d) no match for directory vnode %p\n",
+ DPRINTF("unveil: %s(%d) no match for directory vnode %p\n",
pr->ps_comm, pr->ps_pid, ni->ni_dvp);
-#endif
+
goto done;
}
if ((tname = unveil_namelookup(uv, ni->ni_cnd.cn_nameptr)) == NULL) {
-#ifdef DEBUG_UNVEIL
- printf("unveil: %s(%d) no match for terminal '%s' in "
+ DPRINTF("unveil: %s(%d) no match for terminal '%s' in "
"directory vnode %p\n",
pr->ps_comm, pr->ps_pid,
ni->ni_cnd.cn_nameptr, ni->ni_dvp);
-#endif
+
/* no specific name, so check unveil directory flags */
if (!unveil_flagmatch(ni, uv->uv_flags)) {
-#ifdef DEBUG_UNVEIL
- printf("unveil: %s(%d) terminal "
+ DPRINTF("unveil: %s(%d) terminal "
"'%s' flags mismatch in directory "
"vnode %p\n",
pr->ps_comm, pr->ps_pid,
ni->ni_cnd.cn_nameptr, ni->ni_dvp);
-#endif
+
/*
* If dir has user set restrictions fail with
* EACCES or ENOENT. Otherwise, use any covering
goto done;
}
/* directory flags match, success */
-#ifdef DEBUG_UNVEIL
- printf("unveil: %s(%d): matched \"%s\" underneath vnode %p\n",
+ DPRINTF("unveil: %s(%d): matched \"%s\" underneath vnode %p\n",
pr->ps_comm, pr->ps_pid, ni->ni_cnd.cn_nameptr,
uv->uv_vp);
-#endif
+
return (0);
}
if (!unveil_flagmatch(ni, tname->un_flags)) {
/* do flags match for matched name */
-#ifdef DEBUG_UNVEIL
- printf("unveil: %s(%d) flag mismatch for terminal '%s'\n",
+ DPRINTF("unveil: %s(%d) flag mismatch for terminal '%s'\n",
pr->ps_comm, pr->ps_pid, tname->un_name);
-#endif
+
pr->ps_acflag |= AUNVEIL;
return EACCES;
}
/* name and flags match. success */
-#ifdef DEBUG_UNVEIL
- printf("unveil: %s(%d) matched terminal '%s'\n",
+ DPRINTF("unveil: %s(%d) matched terminal '%s'\n",
pr->ps_comm, pr->ps_pid, tname->un_name);
-#endif
+
return (0);
done:
*/
for (uv = ni->ni_unveil_match; uv != NULL; uv = nuv) {
if (unveil_flagmatch(ni, uv->uv_flags)) {
-#ifdef DEBUG_UNVEIL
- printf("unveil: %s(%d): matched \"%s\" underneath/at "
+ DPRINTF("unveil: %s(%d): matched \"%s\" underneath/at "
"vnode %p\n", pr->ps_comm, pr->ps_pid,
ni->ni_cnd.cn_nameptr, uv->uv_vp);
-#endif
+
return (0);
}
/* if node has any flags set then this is an access violation */
if (uv->uv_flags & UNVEIL_USERSET) {
-#ifdef DEBUG_UNVEIL
- printf("unveil: %s(%d) flag mismatch for vnode %p\n",
+ DPRINTF("unveil: %s(%d) flag mismatch for vnode %p\n",
pr->ps_comm, pr->ps_pid, uv->uv_vp);
-#endif
+
pr->ps_acflag |= AUNVEIL;
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",
+
+ DPRINTF("unveil: %s(%d) check cover for vnode %p, uv_cover %zd\n",
pr->ps_comm, pr->ps_pid, uv->uv_vp, uv->uv_cover);
-#endif
+
nuv = unveil_covered(uv, uv->uv_vp, p);
if (nuv == uv)
break;
if (vp->v_uvcount == 0)
return;
-#ifdef DEBUG_UNVEIL
- printf("unveil_removevnode found vnode %p with count %d\n",
- vp, vp->v_uvcount);
-#endif
+ DPRINTF("%s: found vnode %p with count %d\n",
+ __func__, vp, vp->v_uvcount);
+
vref(vp); /* make sure it is held till we are done */
LIST_FOREACH(pr, &allprocess, ps_list) {
uv->uv_vp != NULL) {
uv->uv_vp = NULL;
uv->uv_flags = 0;
-#ifdef DEBUG_UNVEIL
- printf("unveil_removevnode vnode %p now count %d\n",
- vp, vp->v_uvcount);
-#endif
+
+ DPRINTF("%s: vnode %p now count %d\n",
+ __func__, vp, vp->v_uvcount);
+
if (vp->v_uvcount > 0) {
vrele(vp);
vp->v_uvcount--;