diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-02-22 14:44:32 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-02-22 14:44:32 -0500 |
commit | b2064617c74f301dab1448f1f9c8dbb3c8021058 (patch) | |
tree | 02998695437a023316103256e6c0242e47e4b5eb | |
parent | e30aee9e10bb5168579e047f05c3d13d09e23356 (diff) | |
parent | 17627157cda13089d8a6c1c2d35acb07334b899c (diff) |
Merge tag 'driver-core-4.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core
Pull driver core updates from Greg KH:
"Here is the "small" driver core patches for 4.11-rc1.
Not much here, some firmware documentation and self-test updates, a
debugfs code formatting issue, and a new feature for call_usermodehelper
to make it more robust on systems that want to lock it down in a more
secure way.
All of these have been linux-next for a while now with no reported
issues"
* tag 'driver-core-4.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core:
kernfs: handle null pointers while printing node name and path
Introduce STATIC_USERMODEHELPER to mediate call_usermodehelper()
Make static usermode helper binaries constant
kmod: make usermodehelper path a const string
firmware: revamp firmware documentation
selftests: firmware: send expected errors to /dev/null
selftests: firmware: only modprobe if driver is missing
platform: Print the resource range if device failed to claim
kref: prefer atomic_inc_not_zero to atomic_add_unless
debugfs: improve formatting of debugfs_real_fops()
27 files changed, 593 insertions, 173 deletions
diff --git a/Documentation/driver-api/firmware/built-in-fw.rst b/Documentation/driver-api/firmware/built-in-fw.rst new file mode 100644 index 000000000000..7300e66857f8 --- /dev/null +++ b/Documentation/driver-api/firmware/built-in-fw.rst | |||
@@ -0,0 +1,38 @@ | |||
1 | ================= | ||
2 | Built-in firmware | ||
3 | ================= | ||
4 | |||
5 | Firmware can be built-in to the kernel, this means building the firmware | ||
6 | into vmlinux directly, to enable avoiding having to look for firmware from | ||
7 | the filesystem. Instead, firmware can be looked for inside the kernel | ||
8 | directly. You can enable built-in firmware using the kernel configuration | ||
9 | options: | ||
10 | |||
11 | * CONFIG_EXTRA_FIRMWARE | ||
12 | * CONFIG_EXTRA_FIRMWARE_DIR | ||
13 | |||
14 | This should not be confused with CONFIG_FIRMWARE_IN_KERNEL, this is for drivers | ||
15 | which enables firmware to be built as part of the kernel build process. This | ||
16 | option, CONFIG_FIRMWARE_IN_KERNEL, will build all firmware for all drivers | ||
17 | enabled which ship its firmware inside the Linux kernel source tree. | ||
18 | |||
19 | There are a few reasons why you might want to consider building your firmware | ||
20 | into the kernel with CONFIG_EXTRA_FIRMWARE though: | ||
21 | |||
22 | * Speed | ||
23 | * Firmware is needed for accessing the boot device, and the user doesn't | ||
24 | want to stuff the firmware into the boot initramfs. | ||
25 | |||
26 | Even if you have these needs there are a few reasons why you may not be | ||
27 | able to make use of built-in firmware: | ||
28 | |||
29 | * Legalese - firmware is non-GPL compatible | ||
30 | * Some firmware may be optional | ||
31 | * Firmware upgrades are possible, therefore a new firmware would implicate | ||
32 | a complete kernel rebuild. | ||
33 | * Some firmware files may be really large in size. The remote-proc subsystem | ||
34 | is an example subsystem which deals with these sorts of firmware | ||
35 | * The firmware may need to be scraped out from some device specific location | ||
36 | dynamically, an example is calibration data for for some WiFi chipsets. This | ||
37 | calibration data can be unique per sold device. | ||
38 | |||
diff --git a/Documentation/driver-api/firmware/core.rst b/Documentation/driver-api/firmware/core.rst new file mode 100644 index 000000000000..1d1688cbc078 --- /dev/null +++ b/Documentation/driver-api/firmware/core.rst | |||
@@ -0,0 +1,16 @@ | |||
1 | ========================== | ||
2 | Firmware API core features | ||
3 | ========================== | ||
4 | |||
5 | The firmware API has a rich set of core features available. This section | ||
6 | documents these features. | ||
7 | |||
8 | .. toctree:: | ||
9 | |||
10 | fw_search_path | ||
11 | built-in-fw | ||
12 | firmware_cache | ||
13 | direct-fs-lookup | ||
14 | fallback-mechanisms | ||
15 | lookup-order | ||
16 | |||
diff --git a/Documentation/driver-api/firmware/direct-fs-lookup.rst b/Documentation/driver-api/firmware/direct-fs-lookup.rst new file mode 100644 index 000000000000..82b4d585a213 --- /dev/null +++ b/Documentation/driver-api/firmware/direct-fs-lookup.rst | |||
@@ -0,0 +1,30 @@ | |||
1 | ======================== | ||
2 | Direct filesystem lookup | ||
3 | ======================== | ||
4 | |||
5 | Direct filesystem lookup is the most common form of firmware lookup performed | ||
6 | by the kernel. The kernel looks for the firmware directly on the root | ||
7 | filesystem in the paths documented in the section 'Firmware search paths'. | ||
8 | The filesystem lookup is implemented in fw_get_filesystem_firmware(), it | ||
9 | uses common core kernel file loader facility kernel_read_file_from_path(). | ||
10 | The max path allowed is PATH_MAX -- currently this is 4096 characters. | ||
11 | |||
12 | It is recommended you keep /lib/firmware paths on your root filesystem, | ||
13 | avoid having a separate partition for them in order to avoid possible | ||
14 | races with lookups and avoid uses of the custom fallback mechanisms | ||
15 | documented below. | ||
16 | |||
17 | Firmware and initramfs | ||
18 | ---------------------- | ||
19 | |||
20 | Drivers which are built-in to the kernel should have the firmware integrated | ||
21 | also as part of the initramfs used to boot the kernel given that otherwise | ||
22 | a race is possible with loading the driver and the real rootfs not yet being | ||
23 | available. Stuffing the firmware into initramfs resolves this race issue, | ||
24 | however note that using initrd does not suffice to address the same race. | ||
25 | |||
26 | There are circumstances that justify not wanting to include firmware into | ||
27 | initramfs, such as dealing with large firmware firmware files for the | ||
28 | remote-proc subsystem. For such cases using a userspace fallback mechanism | ||
29 | is currently the only viable solution as only userspace can know for sure | ||
30 | when the real rootfs is ready and mounted. | ||
diff --git a/Documentation/driver-api/firmware/fallback-mechanisms.rst b/Documentation/driver-api/firmware/fallback-mechanisms.rst new file mode 100644 index 000000000000..d19354794e67 --- /dev/null +++ b/Documentation/driver-api/firmware/fallback-mechanisms.rst | |||
@@ -0,0 +1,195 @@ | |||
1 | =================== | ||
2 | Fallback mechanisms | ||
3 | =================== | ||
4 | |||
5 | A fallback mechanism is supported to allow to overcome failures to do a direct | ||
6 | filesystem lookup on the root filesystem or when the firmware simply cannot be | ||
7 | installed for practical reasons on the root filesystem. The kernel | ||
8 | configuration options related to supporting the firmware fallback mechanism are: | ||
9 | |||
10 | * CONFIG_FW_LOADER_USER_HELPER: enables building the firmware fallback | ||
11 | mechanism. Most distributions enable this option today. If enabled but | ||
12 | CONFIG_FW_LOADER_USER_HELPER_FALLBACK is disabled, only the custom fallback | ||
13 | mechanism is available and for the request_firmware_nowait() call. | ||
14 | * CONFIG_FW_LOADER_USER_HELPER_FALLBACK: force enables each request to | ||
15 | enable the kobject uevent fallback mechanism on all firmware API calls | ||
16 | except request_firmware_direct(). Most distributions disable this option | ||
17 | today. The call request_firmware_nowait() allows for one alternative | ||
18 | fallback mechanism: if this kconfig option is enabled and your second | ||
19 | argument to request_firmware_nowait(), uevent, is set to false you are | ||
20 | informing the kernel that you have a custom fallback mechanism and it will | ||
21 | manually load the firmware. Read below for more details. | ||
22 | |||
23 | Note that this means when having this configuration: | ||
24 | |||
25 | CONFIG_FW_LOADER_USER_HELPER=y | ||
26 | CONFIG_FW_LOADER_USER_HELPER_FALLBACK=n | ||
27 | |||
28 | the kobject uevent fallback mechanism will never take effect even | ||
29 | for request_firmware_nowait() when uevent is set to true. | ||
30 | |||
31 | Justifying the firmware fallback mechanism | ||
32 | ========================================== | ||
33 | |||
34 | Direct filesystem lookups may fail for a variety of reasons. Known reasons for | ||
35 | this are worth itemizing and documenting as it justifies the need for the | ||
36 | fallback mechanism: | ||
37 | |||
38 | * Race against access with the root filesystem upon bootup. | ||
39 | |||
40 | * Races upon resume from suspend. This is resolved by the firmware cache, but | ||
41 | the firmware cache is only supported if you use uevents, and its not | ||
42 | supported for request_firmware_into_buf(). | ||
43 | |||
44 | * Firmware is not accessible through typical means: | ||
45 | * It cannot be installed into the root filesystem | ||
46 | * The firmware provides very unique device specific data tailored for | ||
47 | the unit gathered with local information. An example is calibration | ||
48 | data for WiFi chipsets for mobile devices. This calibration data is | ||
49 | not common to all units, but tailored per unit. Such information may | ||
50 | be installed on a separate flash partition other than where the root | ||
51 | filesystem is provided. | ||
52 | |||
53 | Types of fallback mechanisms | ||
54 | ============================ | ||
55 | |||
56 | There are really two fallback mechanisms available using one shared sysfs | ||
57 | interface as a loading facility: | ||
58 | |||
59 | * Kobject uevent fallback mechanism | ||
60 | * Custom fallback mechanism | ||
61 | |||
62 | First lets document the shared sysfs loading facility. | ||
63 | |||
64 | Firmware sysfs loading facility | ||
65 | =============================== | ||
66 | |||
67 | In order to help device drivers upload firmware using a fallback mechanism | ||
68 | the firmware infrastructure creates a sysfs interface to enable userspace | ||
69 | to load and indicate when firmware is ready. The sysfs directory is created | ||
70 | via fw_create_instance(). This call creates a new struct device named after | ||
71 | the firmware requested, and establishes it in the device hierarchy by | ||
72 | associating the device used to make the request as the device's parent. | ||
73 | The sysfs directory's file attributes are defined and controlled through | ||
74 | the new device's class (firmare_class) and group (fw_dev_attr_groups). | ||
75 | This is actually where the original firmware_class.c file name comes from, | ||
76 | as originally the only firmware loading mechanism available was the | ||
77 | mechanism we now use as a fallback mechanism. | ||
78 | |||
79 | To load firmware using the sysfs interface we expose a loading indicator, | ||
80 | and a file upload firmware into: | ||
81 | |||
82 | * /sys/$DEVPATH/loading | ||
83 | * /sys/$DEVPATH/data | ||
84 | |||
85 | To upload firmware you will echo 1 onto the loading file to indicate | ||
86 | you are loading firmware. You then cat the firmware into the data file, | ||
87 | and you notify the kernel the firmware is ready by echo'ing 0 onto | ||
88 | the loading file. | ||
89 | |||
90 | The firmware device used to help load firmware using sysfs is only created if | ||
91 | direct firmware loading fails and if the fallback mechanism is enabled for your | ||
92 | firmware request, this is set up with fw_load_from_user_helper(). It is | ||
93 | important to re-iterate that no device is created if a direct filesystem lookup | ||
94 | succeeded. | ||
95 | |||
96 | Using:: | ||
97 | |||
98 | echo 1 > /sys/$DEVPATH/loading | ||
99 | |||
100 | Will clean any previous partial load at once and make the firmware API | ||
101 | return an error. When loading firmware the firmware_class grows a buffer | ||
102 | for the firmware in PAGE_SIZE increments to hold the image as it comes in. | ||
103 | |||
104 | firmware_data_read() and firmware_loading_show() are just provided for the | ||
105 | test_firmware driver for testing, they are not called in normal use or | ||
106 | expected to be used regularly by userspace. | ||
107 | |||
108 | Firmware kobject uevent fallback mechanism | ||
109 | ========================================== | ||
110 | |||
111 | Since a device is created for the sysfs interface to help load firmware as a | ||
112 | fallback mechanism userspace can be informed of the addition of the device by | ||
113 | relying on kobject uevents. The addition of the device into the device | ||
114 | hierarchy means the fallback mechanism for firmware loading has been initiated. | ||
115 | For details of implementation refer to _request_firmware_load(), in particular | ||
116 | on the use of dev_set_uevent_suppress() and kobject_uevent(). | ||
117 | |||
118 | The kernel's kobject uevent mechanism is implemented in lib/kobject_uevent.c, | ||
119 | it issues uevents to userspace. As a supplement to kobject uevents Linux | ||
120 | distributions could also enable CONFIG_UEVENT_HELPER_PATH, which makes use of | ||
121 | core kernel's usermode helper (UMH) functionality to call out to a userspace | ||
122 | helper for kobject uevents. In practice though no standard distribution has | ||
123 | ever used the CONFIG_UEVENT_HELPER_PATH. If CONFIG_UEVENT_HELPER_PATH is | ||
124 | enabled this binary would be called each time kobject_uevent_env() gets called | ||
125 | in the kernel for each kobject uevent triggered. | ||
126 | |||
127 | Different implementations have been supported in userspace to take advantage of | ||
128 | this fallback mechanism. When firmware loading was only possible using the | ||
129 | sysfs mechanism the userspace component "hotplug" provided the functionality of | ||
130 | monitoring for kobject events. Historically this was superseded be systemd's | ||
131 | udev, however firmware loading support was removed from udev as of systemd | ||
132 | commit be2ea723b1d0 ("udev: remove userspace firmware loading support") | ||
133 | as of v217 on August, 2014. This means most Linux distributions today are | ||
134 | not using or taking advantage of the firmware fallback mechanism provided | ||
135 | by kobject uevents. This is specially exacerbated due to the fact that most | ||
136 | distributions today disable CONFIG_FW_LOADER_USER_HELPER_FALLBACK. | ||
137 | |||
138 | Refer to do_firmware_uevent() for details of the kobject event variables | ||
139 | setup. Variables passwdd with a kobject add event: | ||
140 | |||
141 | * FIRMWARE=firmware name | ||
142 | * TIMEOUT=timeout value | ||
143 | * ASYNC=whether or not the API request was asynchronous | ||
144 | |||
145 | By default DEVPATH is set by the internal kernel kobject infrastructure. | ||
146 | Below is an example simple kobject uevent script:: | ||
147 | |||
148 | # Both $DEVPATH and $FIRMWARE are already provided in the environment. | ||
149 | MY_FW_DIR=/lib/firmware/ | ||
150 | echo 1 > /sys/$DEVPATH/loading | ||
151 | cat $MY_FW_DIR/$FIRMWARE > /sys/$DEVPATH/data | ||
152 | echo 0 > /sys/$DEVPATH/loading | ||
153 | |||
154 | Firmware custom fallback mechanism | ||
155 | ================================== | ||
156 | |||
157 | Users of the request_firmware_nowait() call have yet another option available | ||
158 | at their disposal: rely on the sysfs fallback mechanism but request that no | ||
159 | kobject uevents be issued to userspace. The original logic behind this | ||
160 | was that utilities other than udev might be required to lookup firmware | ||
161 | in non-traditional paths -- paths outside of the listing documented in the | ||
162 | section 'Direct filesystem lookup'. This option is not available to any of | ||
163 | the other API calls as uevents are always forced for them. | ||
164 | |||
165 | Since uevents are only meaningful if the fallback mechanism is enabled | ||
166 | in your kernel it would seem odd to enable uevents with kernels that do not | ||
167 | have the fallback mechanism enabled in their kernels. Unfortunately we also | ||
168 | rely on the uevent flag which can be disabled by request_firmware_nowait() to | ||
169 | also setup the firmware cache for firmware requests. As documented above, | ||
170 | the firmware cache is only set up if uevent is enabled for an API call. | ||
171 | Although this can disable the firmware cache for request_firmware_nowait() | ||
172 | calls, users of this API should not use it for the purposes of disabling | ||
173 | the cache as that was not the original purpose of the flag. Not setting | ||
174 | the uevent flag means you want to opt-in for the firmware fallback mechanism | ||
175 | but you want to suppress kobject uevents, as you have a custom solution which | ||
176 | will monitor for your device addition into the device hierarchy somehow and | ||
177 | load firmware for you through a custom path. | ||
178 | |||
179 | Firmware fallback timeout | ||
180 | ========================= | ||
181 | |||
182 | The firmware fallback mechanism has a timeout. If firmware is not loaded | ||
183 | onto the sysfs interface by the timeout value an error is sent to the | ||
184 | driver. By default the timeout is set to 60 seconds if uevents are | ||
185 | desirable, otherwise MAX_JIFFY_OFFSET is used (max timeout possible). | ||
186 | The logic behind using MAX_JIFFY_OFFSET for non-uevents is that a custom | ||
187 | solution will have as much time as it needs to load firmware. | ||
188 | |||
189 | You can customize the firmware timeout by echo'ing your desired timeout into | ||
190 | the following file: | ||
191 | |||
192 | * /sys/class/firmware/timeout | ||
193 | |||
194 | If you echo 0 into it means MAX_JIFFY_OFFSET will be used. The data type | ||
195 | for the timeout is an int. | ||
diff --git a/Documentation/driver-api/firmware/firmware_cache.rst b/Documentation/driver-api/firmware/firmware_cache.rst new file mode 100644 index 000000000000..2210e5bfb332 --- /dev/null +++ b/Documentation/driver-api/firmware/firmware_cache.rst | |||
@@ -0,0 +1,51 @@ | |||
1 | ============== | ||
2 | Firmware cache | ||
3 | ============== | ||
4 | |||
5 | When Linux resumes from suspend some device drivers require firmware lookups to | ||
6 | re-initialize devices. During resume there may be a period of time during which | ||
7 | firmware lookups are not possible, during this short period of time firmware | ||
8 | requests will fail. Time is of essence though, and delaying drivers to wait for | ||
9 | the root filesystem for firmware delays user experience with device | ||
10 | functionality. In order to support these requirements the firmware | ||
11 | infrastructure implements a firmware cache for device drivers for most API | ||
12 | calls, automatically behind the scenes. | ||
13 | |||
14 | The firmware cache makes using certain firmware API calls safe during a device | ||
15 | driver's suspend and resume callback. Users of these API calls needn't cache | ||
16 | the firmware by themselves for dealing with firmware loss during system resume. | ||
17 | |||
18 | The firmware cache works by requesting for firmware prior to suspend and | ||
19 | caching it in memory. Upon resume device drivers using the firmware API will | ||
20 | have access to the firmware immediately, without having to wait for the root | ||
21 | filesystem to mount or dealing with possible race issues with lookups as the | ||
22 | root filesystem mounts. | ||
23 | |||
24 | Some implementation details about the firmware cache setup: | ||
25 | |||
26 | * The firmware cache is setup by adding a devres entry for each device that | ||
27 | uses all synchronous call except :c:func:`request_firmware_into_buf`. | ||
28 | |||
29 | * If an asynchronous call is used the firmware cache is only set up for a | ||
30 | device if if the second argument (uevent) to request_firmware_nowait() is | ||
31 | true. When uevent is true it requests that a kobject uevent be sent to | ||
32 | userspace for the firmware request. For details refer to the Fackback | ||
33 | mechanism documented below. | ||
34 | |||
35 | * If the firmware cache is determined to be needed as per the above two | ||
36 | criteria the firmware cache is setup by adding a devres entry for the | ||
37 | device making the firmware request. | ||
38 | |||
39 | * The firmware devres entry is maintained throughout the lifetime of the | ||
40 | device. This means that even if you release_firmware() the firmware cache | ||
41 | will still be used on resume from suspend. | ||
42 | |||
43 | * The timeout for the fallback mechanism is temporarily reduced to 10 seconds | ||
44 | as the firmware cache is set up during suspend, the timeout is set back to | ||
45 | the old value you had configured after the cache is set up. | ||
46 | |||
47 | * Upon suspend any pending non-uevent firmware requests are killed to avoid | ||
48 | stalling the kernel, this is done with kill_requests_without_uevent(). Kernel | ||
49 | calls requiring the non-uevent therefore need to implement their own firmware | ||
50 | cache mechanism but must not use the firmware API on suspend. | ||
51 | |||
diff --git a/Documentation/driver-api/firmware/fw_search_path.rst b/Documentation/driver-api/firmware/fw_search_path.rst new file mode 100644 index 000000000000..a360f1009fa3 --- /dev/null +++ b/Documentation/driver-api/firmware/fw_search_path.rst | |||
@@ -0,0 +1,26 @@ | |||
1 | ===================== | ||
2 | Firmware search paths | ||
3 | ===================== | ||
4 | |||
5 | The following search paths are used to look for firmware on your | ||
6 | root filesystem. | ||
7 | |||
8 | * fw_path_para - module parameter - default is empty so this is ignored | ||
9 | * /lib/firmware/updates/UTS_RELEASE/ | ||
10 | * /lib/firmware/updates/ | ||
11 | * /lib/firmware/UTS_RELEASE/ | ||
12 | * /lib/firmware/ | ||
13 | |||
14 | The module parameter ''path'' can be passed to the firmware_class module | ||
15 | to activate the first optional custom fw_path_para. The custom path can | ||
16 | only be up to 256 characters long. The kernel parameter passed would be: | ||
17 | |||
18 | * 'firmware_class.path=$CUSTOMIZED_PATH' | ||
19 | |||
20 | There is an alternative to customize the path at run time after bootup, you | ||
21 | can use the file: | ||
22 | |||
23 | * /sys/module/firmware_class/parameters/path | ||
24 | |||
25 | You would echo into it your custom path and firmware requested will be | ||
26 | searched for there first. | ||
diff --git a/Documentation/driver-api/firmware/index.rst b/Documentation/driver-api/firmware/index.rst new file mode 100644 index 000000000000..1abe01793031 --- /dev/null +++ b/Documentation/driver-api/firmware/index.rst | |||
@@ -0,0 +1,16 @@ | |||
1 | ================== | ||
2 | Linux Firmware API | ||
3 | ================== | ||
4 | |||
5 | .. toctree:: | ||
6 | |||
7 | introduction | ||
8 | core | ||
9 | request_firmware | ||
10 | |||
11 | .. only:: subproject and html | ||
12 | |||
13 | Indices | ||
14 | ======= | ||
15 | |||
16 | * :ref:`genindex` | ||
diff --git a/Documentation/driver-api/firmware/introduction.rst b/Documentation/driver-api/firmware/introduction.rst new file mode 100644 index 000000000000..211cb44eb972 --- /dev/null +++ b/Documentation/driver-api/firmware/introduction.rst | |||
@@ -0,0 +1,27 @@ | |||
1 | ============ | ||
2 | Introduction | ||
3 | ============ | ||
4 | |||
5 | The firmware API enables kernel code to request files required | ||
6 | for functionality from userspace, the uses vary: | ||
7 | |||
8 | * Microcode for CPU errata | ||
9 | * Device driver firmware, required to be loaded onto device | ||
10 | microcontrollers | ||
11 | * Device driver information data (calibration data, EEPROM overrides), | ||
12 | some of which can be completely optional. | ||
13 | |||
14 | Types of firmware requests | ||
15 | ========================== | ||
16 | |||
17 | There are two types of calls: | ||
18 | |||
19 | * Synchronous | ||
20 | * Asynchronous | ||
21 | |||
22 | Which one you use vary depending on your requirements, the rule of thumb | ||
23 | however is you should strive to use the asynchronous APIs unless you also | ||
24 | are already using asynchronous initialization mechanisms which will not | ||
25 | stall or delay boot. Even if loading firmware does not take a lot of time | ||
26 | processing firmware might, and this can still delay boot or initialization, | ||
27 | as such mechanisms such as asynchronous probe can help supplement drivers. | ||
diff --git a/Documentation/driver-api/firmware/lookup-order.rst b/Documentation/driver-api/firmware/lookup-order.rst new file mode 100644 index 000000000000..88c81739683c --- /dev/null +++ b/Documentation/driver-api/firmware/lookup-order.rst | |||
@@ -0,0 +1,18 @@ | |||
1 | ===================== | ||
2 | Firmware lookup order | ||
3 | ===================== | ||
4 | |||
5 | Different functionality is available to enable firmware to be found. | ||
6 | Below is chronological order of how firmware will be looked for once | ||
7 | a driver issues a firmware API call. | ||
8 | |||
9 | * The ''Built-in firmware'' is checked first, if the firmware is present we | ||
10 | return it immediately | ||
11 | * The ''Firmware cache'' is looked at next. If the firmware is found we | ||
12 | return it immediately | ||
13 | * The ''Direct filesystem lookup'' is performed next, if found we | ||
14 | return it immediately | ||
15 | * If no firmware has been found and the fallback mechanism was enabled | ||
16 | the sysfs interface is created. After this either a kobject uevent | ||
17 | is issued or the custom firmware loading is relied upon for firmware | ||
18 | loading up to the timeout value. | ||
diff --git a/Documentation/driver-api/firmware/request_firmware.rst b/Documentation/driver-api/firmware/request_firmware.rst new file mode 100644 index 000000000000..cc0aea880824 --- /dev/null +++ b/Documentation/driver-api/firmware/request_firmware.rst | |||
@@ -0,0 +1,56 @@ | |||
1 | ==================== | ||
2 | request_firmware API | ||
3 | ==================== | ||
4 | |||
5 | You would typically load firmware and then load it into your device somehow. | ||
6 | The typical firmware work flow is reflected below:: | ||
7 | |||
8 | if(request_firmware(&fw_entry, $FIRMWARE, device) == 0) | ||
9 | copy_fw_to_device(fw_entry->data, fw_entry->size); | ||
10 | release_firmware(fw_entry); | ||
11 | |||
12 | Synchronous firmware requests | ||
13 | ============================= | ||
14 | |||
15 | Synchronous firmware requests will wait until the firmware is found or until | ||
16 | an error is returned. | ||
17 | |||
18 | request_firmware | ||
19 | ---------------- | ||
20 | .. kernel-doc:: drivers/base/firmware_class.c | ||
21 | :functions: request_firmware | ||
22 | |||
23 | request_firmware_direct | ||
24 | ----------------------- | ||
25 | .. kernel-doc:: drivers/base/firmware_class.c | ||
26 | :functions: request_firmware_direct | ||
27 | |||
28 | request_firmware_into_buf | ||
29 | ------------------------- | ||
30 | .. kernel-doc:: drivers/base/firmware_class.c | ||
31 | :functions: request_firmware_into_buf | ||
32 | |||
33 | Asynchronous firmware requests | ||
34 | ============================== | ||
35 | |||
36 | Asynchronous firmware requests allow driver code to not have to wait | ||
37 | until the firmware or an error is returned. Function callbacks are | ||
38 | provided so that when the firmware or an error is found the driver is | ||
39 | informed through the callback. request_firmware_nowait() cannot be called | ||
40 | in atomic contexts. | ||
41 | |||
42 | request_firmware_nowait | ||
43 | ----------------------- | ||
44 | .. kernel-doc:: drivers/base/firmware_class.c | ||
45 | :functions: request_firmware_nowait | ||
46 | |||
47 | request firmware API expected driver use | ||
48 | ======================================== | ||
49 | |||
50 | Once an API call returns you process the firmware and then release the | ||
51 | firmware. For example if you used request_firmware() and it returns, | ||
52 | the driver has the firmware image accessible in fw_entry->{data,size}. | ||
53 | If something went wrong request_firmware() returns non-zero and fw_entry | ||
54 | is set to NULL. Once your driver is done with processing the firmware it | ||
55 | can call call release_firmware(fw_entry) to release the firmware image | ||
56 | and any related resource. | ||
diff --git a/Documentation/driver-api/index.rst b/Documentation/driver-api/index.rst index c5a1cd0a4ae7..dbd34c9c1d93 100644 --- a/Documentation/driver-api/index.rst +++ b/Documentation/driver-api/index.rst | |||
@@ -31,6 +31,7 @@ available subsections can be seen below. | |||
31 | vme | 31 | vme |
32 | 80211/index | 32 | 80211/index |
33 | uio-howto | 33 | uio-howto |
34 | firmware/index | ||
34 | 35 | ||
35 | .. only:: subproject and html | 36 | .. only:: subproject and html |
36 | 37 | ||
diff --git a/Documentation/firmware_class/README b/Documentation/firmware_class/README deleted file mode 100644 index cafdca8b3b15..000000000000 --- a/Documentation/firmware_class/README +++ /dev/null | |||
@@ -1,128 +0,0 @@ | |||
1 | |||
2 | request_firmware() hotplug interface: | ||
3 | ------------------------------------ | ||
4 | Copyright (C) 2003 Manuel Estrada Sainz | ||
5 | |||
6 | Why: | ||
7 | --- | ||
8 | |||
9 | Today, the most extended way to use firmware in the Linux kernel is linking | ||
10 | it statically in a header file. Which has political and technical issues: | ||
11 | |||
12 | 1) Some firmware is not legal to redistribute. | ||
13 | 2) The firmware occupies memory permanently, even though it often is just | ||
14 | used once. | ||
15 | 3) Some people, like the Debian crowd, don't consider some firmware free | ||
16 | enough and remove entire drivers (e.g.: keyspan). | ||
17 | |||
18 | High level behavior (mixed): | ||
19 | ============================ | ||
20 | |||
21 | 1), kernel(driver): | ||
22 | - calls request_firmware(&fw_entry, $FIRMWARE, device) | ||
23 | - kernel searches the firmware image with name $FIRMWARE directly | ||
24 | in the below search path of root filesystem: | ||
25 | User customized search path by module parameter 'path'[1] | ||
26 | "/lib/firmware/updates/" UTS_RELEASE, | ||
27 | "/lib/firmware/updates", | ||
28 | "/lib/firmware/" UTS_RELEASE, | ||
29 | "/lib/firmware" | ||
30 | - If found, goto 7), else goto 2) | ||
31 | |||
32 | [1], the 'path' is a string parameter which length should be less | ||
33 | than 256, user should pass 'firmware_class.path=$CUSTOMIZED_PATH' | ||
34 | if firmware_class is built in kernel(the general situation) | ||
35 | |||
36 | 2), userspace: | ||
37 | - /sys/class/firmware/xxx/{loading,data} appear. | ||
38 | - hotplug gets called with a firmware identifier in $FIRMWARE | ||
39 | and the usual hotplug environment. | ||
40 | - hotplug: echo 1 > /sys/class/firmware/xxx/loading | ||
41 | |||
42 | 3), kernel: Discard any previous partial load. | ||
43 | |||
44 | 4), userspace: | ||
45 | - hotplug: cat appropriate_firmware_image > \ | ||
46 | /sys/class/firmware/xxx/data | ||
47 | |||
48 | 5), kernel: grows a buffer in PAGE_SIZE increments to hold the image as it | ||
49 | comes in. | ||
50 | |||
51 | 6), userspace: | ||
52 | - hotplug: echo 0 > /sys/class/firmware/xxx/loading | ||
53 | |||
54 | 7), kernel: request_firmware() returns and the driver has the firmware | ||
55 | image in fw_entry->{data,size}. If something went wrong | ||
56 | request_firmware() returns non-zero and fw_entry is set to | ||
57 | NULL. | ||
58 | |||
59 | 8), kernel(driver): Driver code calls release_firmware(fw_entry) releasing | ||
60 | the firmware image and any related resource. | ||
61 | |||
62 | High level behavior (driver code): | ||
63 | ================================== | ||
64 | |||
65 | if(request_firmware(&fw_entry, $FIRMWARE, device) == 0) | ||
66 | copy_fw_to_device(fw_entry->data, fw_entry->size); | ||
67 | release_firmware(fw_entry); | ||
68 | |||
69 | Sample/simple hotplug script: | ||
70 | ============================ | ||
71 | |||
72 | # Both $DEVPATH and $FIRMWARE are already provided in the environment. | ||
73 | |||
74 | HOTPLUG_FW_DIR=/usr/lib/hotplug/firmware/ | ||
75 | |||
76 | echo 1 > /sys/$DEVPATH/loading | ||
77 | cat $HOTPLUG_FW_DIR/$FIRMWARE > /sys/$DEVPATH/data | ||
78 | echo 0 > /sys/$DEVPATH/loading | ||
79 | |||
80 | Random notes: | ||
81 | ============ | ||
82 | |||
83 | - "echo -1 > /sys/class/firmware/xxx/loading" will cancel the load at | ||
84 | once and make request_firmware() return with error. | ||
85 | |||
86 | - firmware_data_read() and firmware_loading_show() are just provided | ||
87 | for testing and completeness, they are not called in normal use. | ||
88 | |||
89 | - There is also /sys/class/firmware/timeout which holds a timeout in | ||
90 | seconds for the whole load operation. | ||
91 | |||
92 | - request_firmware_nowait() is also provided for convenience in | ||
93 | user contexts to request firmware asynchronously, but can't be called | ||
94 | in atomic contexts. | ||
95 | |||
96 | |||
97 | about in-kernel persistence: | ||
98 | --------------------------- | ||
99 | Under some circumstances, as explained below, it would be interesting to keep | ||
100 | firmware images in non-swappable kernel memory or even in the kernel image | ||
101 | (probably within initramfs). | ||
102 | |||
103 | Note that this functionality has not been implemented. | ||
104 | |||
105 | - Why OPTIONAL in-kernel persistence may be a good idea sometimes: | ||
106 | |||
107 | - If the device that needs the firmware is needed to access the | ||
108 | filesystem. When upon some error the device has to be reset and the | ||
109 | firmware reloaded, it won't be possible to get it from userspace. | ||
110 | e.g.: | ||
111 | - A diskless client with a network card that needs firmware. | ||
112 | - The filesystem is stored in a disk behind an scsi device | ||
113 | that needs firmware. | ||
114 | - Replacing buggy DSDT/SSDT ACPI tables on boot. | ||
115 | Note: this would require the persistent objects to be included | ||
116 | within the kernel image, probably within initramfs. | ||
117 | |||
118 | And the same device can be needed to access the filesystem or not depending | ||
119 | on the setup, so I think that the choice on what firmware to make | ||
120 | persistent should be left to userspace. | ||
121 | |||
122 | about firmware cache: | ||
123 | -------------------- | ||
124 | After firmware cache mechanism is introduced during system sleep, | ||
125 | request_firmware can be called safely inside device's suspend and | ||
126 | resume callback, and callers needn't cache the firmware by | ||
127 | themselves any more for dealing with firmware loss during system | ||
128 | resume. | ||
diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 647e4761dbf3..c2456839214a 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c | |||
@@ -406,7 +406,7 @@ int platform_device_add(struct platform_device *pdev) | |||
406 | } | 406 | } |
407 | 407 | ||
408 | if (p && insert_resource(p, r)) { | 408 | if (p && insert_resource(p, r)) { |
409 | dev_err(&pdev->dev, "failed to claim resource %d\n", i); | 409 | dev_err(&pdev->dev, "failed to claim resource %d: %pR\n", i, r); |
410 | ret = -EBUSY; | 410 | ret = -EBUSY; |
411 | goto failed; | 411 | goto failed; |
412 | } | 412 | } |
diff --git a/drivers/macintosh/windfarm_core.c b/drivers/macintosh/windfarm_core.c index 465d770ab0bb..5e013d781a74 100644 --- a/drivers/macintosh/windfarm_core.c +++ b/drivers/macintosh/windfarm_core.c | |||
@@ -74,8 +74,8 @@ static inline void wf_notify(int event, void *param) | |||
74 | 74 | ||
75 | static int wf_critical_overtemp(void) | 75 | static int wf_critical_overtemp(void) |
76 | { | 76 | { |
77 | static char * critical_overtemp_path = "/sbin/critical_overtemp"; | 77 | static char const critical_overtemp_path[] = "/sbin/critical_overtemp"; |
78 | char *argv[] = { critical_overtemp_path, NULL }; | 78 | char *argv[] = { (char *)critical_overtemp_path, NULL }; |
79 | static char *envp[] = { "HOME=/", | 79 | static char *envp[] = { "HOME=/", |
80 | "TERM=linux", | 80 | "TERM=linux", |
81 | "PATH=/sbin:/usr/sbin:/bin:/usr/bin", | 81 | "PATH=/sbin:/usr/sbin:/bin:/usr/bin", |
diff --git a/drivers/net/hamradio/baycom_epp.c b/drivers/net/hamradio/baycom_epp.c index 7d054697b199..594fa1407e29 100644 --- a/drivers/net/hamradio/baycom_epp.c +++ b/drivers/net/hamradio/baycom_epp.c | |||
@@ -299,7 +299,7 @@ static inline void baycom_int_freq(struct baycom_state *bc) | |||
299 | * eppconfig_path should be setable via /proc/sys. | 299 | * eppconfig_path should be setable via /proc/sys. |
300 | */ | 300 | */ |
301 | 301 | ||
302 | static char eppconfig_path[256] = "/usr/sbin/eppfpga"; | 302 | static char const eppconfig_path[] = "/usr/sbin/eppfpga"; |
303 | 303 | ||
304 | static char *envp[] = { "HOME=/", "TERM=linux", "PATH=/usr/bin:/bin", NULL }; | 304 | static char *envp[] = { "HOME=/", "TERM=linux", "PATH=/usr/bin:/bin", NULL }; |
305 | 305 | ||
@@ -308,8 +308,12 @@ static int eppconfig(struct baycom_state *bc) | |||
308 | { | 308 | { |
309 | char modearg[256]; | 309 | char modearg[256]; |
310 | char portarg[16]; | 310 | char portarg[16]; |
311 | char *argv[] = { eppconfig_path, "-s", "-p", portarg, "-m", modearg, | 311 | char *argv[] = { |
312 | NULL }; | 312 | (char *)eppconfig_path, |
313 | "-s", | ||
314 | "-p", portarg, | ||
315 | "-m", modearg, | ||
316 | NULL }; | ||
313 | 317 | ||
314 | /* set up arguments */ | 318 | /* set up arguments */ |
315 | sprintf(modearg, "%sclk,%smodem,fclk=%d,bps=%d,divider=%d%s,extstat", | 319 | sprintf(modearg, "%sclk,%smodem,fclk=%d,bps=%d,divider=%d%s,extstat", |
diff --git a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c index c38a5b9733c8..0ced908e7aa8 100644 --- a/drivers/pnp/pnpbios/core.c +++ b/drivers/pnp/pnpbios/core.c | |||
@@ -98,6 +98,7 @@ static struct completion unload_sem; | |||
98 | */ | 98 | */ |
99 | static int pnp_dock_event(int dock, struct pnp_docking_station_info *info) | 99 | static int pnp_dock_event(int dock, struct pnp_docking_station_info *info) |
100 | { | 100 | { |
101 | static char const sbin_pnpbios[] = "/sbin/pnpbios"; | ||
101 | char *argv[3], **envp, *buf, *scratch; | 102 | char *argv[3], **envp, *buf, *scratch; |
102 | int i = 0, value; | 103 | int i = 0, value; |
103 | 104 | ||
@@ -112,7 +113,7 @@ static int pnp_dock_event(int dock, struct pnp_docking_station_info *info) | |||
112 | * integrated into the driver core and use the usual infrastructure | 113 | * integrated into the driver core and use the usual infrastructure |
113 | * like sysfs and uevents | 114 | * like sysfs and uevents |
114 | */ | 115 | */ |
115 | argv[0] = "/sbin/pnpbios"; | 116 | argv[0] = (char *)sbin_pnpbios; |
116 | argv[1] = "dock"; | 117 | argv[1] = "dock"; |
117 | argv[2] = NULL; | 118 | argv[2] = NULL; |
118 | 119 | ||
@@ -139,7 +140,7 @@ static int pnp_dock_event(int dock, struct pnp_docking_station_info *info) | |||
139 | info->location_id, info->serial, info->capabilities); | 140 | info->location_id, info->serial, info->capabilities); |
140 | envp[i] = NULL; | 141 | envp[i] = NULL; |
141 | 142 | ||
142 | value = call_usermodehelper(argv [0], argv, envp, UMH_WAIT_EXEC); | 143 | value = call_usermodehelper(sbin_pnpbios, argv, envp, UMH_WAIT_EXEC); |
143 | kfree(buf); | 144 | kfree(buf); |
144 | kfree(envp); | 145 | kfree(envp); |
145 | return 0; | 146 | return 0; |
diff --git a/drivers/staging/greybus/svc_watchdog.c b/drivers/staging/greybus/svc_watchdog.c index 3729460fb954..12cef5c06e27 100644 --- a/drivers/staging/greybus/svc_watchdog.c +++ b/drivers/staging/greybus/svc_watchdog.c | |||
@@ -44,14 +44,14 @@ static int svc_watchdog_pm_notifier(struct notifier_block *notifier, | |||
44 | 44 | ||
45 | static void greybus_reset(struct work_struct *work) | 45 | static void greybus_reset(struct work_struct *work) |
46 | { | 46 | { |
47 | static char start_path[256] = "/system/bin/start"; | 47 | static char const start_path[] = "/system/bin/start"; |
48 | static char *envp[] = { | 48 | static char *envp[] = { |
49 | "HOME=/", | 49 | "HOME=/", |
50 | "PATH=/sbin:/vendor/bin:/system/sbin:/system/bin:/system/xbin", | 50 | "PATH=/sbin:/vendor/bin:/system/sbin:/system/bin:/system/xbin", |
51 | NULL, | 51 | NULL, |
52 | }; | 52 | }; |
53 | static char *argv[] = { | 53 | static char *argv[] = { |
54 | start_path, | 54 | (char *)start_path, |
55 | "unipro_reset", | 55 | "unipro_reset", |
56 | NULL, | 56 | NULL, |
57 | }; | 57 | }; |
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c b/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c index 9bc284812c30..dbb58fb16482 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c | |||
@@ -268,8 +268,8 @@ void rtl92e_dm_watchdog(struct net_device *dev) | |||
268 | static void _rtl92e_dm_check_ac_dc_power(struct net_device *dev) | 268 | static void _rtl92e_dm_check_ac_dc_power(struct net_device *dev) |
269 | { | 269 | { |
270 | struct r8192_priv *priv = rtllib_priv(dev); | 270 | struct r8192_priv *priv = rtllib_priv(dev); |
271 | static char *ac_dc_script = "/etc/acpi/wireless-rtl-ac-dc-power.sh"; | 271 | static char const ac_dc_script[] = "/etc/acpi/wireless-rtl-ac-dc-power.sh"; |
272 | char *argv[] = {ac_dc_script, DRV_NAME, NULL}; | 272 | char *argv[] = {(char *)ac_dc_script, DRV_NAME, NULL}; |
273 | static char *envp[] = {"HOME=/", | 273 | static char *envp[] = {"HOME=/", |
274 | "TERM=linux", | 274 | "TERM=linux", |
275 | "PATH=/usr/bin:/bin", | 275 | "PATH=/usr/bin:/bin", |
@@ -1823,7 +1823,7 @@ static void _rtl92e_dm_check_rf_ctrl_gpio(void *data) | |||
1823 | enum rt_rf_power_state eRfPowerStateToSet; | 1823 | enum rt_rf_power_state eRfPowerStateToSet; |
1824 | bool bActuallySet = false; | 1824 | bool bActuallySet = false; |
1825 | char *argv[3]; | 1825 | char *argv[3]; |
1826 | static char *RadioPowerPath = "/etc/acpi/events/RadioPower.sh"; | 1826 | static char const RadioPowerPath[] = "/etc/acpi/events/RadioPower.sh"; |
1827 | static char *envp[] = {"HOME=/", "TERM=linux", "PATH=/usr/bin:/bin", | 1827 | static char *envp[] = {"HOME=/", "TERM=linux", "PATH=/usr/bin:/bin", |
1828 | NULL}; | 1828 | NULL}; |
1829 | 1829 | ||
@@ -1862,7 +1862,7 @@ static void _rtl92e_dm_check_rf_ctrl_gpio(void *data) | |||
1862 | else | 1862 | else |
1863 | argv[1] = "RFON"; | 1863 | argv[1] = "RFON"; |
1864 | 1864 | ||
1865 | argv[0] = RadioPowerPath; | 1865 | argv[0] = (char *)RadioPowerPath; |
1866 | argv[2] = NULL; | 1866 | argv[2] = NULL; |
1867 | call_usermodehelper(RadioPowerPath, argv, envp, UMH_WAIT_PROC); | 1867 | call_usermodehelper(RadioPowerPath, argv, envp, UMH_WAIT_PROC); |
1868 | } | 1868 | } |
diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c index cf4c636ff4da..439b946c4808 100644 --- a/fs/kernfs/dir.c +++ b/fs/kernfs/dir.c | |||
@@ -41,6 +41,9 @@ static bool kernfs_lockdep(struct kernfs_node *kn) | |||
41 | 41 | ||
42 | static int kernfs_name_locked(struct kernfs_node *kn, char *buf, size_t buflen) | 42 | static int kernfs_name_locked(struct kernfs_node *kn, char *buf, size_t buflen) |
43 | { | 43 | { |
44 | if (!kn) | ||
45 | return strlcpy(buf, "(null)", buflen); | ||
46 | |||
44 | return strlcpy(buf, kn->parent ? kn->name : "/", buflen); | 47 | return strlcpy(buf, kn->parent ? kn->name : "/", buflen); |
45 | } | 48 | } |
46 | 49 | ||
@@ -110,6 +113,8 @@ static struct kernfs_node *kernfs_common_ancestor(struct kernfs_node *a, | |||
110 | * kn_to: /n1/n2/n3 [depth=3] | 113 | * kn_to: /n1/n2/n3 [depth=3] |
111 | * result: /../.. | 114 | * result: /../.. |
112 | * | 115 | * |
116 | * [3] when @kn_to is NULL result will be "(null)" | ||
117 | * | ||
113 | * Returns the length of the full path. If the full length is equal to or | 118 | * Returns the length of the full path. If the full length is equal to or |
114 | * greater than @buflen, @buf contains the truncated path with the trailing | 119 | * greater than @buflen, @buf contains the truncated path with the trailing |
115 | * '\0'. On error, -errno is returned. | 120 | * '\0'. On error, -errno is returned. |
@@ -123,6 +128,9 @@ static int kernfs_path_from_node_locked(struct kernfs_node *kn_to, | |||
123 | size_t depth_from, depth_to, len = 0; | 128 | size_t depth_from, depth_to, len = 0; |
124 | int i, j; | 129 | int i, j; |
125 | 130 | ||
131 | if (!kn_to) | ||
132 | return strlcpy(buf, "(null)", buflen); | ||
133 | |||
126 | if (!kn_from) | 134 | if (!kn_from) |
127 | kn_from = kernfs_root(kn_to)->kn; | 135 | kn_from = kernfs_root(kn_to)->kn; |
128 | 136 | ||
@@ -166,6 +174,8 @@ static int kernfs_path_from_node_locked(struct kernfs_node *kn_to, | |||
166 | * similar to strlcpy(). It returns the length of @kn's name and if @buf | 174 | * similar to strlcpy(). It returns the length of @kn's name and if @buf |
167 | * isn't long enough, it's filled upto @buflen-1 and nul terminated. | 175 | * isn't long enough, it's filled upto @buflen-1 and nul terminated. |
168 | * | 176 | * |
177 | * Fills buffer with "(null)" if @kn is NULL. | ||
178 | * | ||
169 | * This function can be called from any context. | 179 | * This function can be called from any context. |
170 | */ | 180 | */ |
171 | int kernfs_name(struct kernfs_node *kn, char *buf, size_t buflen) | 181 | int kernfs_name(struct kernfs_node *kn, char *buf, size_t buflen) |
diff --git a/fs/nfsd/nfs4layouts.c b/fs/nfsd/nfs4layouts.c index 1fc07a9c70e9..e122da696f1b 100644 --- a/fs/nfsd/nfs4layouts.c +++ b/fs/nfsd/nfs4layouts.c | |||
@@ -614,6 +614,7 @@ nfsd4_cb_layout_fail(struct nfs4_layout_stateid *ls) | |||
614 | { | 614 | { |
615 | struct nfs4_client *clp = ls->ls_stid.sc_client; | 615 | struct nfs4_client *clp = ls->ls_stid.sc_client; |
616 | char addr_str[INET6_ADDRSTRLEN]; | 616 | char addr_str[INET6_ADDRSTRLEN]; |
617 | static char const nfsd_recall_failed[] = "/sbin/nfsd-recall-failed"; | ||
617 | static char *envp[] = { | 618 | static char *envp[] = { |
618 | "HOME=/", | 619 | "HOME=/", |
619 | "TERM=linux", | 620 | "TERM=linux", |
@@ -629,12 +630,13 @@ nfsd4_cb_layout_fail(struct nfs4_layout_stateid *ls) | |||
629 | "nfsd: client %s failed to respond to layout recall. " | 630 | "nfsd: client %s failed to respond to layout recall. " |
630 | " Fencing..\n", addr_str); | 631 | " Fencing..\n", addr_str); |
631 | 632 | ||
632 | argv[0] = "/sbin/nfsd-recall-failed"; | 633 | argv[0] = (char *)nfsd_recall_failed; |
633 | argv[1] = addr_str; | 634 | argv[1] = addr_str; |
634 | argv[2] = ls->ls_file->f_path.mnt->mnt_sb->s_id; | 635 | argv[2] = ls->ls_file->f_path.mnt->mnt_sb->s_id; |
635 | argv[3] = NULL; | 636 | argv[3] = NULL; |
636 | 637 | ||
637 | error = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC); | 638 | error = call_usermodehelper(nfsd_recall_failed, argv, envp, |
639 | UMH_WAIT_PROC); | ||
638 | if (error) { | 640 | if (error) { |
639 | printk(KERN_ERR "nfsd: fence failed for client %s: %d!\n", | 641 | printk(KERN_ERR "nfsd: fence failed for client %s: %d!\n", |
640 | addr_str, error); | 642 | addr_str, error); |
diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h index c0befcf41b58..9d571acd3a48 100644 --- a/include/linux/debugfs.h +++ b/include/linux/debugfs.h | |||
@@ -52,8 +52,7 @@ extern struct srcu_struct debugfs_srcu; | |||
52 | * Must only be called under the protection established by | 52 | * Must only be called under the protection established by |
53 | * debugfs_use_file_start(). | 53 | * debugfs_use_file_start(). |
54 | */ | 54 | */ |
55 | static inline const struct file_operations * | 55 | static inline const struct file_operations *debugfs_real_fops(const struct file *filp) |
56 | debugfs_real_fops(const struct file *filp) | ||
57 | __must_hold(&debugfs_srcu) | 56 | __must_hold(&debugfs_srcu) |
58 | { | 57 | { |
59 | /* | 58 | /* |
diff --git a/include/linux/kmod.h b/include/linux/kmod.h index fcfd2bf14d3f..c4e441e00db5 100644 --- a/include/linux/kmod.h +++ b/include/linux/kmod.h | |||
@@ -56,7 +56,7 @@ struct file; | |||
56 | struct subprocess_info { | 56 | struct subprocess_info { |
57 | struct work_struct work; | 57 | struct work_struct work; |
58 | struct completion *complete; | 58 | struct completion *complete; |
59 | char *path; | 59 | const char *path; |
60 | char **argv; | 60 | char **argv; |
61 | char **envp; | 61 | char **envp; |
62 | int wait; | 62 | int wait; |
@@ -67,10 +67,11 @@ struct subprocess_info { | |||
67 | }; | 67 | }; |
68 | 68 | ||
69 | extern int | 69 | extern int |
70 | call_usermodehelper(char *path, char **argv, char **envp, int wait); | 70 | call_usermodehelper(const char *path, char **argv, char **envp, int wait); |
71 | 71 | ||
72 | extern struct subprocess_info * | 72 | extern struct subprocess_info * |
73 | call_usermodehelper_setup(char *path, char **argv, char **envp, gfp_t gfp_mask, | 73 | call_usermodehelper_setup(const char *path, char **argv, char **envp, |
74 | gfp_t gfp_mask, | ||
74 | int (*init)(struct subprocess_info *info, struct cred *new), | 75 | int (*init)(struct subprocess_info *info, struct cred *new), |
75 | void (*cleanup)(struct subprocess_info *), void *data); | 76 | void (*cleanup)(struct subprocess_info *), void *data); |
76 | 77 | ||
diff --git a/include/trace/events/cgroup.h b/include/trace/events/cgroup.h index ab68640a18d0..c226f50e88fa 100644 --- a/include/trace/events/cgroup.h +++ b/include/trace/events/cgroup.h | |||
@@ -61,19 +61,15 @@ DECLARE_EVENT_CLASS(cgroup, | |||
61 | __field( int, id ) | 61 | __field( int, id ) |
62 | __field( int, level ) | 62 | __field( int, level ) |
63 | __dynamic_array(char, path, | 63 | __dynamic_array(char, path, |
64 | cgrp->kn ? cgroup_path(cgrp, NULL, 0) + 1 | 64 | cgroup_path(cgrp, NULL, 0) + 1) |
65 | : strlen("(null)")) | ||
66 | ), | 65 | ), |
67 | 66 | ||
68 | TP_fast_assign( | 67 | TP_fast_assign( |
69 | __entry->root = cgrp->root->hierarchy_id; | 68 | __entry->root = cgrp->root->hierarchy_id; |
70 | __entry->id = cgrp->id; | 69 | __entry->id = cgrp->id; |
71 | __entry->level = cgrp->level; | 70 | __entry->level = cgrp->level; |
72 | if (cgrp->kn) | 71 | cgroup_path(cgrp, __get_dynamic_array(path), |
73 | cgroup_path(cgrp, __get_dynamic_array(path), | 72 | __get_dynamic_array_len(path)); |
74 | __get_dynamic_array_len(path)); | ||
75 | else | ||
76 | __assign_str(path, "(null)"); | ||
77 | ), | 73 | ), |
78 | 74 | ||
79 | TP_printk("root=%d id=%d level=%d path=%s", | 75 | TP_printk("root=%d id=%d level=%d path=%s", |
@@ -119,8 +115,7 @@ DECLARE_EVENT_CLASS(cgroup_migrate, | |||
119 | __field( int, dst_id ) | 115 | __field( int, dst_id ) |
120 | __field( int, dst_level ) | 116 | __field( int, dst_level ) |
121 | __dynamic_array(char, dst_path, | 117 | __dynamic_array(char, dst_path, |
122 | dst_cgrp->kn ? cgroup_path(dst_cgrp, NULL, 0) + 1 | 118 | cgroup_path(dst_cgrp, NULL, 0) + 1) |
123 | : strlen("(null)")) | ||
124 | __field( int, pid ) | 119 | __field( int, pid ) |
125 | __string( comm, task->comm ) | 120 | __string( comm, task->comm ) |
126 | ), | 121 | ), |
@@ -129,11 +124,8 @@ DECLARE_EVENT_CLASS(cgroup_migrate, | |||
129 | __entry->dst_root = dst_cgrp->root->hierarchy_id; | 124 | __entry->dst_root = dst_cgrp->root->hierarchy_id; |
130 | __entry->dst_id = dst_cgrp->id; | 125 | __entry->dst_id = dst_cgrp->id; |
131 | __entry->dst_level = dst_cgrp->level; | 126 | __entry->dst_level = dst_cgrp->level; |
132 | if (dst_cgrp->kn) | 127 | cgroup_path(dst_cgrp, __get_dynamic_array(dst_path), |
133 | cgroup_path(dst_cgrp, __get_dynamic_array(dst_path), | 128 | __get_dynamic_array_len(dst_path)); |
134 | __get_dynamic_array_len(dst_path)); | ||
135 | else | ||
136 | __assign_str(dst_path, "(null)"); | ||
137 | __entry->pid = task->pid; | 129 | __entry->pid = task->pid; |
138 | __assign_str(comm, task->comm); | 130 | __assign_str(comm, task->comm); |
139 | ), | 131 | ), |
diff --git a/kernel/kmod.c b/kernel/kmod.c index d45c96073afb..0c407f905ca4 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c | |||
@@ -516,7 +516,7 @@ static void helper_unlock(void) | |||
516 | * Function must be runnable in either a process context or the | 516 | * Function must be runnable in either a process context or the |
517 | * context in which call_usermodehelper_exec is called. | 517 | * context in which call_usermodehelper_exec is called. |
518 | */ | 518 | */ |
519 | struct subprocess_info *call_usermodehelper_setup(char *path, char **argv, | 519 | struct subprocess_info *call_usermodehelper_setup(const char *path, char **argv, |
520 | char **envp, gfp_t gfp_mask, | 520 | char **envp, gfp_t gfp_mask, |
521 | int (*init)(struct subprocess_info *info, struct cred *new), | 521 | int (*init)(struct subprocess_info *info, struct cred *new), |
522 | void (*cleanup)(struct subprocess_info *info), | 522 | void (*cleanup)(struct subprocess_info *info), |
@@ -528,7 +528,12 @@ struct subprocess_info *call_usermodehelper_setup(char *path, char **argv, | |||
528 | goto out; | 528 | goto out; |
529 | 529 | ||
530 | INIT_WORK(&sub_info->work, call_usermodehelper_exec_work); | 530 | INIT_WORK(&sub_info->work, call_usermodehelper_exec_work); |
531 | |||
532 | #ifdef CONFIG_STATIC_USERMODEHELPER | ||
533 | sub_info->path = CONFIG_STATIC_USERMODEHELPER_PATH; | ||
534 | #else | ||
531 | sub_info->path = path; | 535 | sub_info->path = path; |
536 | #endif | ||
532 | sub_info->argv = argv; | 537 | sub_info->argv = argv; |
533 | sub_info->envp = envp; | 538 | sub_info->envp = envp; |
534 | 539 | ||
@@ -566,6 +571,15 @@ int call_usermodehelper_exec(struct subprocess_info *sub_info, int wait) | |||
566 | retval = -EBUSY; | 571 | retval = -EBUSY; |
567 | goto out; | 572 | goto out; |
568 | } | 573 | } |
574 | |||
575 | /* | ||
576 | * If there is no binary for us to call, then just return and get out of | ||
577 | * here. This allows us to set STATIC_USERMODEHELPER_PATH to "" and | ||
578 | * disable all call_usermodehelper() calls. | ||
579 | */ | ||
580 | if (strlen(sub_info->path) == 0) | ||
581 | goto out; | ||
582 | |||
569 | /* | 583 | /* |
570 | * Set the completion pointer only if there is a waiter. | 584 | * Set the completion pointer only if there is a waiter. |
571 | * This makes it possible to use umh_complete to free | 585 | * This makes it possible to use umh_complete to free |
@@ -613,7 +627,7 @@ EXPORT_SYMBOL(call_usermodehelper_exec); | |||
613 | * This function is the equivalent to use call_usermodehelper_setup() and | 627 | * This function is the equivalent to use call_usermodehelper_setup() and |
614 | * call_usermodehelper_exec(). | 628 | * call_usermodehelper_exec(). |
615 | */ | 629 | */ |
616 | int call_usermodehelper(char *path, char **argv, char **envp, int wait) | 630 | int call_usermodehelper(const char *path, char **argv, char **envp, int wait) |
617 | { | 631 | { |
618 | struct subprocess_info *info; | 632 | struct subprocess_info *info; |
619 | gfp_t gfp_mask = (wait == UMH_NO_WAIT) ? GFP_ATOMIC : GFP_KERNEL; | 633 | gfp_t gfp_mask = (wait == UMH_NO_WAIT) ? GFP_ATOMIC : GFP_KERNEL; |
diff --git a/security/Kconfig b/security/Kconfig index 118f4549404e..d900f47eaa68 100644 --- a/security/Kconfig +++ b/security/Kconfig | |||
@@ -158,6 +158,41 @@ config HARDENED_USERCOPY_PAGESPAN | |||
158 | been removed. This config is intended to be used only while | 158 | been removed. This config is intended to be used only while |
159 | trying to find such users. | 159 | trying to find such users. |
160 | 160 | ||
161 | config STATIC_USERMODEHELPER | ||
162 | bool "Force all usermode helper calls through a single binary" | ||
163 | help | ||
164 | By default, the kernel can call many different userspace | ||
165 | binary programs through the "usermode helper" kernel | ||
166 | interface. Some of these binaries are statically defined | ||
167 | either in the kernel code itself, or as a kernel configuration | ||
168 | option. However, some of these are dynamically created at | ||
169 | runtime, or can be modified after the kernel has started up. | ||
170 | To provide an additional layer of security, route all of these | ||
171 | calls through a single executable that can not have its name | ||
172 | changed. | ||
173 | |||
174 | Note, it is up to this single binary to then call the relevant | ||
175 | "real" usermode helper binary, based on the first argument | ||
176 | passed to it. If desired, this program can filter and pick | ||
177 | and choose what real programs are called. | ||
178 | |||
179 | If you wish for all usermode helper programs are to be | ||
180 | disabled, choose this option and then set | ||
181 | STATIC_USERMODEHELPER_PATH to an empty string. | ||
182 | |||
183 | config STATIC_USERMODEHELPER_PATH | ||
184 | string "Path to the static usermode helper binary" | ||
185 | depends on STATIC_USERMODEHELPER | ||
186 | default "/sbin/usermode-helper" | ||
187 | help | ||
188 | The binary called by the kernel when any usermode helper | ||
189 | program is wish to be run. The "real" application's name will | ||
190 | be in the first argument passed to this program on the command | ||
191 | line. | ||
192 | |||
193 | If you wish for all usermode helper programs to be disabled, | ||
194 | specify an empty string here (i.e. ""). | ||
195 | |||
161 | source security/selinux/Kconfig | 196 | source security/selinux/Kconfig |
162 | source security/smack/Kconfig | 197 | source security/smack/Kconfig |
163 | source security/tomoyo/Kconfig | 198 | source security/tomoyo/Kconfig |
diff --git a/security/keys/request_key.c b/security/keys/request_key.c index 43affcf10b22..9822e500d50d 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c | |||
@@ -72,7 +72,7 @@ static void umh_keys_cleanup(struct subprocess_info *info) | |||
72 | /* | 72 | /* |
73 | * Call a usermode helper with a specific session keyring. | 73 | * Call a usermode helper with a specific session keyring. |
74 | */ | 74 | */ |
75 | static int call_usermodehelper_keys(char *path, char **argv, char **envp, | 75 | static int call_usermodehelper_keys(const char *path, char **argv, char **envp, |
76 | struct key *session_keyring, int wait) | 76 | struct key *session_keyring, int wait) |
77 | { | 77 | { |
78 | struct subprocess_info *info; | 78 | struct subprocess_info *info; |
@@ -95,6 +95,7 @@ static int call_sbin_request_key(struct key_construction *cons, | |||
95 | const char *op, | 95 | const char *op, |
96 | void *aux) | 96 | void *aux) |
97 | { | 97 | { |
98 | static char const request_key[] = "/sbin/request-key"; | ||
98 | const struct cred *cred = current_cred(); | 99 | const struct cred *cred = current_cred(); |
99 | key_serial_t prkey, sskey; | 100 | key_serial_t prkey, sskey; |
100 | struct key *key = cons->key, *authkey = cons->authkey, *keyring, | 101 | struct key *key = cons->key, *authkey = cons->authkey, *keyring, |
@@ -161,7 +162,7 @@ static int call_sbin_request_key(struct key_construction *cons, | |||
161 | 162 | ||
162 | /* set up the argument list */ | 163 | /* set up the argument list */ |
163 | i = 0; | 164 | i = 0; |
164 | argv[i++] = "/sbin/request-key"; | 165 | argv[i++] = (char *)request_key; |
165 | argv[i++] = (char *) op; | 166 | argv[i++] = (char *) op; |
166 | argv[i++] = key_str; | 167 | argv[i++] = key_str; |
167 | argv[i++] = uid_str; | 168 | argv[i++] = uid_str; |
@@ -172,7 +173,7 @@ static int call_sbin_request_key(struct key_construction *cons, | |||
172 | argv[i] = NULL; | 173 | argv[i] = NULL; |
173 | 174 | ||
174 | /* do it */ | 175 | /* do it */ |
175 | ret = call_usermodehelper_keys(argv[0], argv, envp, keyring, | 176 | ret = call_usermodehelper_keys(request_key, argv, envp, keyring, |
176 | UMH_WAIT_PROC); | 177 | UMH_WAIT_PROC); |
177 | kdebug("usermode -> 0x%x", ret); | 178 | kdebug("usermode -> 0x%x", ret); |
178 | if (ret >= 0) { | 179 | if (ret >= 0) { |
diff --git a/tools/testing/selftests/firmware/fw_filesystem.sh b/tools/testing/selftests/firmware/fw_filesystem.sh index 5c495ad7958a..e35691239350 100755 --- a/tools/testing/selftests/firmware/fw_filesystem.sh +++ b/tools/testing/selftests/firmware/fw_filesystem.sh | |||
@@ -5,9 +5,24 @@ | |||
5 | # know so we can be sure we're not accidentally testing the user helper. | 5 | # know so we can be sure we're not accidentally testing the user helper. |
6 | set -e | 6 | set -e |
7 | 7 | ||
8 | modprobe test_firmware | ||
9 | |||
10 | DIR=/sys/devices/virtual/misc/test_firmware | 8 | DIR=/sys/devices/virtual/misc/test_firmware |
9 | TEST_DIR=$(dirname $0) | ||
10 | |||
11 | test_modprobe() | ||
12 | { | ||
13 | if [ ! -d $DIR ]; then | ||
14 | echo "$0: $DIR not present" | ||
15 | echo "You must have the following enabled in your kernel:" | ||
16 | cat $TEST_DIR/config | ||
17 | exit 1 | ||
18 | fi | ||
19 | } | ||
20 | |||
21 | trap "test_modprobe" EXIT | ||
22 | |||
23 | if [ ! -d $DIR ]; then | ||
24 | modprobe test_firmware | ||
25 | fi | ||
11 | 26 | ||
12 | # CONFIG_FW_LOADER_USER_HELPER has a sysfs class under /sys/class/firmware/ | 27 | # CONFIG_FW_LOADER_USER_HELPER has a sysfs class under /sys/class/firmware/ |
13 | # These days no one enables CONFIG_FW_LOADER_USER_HELPER so check for that | 28 | # These days no one enables CONFIG_FW_LOADER_USER_HELPER so check for that |
@@ -48,18 +63,18 @@ echo "ABCD0123" >"$FW" | |||
48 | 63 | ||
49 | NAME=$(basename "$FW") | 64 | NAME=$(basename "$FW") |
50 | 65 | ||
51 | if printf '\000' >"$DIR"/trigger_request; then | 66 | if printf '\000' >"$DIR"/trigger_request 2> /dev/null; then |
52 | echo "$0: empty filename should not succeed" >&2 | 67 | echo "$0: empty filename should not succeed" >&2 |
53 | exit 1 | 68 | exit 1 |
54 | fi | 69 | fi |
55 | 70 | ||
56 | if printf '\000' >"$DIR"/trigger_async_request; then | 71 | if printf '\000' >"$DIR"/trigger_async_request 2> /dev/null; then |
57 | echo "$0: empty filename should not succeed (async)" >&2 | 72 | echo "$0: empty filename should not succeed (async)" >&2 |
58 | exit 1 | 73 | exit 1 |
59 | fi | 74 | fi |
60 | 75 | ||
61 | # Request a firmware that doesn't exist, it should fail. | 76 | # Request a firmware that doesn't exist, it should fail. |
62 | if echo -n "nope-$NAME" >"$DIR"/trigger_request; then | 77 | if echo -n "nope-$NAME" >"$DIR"/trigger_request 2> /dev/null; then |
63 | echo "$0: firmware shouldn't have loaded" >&2 | 78 | echo "$0: firmware shouldn't have loaded" >&2 |
64 | exit 1 | 79 | exit 1 |
65 | fi | 80 | fi |