diff options
author | green <green@FreeBSD.org> | 2000-08-29 11:28:06 +0000 |
---|---|---|
committer | green <green@FreeBSD.org> | 2000-08-29 11:28:06 +0000 |
commit | 0fa5ae2859837ce45dfa1d212731cbed7a6bf037 (patch) | |
tree | a0487072d9e3fda944c9970116207cd67e21e923 /sys/kern/kern_proc.c | |
parent | 0290d697a80874eccbc3e0228ae5f2acb2b7522c (diff) | |
download | FreeBSD-src-0fa5ae2859837ce45dfa1d212731cbed7a6bf037.zip FreeBSD-src-0fa5ae2859837ce45dfa1d212731cbed7a6bf037.tar.gz |
Remove any possibility of hiwat-related race conditions by changing
the chgsbsize() call to use a "subject" pointer (&sb.sb_hiwat) and
a u_long target to set it to. The whole thing is splnet().
This fixes a problem that jdp has been able to provoke.
Diffstat (limited to 'sys/kern/kern_proc.c')
-rw-r--r-- | sys/kern/kern_proc.c | 16 |
1 files changed, 12 insertions, 4 deletions
diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c index 9fd0f45..4a4282a 100644 --- a/sys/kern/kern_proc.c +++ b/sys/kern/kern_proc.c @@ -194,25 +194,33 @@ chgproccnt(uid, diff, max) * Change the total socket buffer size a user has used. */ int -chgsbsize(uid, diff, max) +chgsbsize(uid, hiwat, to, max) uid_t uid; - rlim_t diff; + u_long *hiwat; + u_long to; rlim_t max; { struct uidinfo *uip; + rlim_t diff; + int s; uip = uifind(uid); - if (diff < 0) - KASSERT(uip != NULL, ("reducing sbsize: lost count, uid = %d", uid)); + KASSERT(to >= *hiwat || uip != NULL, + ("reducing sbsize: lost count, uid = %d", uid)); if (uip == NULL) uip = uicreate(uid); + s = splnet(); + diff = to - *hiwat; /* don't allow them to exceed max, but allow subtraction */ if (diff > 0 && uip->ui_sbsize + diff > max) { (void)uifree(uip); + splx(s); return (0); } uip->ui_sbsize += diff; + *hiwat = to; (void)uifree(uip); + splx(s); return (1); } |