From nobody Wed Jul 29 17:47:59 2026 X-Original-To: dev-commits-src-all@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 4h9KYW5wwlz6mZdr for ; Wed, 29 Jul 2026 17:47:59 +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 4h9KYW1lQ3z3gBD for ; Wed, 29 Jul 2026 17:47:59 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1785347279; 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=y4cvXa5tTJaUs22ZhwNJcbOk+IrA9G/YvlrIF5xrh9g=; b=teenJ/rbEKigyMw37183ixPYA8fzkide+KTmep4hi3+ProLcB1q9ZcVu+0iiImvM1rIjqE OJS5hlxp8hv0JVv604mrhDsdGnb0KJPhqczcbvncZnZ5sNVsmXYEPWTiiVu43Lo6azwR8E urEh7ld7a7Nr0uGy8COS6XCQtTdmW6E0R0K4cb3F/g4UPtw7xco0myt7dz/3rI9Ioi7f/J YBZAo4z948uiXWhgoyydnPsTyZp2SEeRs76znPMtnpw/HFHlcPpyqlJn5kYXZzpnf52sWz iRVpSyViLhJyBXFj9mx/KOkbDdGdY6PvAOSWEmg9NkJx0uTY5pJsvMD7i2kGBg== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1785347279; a=rsa-sha256; cv=none; b=gDGHohoy2wouHlvEycBV5rVD+S+WZe+YqgkJra4gSep5+e2GWDz2sul1vGpFMNh5tWbcLx NdDBYNkw6+aBa10uW1wgGwV+wZFzmYH2Yc/5Un6GsE5uXxb3BfJK2k0F7+G8tcjLSuU7/k Vn5xpq89IiDQHFdCCYlwuLWm1wY567CQLTe6aw6Gn0FsPLshOIW4s/1JEMHZ0GIne0yntE 35nGiuDITiH72DueR3qBHvEvwQZBsm4xPqt3xDwey+xr0tGadmZs9lLzJGjfLQL5gZXOku RHJzvhnPJ3xHIJ/RiIJED/9FL2MKGBOHzmXxI6AMaPaqUvFMlGv1gLiKx/4KqQ== 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=1785347279; 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=y4cvXa5tTJaUs22ZhwNJcbOk+IrA9G/YvlrIF5xrh9g=; b=g3xq1XhQXLmP/vLgnkH6DT8KDz+gENJnfEZGu3hhMS0y9ptjxeoytdqXd/XsUO9B+D6Ao3 OcRNYGvpBDDgTOs0arwqdMHTC2rg/4wWzwLi2zKMFIKo15idOCNp7o3xSqR93ndtcVCEkX uag5uUhTEZh3AP6RUuDgL8hobkm07G02JvNFXinScmAXzXgVVhiONTXTGiU8eNEV+sT9yH WpZL2BUUt0/oZmLUIxA/8WuJKnPjcVfl4udoteVsbL06chvum0iIM6DINHT6Nv6D+5FrVA p91I+wNv3GyQ/gRHQAWOgJyxapX5VuawfQwXvNgrxesRqoy8Rh7AaPJALpchWg== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4h9KYW0l41zcJP for ; Wed, 29 Jul 2026 17:47:59 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 397b8 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Wed, 29 Jul 2026 17:47:59 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Mark Johnston Subject: git: 8c5e2d26cde5 - main - sysvsem: Fix a TOCTOU race in semctl({GET,SET}ALL) List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@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/main X-Git-Reftype: branch X-Git-Commit: 8c5e2d26cde5d06c362e6925dbcdbd43aa315a12 Auto-Submitted: auto-generated Date: Wed, 29 Jul 2026 17:47:59 +0000 Message-Id: <6a6a3ccf.397b8.175f93b4@gitrepo.freebsd.org> The branch main has been updated by markj: URL: https://cgit.FreeBSD.org/src/commit/?id=8c5e2d26cde5d06c362e6925dbcdbd43aa315a12 commit 8c5e2d26cde5d06c362e6925dbcdbd43aa315a12 Author: Mark Johnston AuthorDate: 2026-07-27 15:41:30 +0000 Commit: Mark Johnston CommitDate: 2026-07-29 17:45:02 +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",