[glsdk/meta-ti-glsdk.git] / recipes-kernel / linux / linux-ti33x-psp-3.2 / 3.2.1 / 0003-firmware-Fix-an-oops-on-reading-fw_priv-fw-in-sysfs-.patch
1 From 9fa97016831ab21d14565a478dc462f35dfb7d2b Mon Sep 17 00:00:00 2001
2 From: Neil Horman <nhorman@tuxdriver.com>
3 Date: Mon, 2 Jan 2012 15:31:23 -0500
4 Subject: [PATCH 03/49] firmware: Fix an oops on reading fw_priv->fw in sysfs
5 loading file
7 commit eea915bb0d1358755f151eaefb8208a2d5f3e10c upstream.
9 This oops was reported recently:
10 firmware_loading_store+0xf9/0x17b
11 dev_attr_store+0x20/0x22
12 sysfs_write_file+0x101/0x134
13 vfs_write+0xac/0xf3
14 sys_write+0x4a/0x6e
15 system_call_fastpath+0x16/0x1b
17 The complete backtrace was unfortunately not captured, but details can be found
18 here:
19 https://bugzilla.redhat.com/show_bug.cgi?id=769920
21 The cause is fairly clear.
23 Its caused by the fact that firmware_loading_store has a case 0 in its
24 switch statement that reads and writes the fw_priv->fw poniter without the
25 protection of the fw_lock mutex. since there is a window between the time that
26 _request_firmware sets fw_priv->fw to NULL and the time the corresponding sysfs
27 file is unregistered, its possible for a user space application to race in, and
28 write a zero to the loading file, causing a NULL dereference in
29 firmware_loading_store. Fix it by extending the protection of the fw_lock mutex
30 to cover all of the firware_loading_store function.
32 Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
33 Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
34 ---
35 drivers/base/firmware_class.c | 14 +++++++-------
36 1 files changed, 7 insertions(+), 7 deletions(-)
38 diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
39 index 06ed6b4..3719c94 100644
40 --- a/drivers/base/firmware_class.c
41 +++ b/drivers/base/firmware_class.c
42 @@ -226,13 +226,13 @@ static ssize_t firmware_loading_store(struct device *dev,
43 int loading = simple_strtol(buf, NULL, 10);
44 int i;
46 + mutex_lock(&fw_lock);
47 +
48 + if (!fw_priv->fw)
49 + goto out;
50 +
51 switch (loading) {
52 case 1:
53 - mutex_lock(&fw_lock);
54 - if (!fw_priv->fw) {
55 - mutex_unlock(&fw_lock);
56 - break;
57 - }
58 firmware_free_data(fw_priv->fw);
59 memset(fw_priv->fw, 0, sizeof(struct firmware));
60 /* If the pages are not owned by 'struct firmware' */
61 @@ -243,7 +243,6 @@ static ssize_t firmware_loading_store(struct device *dev,
62 fw_priv->page_array_size = 0;
63 fw_priv->nr_pages = 0;
64 set_bit(FW_STATUS_LOADING, &fw_priv->status);
65 - mutex_unlock(&fw_lock);
66 break;
67 case 0:
68 if (test_bit(FW_STATUS_LOADING, &fw_priv->status)) {
69 @@ -274,7 +273,8 @@ static ssize_t firmware_loading_store(struct device *dev,
70 fw_load_abort(fw_priv);
71 break;
72 }
73 -
74 +out:
75 + mutex_unlock(&fw_lock);
76 return count;
77 }
79 --
80 1.7.7.4