Mon Dec 14 23:12:12 2020 UTC ()
when updating the per-uid "semcnt", decrement the counter for the uid
that created the ksem, not the uid of the process freeing the ksem.
fixes PR 55509.

Reported-by: syzbot+9d04b3ef2ca180ef9b06@syzkaller.appspotmail.com


(chs)
diff -r1.59 -r1.60 src/sys/kern/uipc_sem.c

cvs diff -r1.59 -r1.60 src/sys/kern/uipc_sem.c (expand / switch to unified diff)

--- src/sys/kern/uipc_sem.c 2020/05/04 13:58:48 1.59
+++ src/sys/kern/uipc_sem.c 2020/12/14 23:12:12 1.60
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: uipc_sem.c,v 1.59 2020/05/04 13:58:48 riastradh Exp $ */ 1/* $NetBSD: uipc_sem.c,v 1.60 2020/12/14 23:12:12 chs Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2011, 2019 The NetBSD Foundation, Inc. 4 * Copyright (c) 2011, 2019 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Mindaugas Rasiukevicius and Jason R. Thorpe. 8 * by Mindaugas Rasiukevicius and Jason R. Thorpe.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -50,27 +50,27 @@ @@ -50,27 +50,27 @@
50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55 * SUCH DAMAGE. 55 * SUCH DAMAGE.
56 */ 56 */
57 57
58/* 58/*
59 * Implementation of POSIX semaphore. 59 * Implementation of POSIX semaphore.
60 */ 60 */
61 61
62#include <sys/cdefs.h> 62#include <sys/cdefs.h>
63__KERNEL_RCSID(0, "$NetBSD: uipc_sem.c,v 1.59 2020/05/04 13:58:48 riastradh Exp $"); 63__KERNEL_RCSID(0, "$NetBSD: uipc_sem.c,v 1.60 2020/12/14 23:12:12 chs Exp $");
64 64
65#include <sys/param.h> 65#include <sys/param.h>
66#include <sys/kernel.h> 66#include <sys/kernel.h>
67 67
68#include <sys/atomic.h> 68#include <sys/atomic.h>
69#include <sys/proc.h> 69#include <sys/proc.h>
70#include <sys/lwp.h> 70#include <sys/lwp.h>
71#include <sys/ksem.h> 71#include <sys/ksem.h>
72#include <sys/syscall.h> 72#include <sys/syscall.h>
73#include <sys/stat.h> 73#include <sys/stat.h>
74#include <sys/kmem.h> 74#include <sys/kmem.h>
75#include <sys/fcntl.h> 75#include <sys/fcntl.h>
76#include <sys/file.h> 76#include <sys/file.h>
@@ -459,66 +459,65 @@ ksem_create(lwp_t *l, const char *name,  @@ -459,66 +459,65 @@ ksem_create(lwp_t *l, const char *name,
459 return ENAMETOOLONG; 459 return ENAMETOOLONG;
460 } 460 }
461 /* Name must start with a '/' but not contain one. */ 461 /* Name must start with a '/' but not contain one. */
462 if (*name != '/' || len < 2 || strchr(name + 1, '/') != NULL) { 462 if (*name != '/' || len < 2 || strchr(name + 1, '/') != NULL) {
463 return EINVAL; 463 return EINVAL;
464 } 464 }
465 kname = kmem_alloc(++len, KM_SLEEP); 465 kname = kmem_alloc(++len, KM_SLEEP);
466 strlcpy(kname, name, len); 466 strlcpy(kname, name, len);
467 } else { 467 } else {
468 kname = NULL; 468 kname = NULL;
469 len = 0; 469 len = 0;
470 } 470 }
471 471
472 chgsemcnt(kauth_cred_getuid(l->l_cred), 1); 
473 
474 ks = kmem_zalloc(sizeof(ksem_t), KM_SLEEP); 472 ks = kmem_zalloc(sizeof(ksem_t), KM_SLEEP);
475 mutex_init(&ks->ks_lock, MUTEX_DEFAULT, IPL_NONE); 473 mutex_init(&ks->ks_lock, MUTEX_DEFAULT, IPL_NONE);
476 cv_init(&ks->ks_cv, "psem"); 474 cv_init(&ks->ks_cv, "psem");
477 ks->ks_name = kname; 475 ks->ks_name = kname;
478 ks->ks_namelen = len; 476 ks->ks_namelen = len;
479 ks->ks_mode = mode; 477 ks->ks_mode = mode;
480 ks->ks_value = val; 478 ks->ks_value = val;
481 ks->ks_ref = 1; 479 ks->ks_ref = 1;
482 480
483 uc = l->l_cred; 481 uc = l->l_cred;
484 ks->ks_uid = kauth_cred_geteuid(uc); 482 ks->ks_uid = kauth_cred_geteuid(uc);
485 ks->ks_gid = kauth_cred_getegid(uc); 483 ks->ks_gid = kauth_cred_getegid(uc);
486 484 chgsemcnt(ks->ks_uid, 1);
487 atomic_inc_uint(&nsems_total); 485 atomic_inc_uint(&nsems_total);
 486
488 *ksret = ks; 487 *ksret = ks;
489 return 0; 488 return 0;
490} 489}
491 490
492static void 491static void
493ksem_free(ksem_t *ks) 492ksem_free(ksem_t *ks)
494{ 493{
495 494
496 KASSERT(!cv_has_waiters(&ks->ks_cv)); 495 KASSERT(!cv_has_waiters(&ks->ks_cv));
497 496
 497 chgsemcnt(ks->ks_uid, -1);
 498 atomic_dec_uint(&nsems_total);
 499
498 if (ks->ks_pshared_id) { 500 if (ks->ks_pshared_id) {
499 KASSERT(ks->ks_pshared_proc == NULL); 501 KASSERT(ks->ks_pshared_proc == NULL);
500 ksem_remove_pshared(ks); 502 ksem_remove_pshared(ks);
501 } 503 }
502 if (ks->ks_name) { 504 if (ks->ks_name) {
503 KASSERT(ks->ks_namelen > 0); 505 KASSERT(ks->ks_namelen > 0);
504 kmem_free(ks->ks_name, ks->ks_namelen); 506 kmem_free(ks->ks_name, ks->ks_namelen);
505 } 507 }
506 mutex_destroy(&ks->ks_lock); 508 mutex_destroy(&ks->ks_lock);
507 cv_destroy(&ks->ks_cv); 509 cv_destroy(&ks->ks_cv);
508 kmem_free(ks, sizeof(ksem_t)); 510 kmem_free(ks, sizeof(ksem_t));
509 
510 atomic_dec_uint(&nsems_total); 
511 chgsemcnt(kauth_cred_getuid(curproc->p_cred), -1); 
512} 511}
513 512
514#define KSEM_ID_IS_PSHARED(id) \ 513#define KSEM_ID_IS_PSHARED(id) \
515 (((id) & KSEM_MARKER_MASK) == KSEM_PSHARED_MARKER) 514 (((id) & KSEM_MARKER_MASK) == KSEM_PSHARED_MARKER)
516 515
517static void 516static void
518ksem_release(ksem_t *ksem, int fd) 517ksem_release(ksem_t *ksem, int fd)
519{ 518{
520 bool destroy = false; 519 bool destroy = false;
521 520
522 KASSERT(mutex_owned(&ksem->ks_lock)); 521 KASSERT(mutex_owned(&ksem->ks_lock));
523 522
524 KASSERT(ksem->ks_ref > 0); 523 KASSERT(ksem->ks_ref > 0);