KernelNewbies:

Linux usermode helper enhancements

Linux has a shared framework for calling out to userspace to run and execute a userspace program, and returning to the kernel the return status of this program, this is provided by the Linux kernel usermode helper (UMH). This is implemented mainly today via the files:

This page documents some future considerations and enhancements for it.

TableOfContents(4)

Review of current usermode helper API users

As of this writing (November 16, 2016) the UMH helper code is currently used for the following purposes:

request_module()

coredump

When a program running receives certain signals (SIGSEGV or SIGQUIT) the kernel will terminate the process and generate a core dump file which can be used to debug the process. These signals can be used to debug processes which terminated unexpectedly. The kernel coredump functionality is implemented in [https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/fs/coredump.c fs/coredump.c], you can tune the pattern for the name of the file dumped using the procfs file:

/proc/sys/kernel/core_pattern

The function format_corename() parses this file and uses it to determine the core filename used. For more details refer to:

initrd linuxrc

Typically Linux distributions need to boot Linux from a block device using a filesystem, generalizing boot for all possible hardware (typical Linux distribution requirements) implicates having a large kernel with a lot of built-in functionality. Linux distributions do not wish to provide all of these drivers as built-in due to size constraints, so long ago a strategy was devised to stuff files into a file which can be mounted on RAM, and from it extract needed drivers to boot systems. One of the first generation mechanisms for this was initrd. The evolution to this mechanism is initramfs.

Upon boot the kernel processes an initrd by creating the special device file /dev/ram0 and then loading onto it the initrd file present on the filesystem as /initrd.image (see rd_load_image() implemented on [https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/init/do_mounts_rd.c init/do_mounts_rd.c]. rd_load_image() loads an initrd to ram disk /dev/ram0. This does a copy, block by block of the contents of the file onto the ramdisk. After this handle_initrd() creates /dev/root.old0 which is used (?) to mount the initrd to /root/. After this it creates the directory /old/, changes directory to it, loads default modules (load_default_modules()) and finally executes /linuxrc using the kernel UMH. Finally it mounts the initrd root to /old/ and chroots to /.

kobject uevents

[https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/lib/kobject_uevent.c lib/kobject_uevent.c] implements handling kobject uevents. The kernel UMH is used when you have set CONFIG_UEVENT_HELPER_PATH, if set then this binary will be called each time kobject_uevent_env() gets called in the kernel for each kobject uevent triggered.

Enhancement ideas

Filesystem suspend

There are very likely races when using the UMH code for each if the kernel had any scheduled kernel call or had a kthread scheduled requesting a UMH during each of these events:

To fix this we should review and generalize use of calling freeze_super() to queue superblock filesystem operations prior to each of these operations. For inspiration we can review and consider the patch being worked on by Jiri Kosina which freezes all filesystems during suspend:

https://git.kernel.org/cgit/linux/kernel/git/jikos/jikos.git/commit/?h=might-rebase/get-rid-of-kthread-freezer&id=394aa67810abefde6d79ea96a90e5d41a7df99f4

Review removal of the UMH lock

The UMH is 'only' used today by the firmware API on [https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/drivers/base/firmware_class.c drivers/base/firmware_class.c], this is used if the firmware requested was found not to be built-in, regardless of whether or not the kernel firmware usermode helper fallback is used. The firmware UMH fallback was added years ago by Rafael to help trigger a warning if drivers used the request_firmare*() API on resume, given this used is flawed when using the firmware UMH fallback. The firmware UMH fallback uses sysfs to help a user binary load firmware. Recall that back in the day we always used the firmware UMH, it was only until recent years that direct filesystem loaded was added by Linus to the kernel. Although the UMH lock was added to help warn if users called the firmware API on resume, these days it also helps protect a race against early users of the kernel trying to read files directly from the filesystem early in boot.

If we are to remove the general UMH lock we need to provide a general facility which both secures races against suspsend / resume and lastly initialization. Note that these days direct filesystem loading was generalized given a slew of different areas in the kernel were determined to use similar code to load files directly from the kernel. This effort is documented here and that work is now complete:

https://kernelnewbies.org/KernelProjects/common-kernel-loader

The new APIs then to consider are:

Although direct filesystem loading is separate from the UMH in the kernel, addressing races against the UMH should help also consider race issues with the direct filesystem loading.

The firmware cache added to the firmware API is only supported for drivers which do not explicitly require the firmware UMH fallback, this is because upon suspend the firmware code kills all pending UMH processes, and waiting on any pending UMH calls proves to in practice stall suspends. The firmware cache then is only provided for drivers that rely on and depend only on the direct filesystem loading.

KernelNewbies: KernelProjects/usermode-helper (last edited 2016-11-16 23:41:00 by mcgrof)