diff options
author | anton <anton@cvs.openbsd.org> | 2019-10-01 18:51:03 +0000 |
---|---|---|
committer | anton <anton@cvs.openbsd.org> | 2019-10-01 18:51:03 +0000 |
commit | 92a979dfb9be12dc4503d44e0a7984b84bed939d (patch) | |
tree | b4b8367d71c98b394d305383ec17f839a6543714 /sys/kern | |
parent | 669b37f51c0a0f1653f45c806c66272623832b1d (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.c | 28 |
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 |