From: mpi Date: Mon, 26 Feb 2018 13:43:51 +0000 (+0000) Subject: Serialize access to UID data with a rwlock. X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=b054dc0d0c531404d2b3d13398246bf2368951ae;p=openbsd Serialize access to UID data with a rwlock. Caller must call uid_release() after making whatever change they needed on the result of uid_find(). Adapted from guenther@'s proctree diff, ok dlg@, visa@ --- diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c index 8ba12226f0d..45e84d8462d 100644 --- a/sys/kern/kern_proc.c +++ b/sys/kern/kern_proc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_proc.c,v 1.81 2018/02/20 12:38:58 mpi Exp $ */ +/* $OpenBSD: kern_proc.c,v 1.82 2018/02/26 13:43:51 mpi Exp $ */ /* $NetBSD: kern_proc.c,v 1.14 1996/02/09 18:59:41 christos Exp $ */ /* @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -49,6 +50,7 @@ #include #include +struct rwlock uidinfolk; #define UIHASH(uid) (&uihashtbl[(uid) & uihash]) LIST_HEAD(uihashhead, uidinfo) *uihashtbl; u_long uihash; /* size of hash table - 1 */ @@ -91,6 +93,7 @@ procinit(void) LIST_INIT(&zombprocess); LIST_INIT(&allproc); + rw_init(&uidinfolk, "uidinfo"); tidhashtbl = hashinit(maxthread / 4, M_PROC, M_NOWAIT, &tidhash); pidhashtbl = hashinit(maxprocess / 4, M_PROC, M_NOWAIT, &pidhash); @@ -113,6 +116,10 @@ procinit(void) PR_WAITOK, "sessionpl", NULL); } +/* + * This returns with `uidinfolk' held: caller must call uid_release() + * after making whatever change they needed. + */ struct uidinfo * uid_find(uid_t uid) { @@ -120,12 +127,15 @@ uid_find(uid_t uid) struct uihashhead *uipp; uipp = UIHASH(uid); + rw_enter_write(&uidinfolk); LIST_FOREACH(uip, uipp, ui_hash) if (uip->ui_uid == uid) break; if (uip) return (uip); + rw_exit_write(&uidinfolk); nuip = malloc(sizeof(*nuip), M_PROC, M_WAITOK|M_ZERO); + rw_enter_write(&uidinfolk); LIST_FOREACH(uip, uipp, ui_hash) if (uip->ui_uid == uid) break; @@ -139,6 +149,12 @@ uid_find(uid_t uid) return (nuip); } +void +uid_release(struct uidinfo *uip) +{ + rw_exit_write(&uidinfolk); +} + /* * Change the count associated with number of threads * a given user is using. @@ -147,12 +163,14 @@ int chgproccnt(uid_t uid, int diff) { struct uidinfo *uip; + long count; uip = uid_find(uid); - uip->ui_proccnt += diff; - if (uip->ui_proccnt < 0) + count = (uip->ui_proccnt += diff); + uid_release(uip); + if (count < 0) panic("chgproccnt: procs < 0"); - return (uip->ui_proccnt); + return count; } /* diff --git a/sys/kern/vfs_lockf.c b/sys/kern/vfs_lockf.c index 019090005be..9bd95aede32 100644 --- a/sys/kern/vfs_lockf.c +++ b/sys/kern/vfs_lockf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vfs_lockf.c,v 1.24 2016/11/07 00:26:33 guenther Exp $ */ +/* $OpenBSD: vfs_lockf.c,v 1.25 2018/02/26 13:43:51 mpi Exp $ */ /* $NetBSD: vfs_lockf.c,v 1.7 1996/02/04 02:18:21 christos Exp $ */ /* @@ -106,9 +106,12 @@ lf_alloc(uid_t uid, int allowfail) uip = uid_find(uid); if (uid && allowfail && uip->ui_lockcnt > - (allowfail == 1 ? maxlocksperuid : (maxlocksperuid * 2))) + (allowfail == 1 ? maxlocksperuid : (maxlocksperuid * 2))) { + uid_release(uip); return (NULL); + } uip->ui_lockcnt++; + uid_release(uip); lock = pool_get(&lockfpool, PR_WAITOK); lock->lf_uid = uid; return (lock); @@ -121,6 +124,7 @@ lf_free(struct lockf *lock) uip = uid_find(lock->lf_uid); uip->ui_lockcnt--; + uid_release(uip); pool_put(&lockfpool, lock); } diff --git a/sys/sys/proc.h b/sys/sys/proc.h index fd0e46e5984..edcaf7cb960 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -1,4 +1,4 @@ -/* $OpenBSD: proc.h,v 1.246 2018/02/20 12:38:58 mpi Exp $ */ +/* $OpenBSD: proc.h,v 1.247 2018/02/26 13:43:51 mpi Exp $ */ /* $NetBSD: proc.h,v 1.44 1996/04/22 01:23:21 christos Exp $ */ /*- @@ -408,6 +408,7 @@ struct uidinfo { }; struct uidinfo *uid_find(uid_t); +void uid_release(struct uidinfo *); /* * We use process IDs <= PID_MAX; PID_MAX + 1 must also fit in a pid_t,