]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/commit
callout(9): Fix a race between CPU migration and callout_drain()
authormarkj <markj@FreeBSD.org>
Thu, 19 Nov 2020 18:37:28 +0000 (18:37 +0000)
committermarkj <markj@FreeBSD.org>
Thu, 19 Nov 2020 18:37:28 +0000 (18:37 +0000)
commit24a92577ae4a77bf55f95636395314c20888c32c
tree8194884b4b416d55142d587a7fcc554ffa1aed6b
parent641cf2d3de59d8680390f24ea4ff8f5171926c88
callout(9): Fix a race between CPU migration and callout_drain()

Suppose a running callout re-arms itself, and before the callout
finishes running another CPU calls callout_drain() and goes to sleep.
softclock_call_cc() will wake up the draining thread, which may not run
immediately if there is a lot of CPU load.  Furthermore, the callout is
still in the callout wheel so it can continue to run and re-arm itself.
Then, suppose that the callout migrates to another CPU before the
draining thread gets a chance to run.  The draining thread is in this
loop in _callout_stop_safe():

while (cc_exec_curr(cc) == c) {
CC_UNLOCK(cc);
sleep();
CC_LOCK(cc);
}

but after the migration, cc points to the wrong CPU's callout state.
Then the draining thread goes off and removes the callout from the
wheel, but does so using the wrong lock and per-CPU callout state.

Fix the problem by doing a re-lookup of the callout CPU after sleeping.

Reported by: syzbot+79569cd4d76636b2cc1c@syzkaller.appspotmail.com
Reported by: syzbot+1b27e0237aa22d8adffa@syzkaller.appspotmail.com
Reported by: syzbot+e21aa5b85a9aff90ef3e@syzkaller.appspotmail.com
Reviewed by: emaste, hselasky
Tested by: pho
MFC after: 1 week
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D27266
sys/kern/kern_timeout.c