linux/include
Rafael J. Wysocki 247bc03742 PM / Sleep: Mitigate race between the freezer and request_firmware()
There is a race condition between the freezer and request_firmware()
such that if request_firmware() is run on one CPU and
freeze_processes() is run on another CPU and usermodehelper_disable()
called by it succeeds to grab umhelper_sem for writing before
usermodehelper_read_trylock() called from request_firmware()
acquires it for reading, the request_firmware() will fail and
trigger a WARN_ON() complaining that it was called at a wrong time.
However, in fact, it wasn't called at a wrong time and
freeze_processes() simply happened to be executed simultaneously.

To avoid this race, at least in some cases, modify
usermodehelper_read_trylock() so that it doesn't fail if the
freezing of tasks has just started and hasn't been completed yet.
Instead, during the freezing of tasks, it will try to freeze the
task that has called it so that it can wait until user space is
thawed without triggering the scary warning.

For this purpose, change usermodehelper_disabled so that it can
take three different values, UMH_ENABLED (0), UMH_FREEZING and
UMH_DISABLED.  The first one means that usermode helpers are
enabled, the last one means "hard disable" (i.e. the system is not
ready for usermode helpers to be used) and the second one
is reserved for the freezer.  Namely, when freeze_processes() is
started, it sets usermodehelper_disabled to UMH_FREEZING which
tells usermodehelper_read_trylock() that it shouldn't fail just
yet and should call try_to_freeze() if woken up and cannot
return immediately.  This way all freezable tasks that happen
to call request_firmware() right before freeze_processes() is
started and lose the race for umhelper_sem with it will be
frozen and will sleep until thaw_processes() unsets
usermodehelper_disabled.  [For the non-freezable callers of
request_firmware() the race for umhelper_sem against
freeze_processes() is unfortunately unavoidable.]

Reported-by: Stephen Boyd <sboyd@codeaurora.org>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: stable@vger.kernel.org
2012-03-28 23:30:28 +02:00
..
acpi
asm-generic The following text was taken from the original review request: 2012-03-24 10:08:39 -07:00
crypto crypto: remove the second argument of k[un]map_atomic() 2012-03-20 21:48:16 +08:00
drm The following text was taken from the original review request: 2012-03-24 10:08:39 -07:00
keys
linux PM / Sleep: Mitigate race between the freezer and request_firmware() 2012-03-28 23:30:28 +02:00
math-emu
media The following text was taken from the original review request: 2012-03-24 10:41:37 -07:00
misc
mtd
net Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net 2012-03-27 16:52:32 -07:00
pcmcia
rdma Merge branches 'cma', 'cxgb3', 'cxgb4', 'ehca', 'iser', 'mad', 'nes', 'qib', 'srp' and 'srpt' into for-next 2012-03-19 09:50:33 -07:00
rxrpc
scsi The following text was taken from the original review request: 2012-03-24 10:41:37 -07:00
sound The following text was taken from the original review request: 2012-03-24 10:41:37 -07:00
target target: Use array_zalloc for device_list 2012-03-15 19:15:51 -07:00
trace Ext4 commits for 3.3 merge window; mostly cleanups and bug fixes 2012-03-28 10:02:55 -07:00
video Merge branch 'platforms' of git://git.linaro.org/people/rmk/linux-arm 2012-03-27 18:17:02 -07:00
xen One tiny feature that accidentally got lost in the initial git pull: 2012-03-24 12:20:25 -07:00
Kbuild