summaryrefslogtreecommitdiff
path: root/sys/kern
diff options
context:
space:
mode:
authoranton <anton@cvs.openbsd.org>2019-10-01 18:51:03 +0000
committeranton <anton@cvs.openbsd.org>2019-10-01 18:51:03 +0000
commit92a979dfb9be12dc4503d44e0a7984b84bed939d (patch)
treeb4b8367d71c98b394d305383ec17f839a6543714 /sys/kern
parent669b37f51c0a0f1653f45c806c66272623832b1d (diff)
Only increment the ps_uvncount counter when a path is successfully added
to the corresponding red-black tree; meaning the path was not already present in the tree. This prevents an assertion to trigger in unveil_destroy() later on when the process exits. ok beck@ Reported-by: syzbot+db66362e1ffdc72e5aeb@syzkaller.appspotmail.com
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/kern_unveil.c28
1 files changed, 18 insertions, 10 deletions
diff --git a/sys/kern/kern_unveil.c b/sys/kern/kern_unveil.c
index 1a887590c53..d7ffc814db0 100644
--- a/sys/kern/kern_unveil.c
+++ b/sys/kern/kern_unveil.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_unveil.c,v 1.33 2019/09/11 15:01:40 beck Exp $ */
+/* $OpenBSD: kern_unveil.c,v 1.34 2019/10/01 18:51:02 anton Exp $ */
/*
* Copyright (c) 2017-2019 Bob Beck <beck@openbsd.org>
@@ -121,24 +121,32 @@ unveil_delete_names(struct unveil *uv)
return ret;
}
-void
+int
unveil_add_name_unlocked(struct unveil *uv, char *name, u_char flags)
{
struct unvname *unvn;
unvn = unvname_new(name, strlen(name) + 1, flags);
- RBT_INSERT(unvname_rbt, &uv->uv_names, unvn);
+ if (RBT_INSERT(unvname_rbt, &uv->uv_names, unvn) != NULL) {
+ /* Name already present. */
+ unvname_delete(unvn);
+ return 0;
+ }
#ifdef DEBUG_UNVEIL
printf("added name %s underneath vnode %p\n", name, uv->uv_vp);
#endif
+ return 1;
}
-void
+int
unveil_add_name(struct unveil *uv, char *name, u_char flags)
{
+ int ret;
+
rw_enter_write(&uv->uv_lock);
- unveil_add_name_unlocked(uv, name, flags);
+ ret = unveil_add_name_unlocked(uv, name, flags);
rw_exit_write(&uv->uv_lock);
+ return ret;
}
struct unvname *
@@ -232,9 +240,9 @@ unveil_copy(struct process *parent, struct process *child)
RBT_INIT(unvname_rbt, &to->uv_names);
rw_enter_read(&from->uv_lock);
RBT_FOREACH_SAFE(unvn, unvname_rbt, &from->uv_names, next) {
- unveil_add_name_unlocked(&child->ps_uvpaths[i],
- unvn->un_name, unvn->un_flags);
- child->ps_uvncount++;
+ if (unveil_add_name_unlocked(&child->ps_uvpaths[i],
+ unvn->un_name, unvn->un_flags))
+ child->ps_uvncount++;
}
rw_exit_read(&from->uv_lock);
to->uv_flags = from->uv_flags;
@@ -617,8 +625,8 @@ unveil_add(struct proc *p, struct nameidata *ndp, const char *permissions)
goto done;
}
- unveil_add_name(uv, ndp->ni_cnd.cn_nameptr, flags);
- pr->ps_uvncount++;
+ if (unveil_add_name(uv, ndp->ni_cnd.cn_nameptr, flags))
+ pr->ps_uvncount++;
ret = 0;
#ifdef DEBUG_UNVEIL