Page MenuHomeFreeBSD

sysvsem: Fix a TOCTOU race in semctl({GET,SET}ALL)
ClosedPublic

Authored by markj on Thu, Jul 23, 6:49 PM.

Details

Summary

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.

Reported by: Maik Muench of Secfault Security

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Not Applicable
Unit
Tests Not Applicable

Event Timeline

markj held this revision as a draft.
markj published this revision for review.Thu, Jul 23, 6:49 PM
markj added reviewers: kib, jhb.
markj changed the visibility from "Public (No Login Required)" to "Subscribers".
markj changed the edit policy from "All Users" to "Subscribers".
markj edited subscribers, added: secteam, kib, jhb; removed: imp, olce.
sys/kern/sysv_sem.c
858

Shouldn't we check semvalid() before reading the count, too?

862

Why EINVAL was chosen? I would say that more proper error is EAGAIN, or might be we should just free the array and retry in kernel.

As I understand it, the interface itself is weird: userspace is supposed to perform semctl(IPC_STAT) to get the semaphore set' size, then allocate the buffer of the right size and call into GETALL/SETALL. So EINVAL in this case indicates that the set was changed meantime, but EFAULT could mean it as well. Also userspace cannot detect that there were less data returned than requested (e.g. due to ABA for IPC_STAT nsems).

markj marked an inline comment as done.

Change errno value

sys/kern/sysv_sem.c
858

Why? The result needs to be re-checked anyway.

862

I changed it to EAGAIN.

sys/kern/sysv_sem.c
858

semvalid() tests for SEM_ALLOC

Check semvalid() before dropping the lock.

This revision is now accepted and ready to land.Mon, Jul 27, 1:28 PM
markj changed the visibility from "Subscribers" to "Public (No Login Required)".Wed, Jul 29, 5:57 PM
markj changed the edit policy from "Subscribers" to "All Users".