From nobody Wed Jul 29 17:49:03 2026 X-Original-To: dev-commits-src-branches@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4h9KZm2Ch7z6mZqc for ; Wed, 29 Jul 2026 17:49:04 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "YR1" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4h9KZl3PVGz3jmY for ; Wed, 29 Jul 2026 17:49:03 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1785347343; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=fPeA8kom0bqlnsSrmh15CrR+bOTN0NuXoT+IcCizsNA=; b=tmC3gRSQ1qBlfy4+5ItuwjMAhRlyeL7uGyd3vnxwFV01/74toQldUMqviVjGarLjQ75YHD nlrQNyGwPsy5ntnSbDzQwOD4R4P+bA3qq2KC06+ZgHrWYRzwyUA1j6zL+ulqzlMx9namp1 o+vSjBgaqGJ1HtexV+3vRNjvWdNHTdRQ1t2uDv1kdF+lqj74d4ppKjkiDHGVor3Xs0+X4U tC5zprq8I0jVTb5c0uoErlAzbVx2LVon1z0qz4KadrHv7K+abdUJEKWz+mrsYSGfdMwlvC D2BxKQ1qhNNU06/ptALSwwm/9lrW7zyKUDvoePICD55+jrLqtQaT3WugryKiXA== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1785347343; a=rsa-sha256; cv=none; b=vitLKUkyrfkO8vXqdM6MioSuROJuppdjbunLLBIxde4kQVJzuEyUWVsG/gKJ0EP+f07oFa VQdE9Jlp006QUMkJHs48eUPzqvf3HlLCzIlSE7XWU64tbOWnNU4QhXipvDCYQ6s4dByx+h tWZ+JKFnm0GfThuaPZePq/lc3a+SaNQV+2Po1YpBJRSVrtqoAsTZl0ktHRMdRthDjWFwwc X/EXHXFWnOEnwZeld9nv0XTJN1F/y6nRCNWea6IdR3BT1uAoleT7lUdS3Fkygadr8MYpyu coX7ErXEATvEh+iGFSZXLj0GBqtO6cjm851dviUSpPPn54ypketYlhO30Q6WzA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1785347343; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=fPeA8kom0bqlnsSrmh15CrR+bOTN0NuXoT+IcCizsNA=; b=XrL21c4vrCOXa9FEWZZvLMLip0tTU0IWyVJ1iRYApYJl4lOUhuN1H/FGSYOQ8Mf4MzCf+J IGDuIBiTBMWKZy22brIwuZSC7g8cT3w0TJEQI0vYZGVXomszc2y7twublWpKXZWuF9mQcs KkL58TVBIVfM3ukid5dT267JXaG60w+0hXkwBM1+/PbfcaHvx+tpFTHHbZuHSHkZRlkYlI 56gKS0gP14dl8kBXT3UtT+M6v/+ljvFFww3lsrIcub9Yvt50CXgguYoHesUqwlE4V0lJa8 5nuTfJEQpQWNC0QyeGih1ZWtGco+yGH4IiyXipjvm7w1zqY4PQfoaw6L/nWJXw== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4h9KZl2Gxtzd9Q for ; Wed, 29 Jul 2026 17:49:03 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 3ac18 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Wed, 29 Jul 2026 17:49:03 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Mark Johnston Subject: git: 8b08ee989506 - stable/14 - sysvsem: Fix a TOCTOU race in semctl({GET,SET}ALL) List-Id: Commits to the stable branches of the FreeBSD src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-branches List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-branches@freebsd.org Sender: owner-dev-commits-src-branches@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: markj X-Git-Repository: src X-Git-Refname: refs/heads/stable/14 X-Git-Reftype: branch X-Git-Commit: 8b08ee989506af8706a640e9881c61981a77446b Auto-Submitted: auto-generated Date: Wed, 29 Jul 2026 17:49:03 +0000 Message-Id: <6a6a3d0f.3ac18.5257d2e0@gitrepo.freebsd.org> The branch stable/14 has been updated by markj: URL: https://cgit.FreeBSD.org/src/commit/?id=8b08ee989506af8706a640e9881c61981a77446b commit 8b08ee989506af8706a640e9881c61981a77446b Author: Mark Johnston AuthorDate: 2026-07-27 15:41:30 +0000 Commit: Mark Johnston CommitDate: 2026-07-29 17:48:54 +0000 sysvsem: Fix a TOCTOU race in semctl({GET,SET}ALL) These commands take a snapshot of the size of a semaphore set, then drop the lock and malloc an appropriately sized array before reacquiring the lock. A comment explains why this is (probably) safe. Unfortunately, it's wrong; it is indeed possible for a malicious userspace to create and destroy 2^{15} sets in the window where the lock is dropped. This race can lead to out-of-bounds reads and writes, and that can be exploited to elevate privileges. Replace the assertions with runtime checks. Approved by: so Security: FreeBSD-SA-26:54.sysvsem Security: CVE-2026-58087 Reported by: Maik Muench of Secfault Security Reviewed by: kib Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D58421 --- sys/kern/sysv_sem.c | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/sys/kern/sysv_sem.c b/sys/kern/sysv_sem.c index a99e1a4de14e..8c3dc6c0d9ed 100644 --- a/sys/kern/sysv_sem.c +++ b/sys/kern/sysv_sem.c @@ -848,25 +848,20 @@ kern_semctl(struct thread *td, int semid, int semnum, int cmd, * won't work for SETALL since we can't copyin() more * data than the user specified as we may return a * spurious EFAULT. - * - * Note that the number of semaphores in a set is - * fixed for the life of that set. The only way that - * the 'count' could change while are blocked in - * malloc() is if this semaphore set were destroyed - * and a new one created with the same index. - * However, semvalid() will catch that due to the - * sequence number unless exactly 0x8000 (or a - * multiple thereof) semaphore sets for the same index - * are created and destroyed while we are in malloc! - * */ + if ((error = semvalid(semid, rpr, semakptr)) != 0) + goto done2; count = semakptr->u.sem_nsems; mtx_unlock(sema_mtxp); array = malloc(sizeof(*array) * count, M_TEMP, M_WAITOK); mtx_lock(sema_mtxp); if ((error = semvalid(semid, rpr, semakptr)) != 0) goto done2; - KASSERT(count == semakptr->u.sem_nsems, ("nsems changed")); + if (count != semakptr->u.sem_nsems) { + /* Unlikely, but possible. */ + error = EAGAIN; + goto done2; + } if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_R))) goto done2; for (i = 0; i < semakptr->u.sem_nsems; i++) @@ -909,10 +904,8 @@ kern_semctl(struct thread *td, int semid, int semnum, int cmd, break; case SETALL: - /* - * See comment on GETALL for why 'count' shouldn't change - * and why we require a userland buffer. - */ + if ((error = semvalid(semid, rpr, semakptr)) != 0) + goto done2; count = semakptr->u.sem_nsems; mtx_unlock(sema_mtxp); array = malloc(sizeof(*array) * count, M_TEMP, M_WAITOK); @@ -922,7 +915,11 @@ kern_semctl(struct thread *td, int semid, int semnum, int cmd, break; if ((error = semvalid(semid, rpr, semakptr)) != 0) goto done2; - KASSERT(count == semakptr->u.sem_nsems, ("nsems changed")); + if (count != semakptr->u.sem_nsems) { + /* Unlikely, but possible. */ + error = EAGAIN; + goto done2; + } if ((error = ipcperm(td, &semakptr->u.sem_perm, IPC_W))) goto done2; for (i = 0; i < semakptr->u.sem_nsems; i++) { @@ -1482,12 +1479,11 @@ semexit_myhook(void *arg, struct proc *p) mtx_lock(sema_mtxp); if ((semakptr->u.sem_perm.mode & SEM_ALLOC) == 0 || - (semakptr->u.sem_perm.seq != seq)) { + semakptr->u.sem_perm.seq != seq || + semakptr->u.sem_nsems <= semnum) { mtx_unlock(sema_mtxp); continue; } - if (semnum >= semakptr->u.sem_nsems) - panic("semexit - semnum out of range"); DPRINTF(( "semexit: %p id=%d num=%d(adj=%d) ; sem=%d\n",