Page MenuHomeFreeBSD

sigtimedwait: Prevent timeout math overflows.
ClosedPublic

Authored by dchagin on Apr 20 2022, 2:29 PM.
Tags
None
Referenced Files
Unknown Object (File)
Feb 15 2024, 9:23 PM
Unknown Object (File)
Jan 14 2024, 9:38 AM
Unknown Object (File)
Dec 22 2023, 11:02 PM
Unknown Object (File)
Sep 12 2023, 1:16 AM
Unknown Object (File)
Aug 11 2023, 1:26 AM
Unknown Object (File)
Aug 11 2023, 1:19 AM
Unknown Object (File)
Aug 11 2023, 1:19 AM
Unknown Object (File)
Aug 11 2023, 1:19 AM
Subscribers

Details

Summary

Our kern_sigtimedwait() calculates absolute sleep timo value as 'uptime+timeout'.
So, when the user specifies a big timeout value (LONG_MAX), the calculated
timo can be less the the current uptime value.
In that case kern_sigtimedwait() returns EAGAIN instead of EINTR, if
unblocked signal was caught.

While here switch to a high-precision sleep method.

Below are to separate commits: fix and tests for it and for some other
kib@ commits to sigwait are.

Test Plan

Add tests for sigwait family syscalls.

Diff Detail

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

Event Timeline

dchagin added reviewers: jhb, kib, mav.
dchagin changed the repository for this revision from rS FreeBSD src repository - subversion to rG FreeBSD src repository.
sys/kern/kern_sig.c
1279

Why not just: ts.tv_sec = INT32_MAX / 2; ? I don't see over used anywhere else.

1288

precision is uninitialized here. Probably not a problem, but not nice.

sys/kern/kern_sig.c
1323

This may give false negative due to sbtt += tc_tick_sbt , while the msleep_sbt() below will use precise time. I guess it may end up in a tight loop till next hardclock.

1338–1339

It would be nice to use this status instead of calling TIMESEL() another time. callouts never return prematurely.

dchagin added inline comments.
sys/kern/kern_sig.c
1338–1339

good catch!

btw, as I understand, sbt eq 0 mean that the thread sleep indefinitely, while negative sbt mean thread no sleep.
So, at least poll() implementation should be checked as seems it uses sbt -1 for infinity sleep timeout

sys/kern/kern_sig.c
1338–1339

Might be callouts indeed do not return prematurely, but note that msleep() uses process-shared wait chain. In other words, if more than one thread called sigtimedwait(2) syscalls, there could be aliased wakeups. Then, if other thread consumed the signal, shouldn't we re-iterate? Or should this case considered an application bug?

sys/kern/kern_sig.c
1338–1339

The removed chunk checked for error == EAGAIN (AKA EWOULDBLOCK) case -- specifically timeout expiration. In case of wakeup() call on the shared wait chain error should be zero and I see the code will indeed reiterate.

This revision is now accepted and ready to land.Apr 21 2022, 12:56 AM
dchagin added inline comments.
sys/kern/kern_sig.c
1338–1339

There will be a storm any way if there are more than one thread, but the threads that do not consume the signal fall to msleep again.
At the same time, the sleep time is absolute and it is not necessary to recheck it as msleep will take care. Or Im missing something?