| From dd1c428188101dd5428aa7bb9ed1a1329a052763 Mon Sep 17 00:00:00 2001 |
| From: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| Date: Thu, 15 Dec 2016 13:09:59 -0800 |
| Subject: [PATCH 3/3] add CONFIG_READONLY_USERMODEHELPER support for lots of |
| places. |
| |
| Dynamic usermode helper should be stopped, so support it... |
| --- |
| arch/x86/kernel/cpu/mcheck/mce.c | 12 ++++++++---- |
| drivers/block/drbd/drbd_int.h | 2 +- |
| drivers/block/drbd/drbd_main.c | 4 +++- |
| drivers/block/drbd/drbd_nl.c | 4 ++-- |
| drivers/video/fbdev/uvesafb.c | 17 +++++++++++------ |
| fs/nfs/cache_lib.c | 12 +++++++++--- |
| include/linux/kobject.h | 3 ++- |
| include/linux/reboot.h | 3 ++- |
| kernel/ksysfs.c | 6 +++++- |
| kernel/reboot.c | 2 +- |
| kernel/sysctl.c | 4 ++++ |
| lib/kobject_uevent.c | 4 ++-- |
| 12 files changed, 50 insertions(+), 23 deletions(-) |
| |
| --- a/arch/x86/kernel/cpu/mcheck/mce.c |
| +++ b/arch/x86/kernel/cpu/mcheck/mce.c |
| @@ -2292,15 +2292,16 @@ static ssize_t set_bank(struct device *s |
| } |
| |
| static ssize_t |
| -show_trigger(struct device *s, struct device_attribute *attr, char *buf) |
| +trigger_show(struct device *s, struct device_attribute *attr, char *buf) |
| { |
| strcpy(buf, mce_helper); |
| strcat(buf, "\n"); |
| return strlen(mce_helper) + 1; |
| } |
| |
| -static ssize_t set_trigger(struct device *s, struct device_attribute *attr, |
| - const char *buf, size_t siz) |
| +#ifndef CONFIG_READONLY_USERMODEHELPER |
| +static ssize_t trigger_store(struct device *s, struct device_attribute *attr, |
| + const char *buf, size_t siz) |
| { |
| char *p; |
| |
| @@ -2313,6 +2314,10 @@ static ssize_t set_trigger(struct device |
| |
| return strlen(mce_helper) + !!p; |
| } |
| +static DEVICE_ATTR_RW(trigger); |
| +#else |
| +static DEVICE_ATTR_RO(trigger); |
| +#endif |
| |
| static ssize_t set_ignore_ce(struct device *s, |
| struct device_attribute *attr, |
| @@ -2370,7 +2375,6 @@ static ssize_t store_int_with_restart(st |
| return ret; |
| } |
| |
| -static DEVICE_ATTR(trigger, 0644, show_trigger, set_trigger); |
| static DEVICE_INT_ATTR(tolerant, 0644, mca_cfg.tolerant); |
| static DEVICE_INT_ATTR(monarch_timeout, 0644, mca_cfg.monarch_timeout); |
| static DEVICE_BOOL_ATTR(dont_log_ce, 0644, mca_cfg.dont_log_ce); |
| --- a/drivers/block/drbd/drbd_int.h |
| +++ b/drivers/block/drbd/drbd_int.h |
| @@ -75,7 +75,7 @@ extern int fault_rate; |
| extern int fault_devs; |
| #endif |
| |
| -extern char drbd_usermode_helper[]; |
| +extern char __ro_umh drbd_usermode_helper[]; |
| |
| |
| /* This is used to stop/restart our threads. |
| --- a/drivers/block/drbd/drbd_main.c |
| +++ b/drivers/block/drbd/drbd_main.c |
| @@ -109,9 +109,11 @@ int proc_details; /* Detail level |
| |
| /* Module parameter for setting the user mode helper program |
| * to run. Default is /sbin/drbdadm */ |
| -char drbd_usermode_helper[80] = "/sbin/drbdadm"; |
| +char __ro_umh drbd_usermode_helper[80] = "/sbin/drbdadm"; |
| |
| +#ifndef CONFIG_READONLY_USERMODEHELPER |
| module_param_string(usermode_helper, drbd_usermode_helper, sizeof(drbd_usermode_helper), 0644); |
| +#endif |
| |
| /* in 2.6.x, our device mapping and config info contains our virtual gendisks |
| * as member "struct gendisk *vdisk;" |
| --- a/drivers/block/drbd/drbd_nl.c |
| +++ b/drivers/block/drbd/drbd_nl.c |
| @@ -344,7 +344,7 @@ int drbd_khelper(struct drbd_device *dev |
| (char[60]) { }, /* address */ |
| NULL }; |
| char mb[14]; |
| - char *argv[] = {drbd_usermode_helper, cmd, mb, NULL }; |
| + char *argv[] = {(char *)drbd_usermode_helper, cmd, mb, NULL }; |
| struct drbd_connection *connection = first_peer_device(device)->connection; |
| struct sib_info sib; |
| int ret; |
| @@ -396,7 +396,7 @@ enum drbd_peer_state conn_khelper(struct |
| (char[60]) { }, /* address */ |
| NULL }; |
| char *resource_name = connection->resource->name; |
| - char *argv[] = {drbd_usermode_helper, cmd, resource_name, NULL }; |
| + char *argv[] = {(char *)drbd_usermode_helper, cmd, resource_name, NULL }; |
| int ret; |
| |
| setup_khelper_env(connection, envp); |
| --- a/drivers/video/fbdev/uvesafb.c |
| +++ b/drivers/video/fbdev/uvesafb.c |
| @@ -30,7 +30,7 @@ static struct cb_id uvesafb_cn_id = { |
| .idx = CN_IDX_V86D, |
| .val = CN_VAL_V86D_UVESAFB |
| }; |
| -static char v86d_path[PATH_MAX] = "/sbin/v86d"; |
| +static char __ro_umh v86d_path[PATH_MAX] = "/sbin/v86d"; |
| static char v86d_started; /* has v86d been started by uvesafb? */ |
| |
| static const struct fb_fix_screeninfo uvesafb_fix = { |
| @@ -114,7 +114,7 @@ static int uvesafb_helper_start(void) |
| }; |
| |
| char *argv[] = { |
| - v86d_path, |
| + (char *)v86d_path, |
| NULL, |
| }; |
| |
| @@ -1883,19 +1883,22 @@ static int uvesafb_setup(char *options) |
| } |
| #endif /* !MODULE */ |
| |
| -static ssize_t show_v86d(struct device_driver *dev, char *buf) |
| +static ssize_t v86d_show(struct device_driver *dev, char *buf) |
| { |
| return snprintf(buf, PAGE_SIZE, "%s\n", v86d_path); |
| } |
| |
| -static ssize_t store_v86d(struct device_driver *dev, const char *buf, |
| +#ifndef CONFIG_READONLY_USERMODEHELPER |
| +static ssize_t v86d_store(struct device_driver *dev, const char *buf, |
| size_t count) |
| { |
| strncpy(v86d_path, buf, PATH_MAX); |
| return count; |
| } |
| - |
| -static DRIVER_ATTR(v86d, S_IRUGO | S_IWUSR, show_v86d, store_v86d); |
| +static DRIVER_ATTR_RW(v86d); |
| +#else |
| +static DRIVER_ATTR_RO(v86d); |
| +#endif |
| |
| static int uvesafb_init(void) |
| { |
| @@ -2017,8 +2020,10 @@ MODULE_PARM_DESC(mode_option, |
| module_param(vbemode, ushort, 0); |
| MODULE_PARM_DESC(vbemode, |
| "VBE mode number to set, overrides the 'mode' option"); |
| +#ifndef CONFIG_READONLY_USERMODEHELPER |
| module_param_string(v86d, v86d_path, PATH_MAX, 0660); |
| MODULE_PARM_DESC(v86d, "Path to the v86d userspace helper."); |
| +#endif |
| |
| MODULE_LICENSE("GPL"); |
| MODULE_AUTHOR("Michal Januszewski <spock@gentoo.org>"); |
| --- a/fs/nfs/cache_lib.c |
| +++ b/fs/nfs/cache_lib.c |
| @@ -20,13 +20,16 @@ |
| #define NFS_CACHE_UPCALL_PATHLEN 256 |
| #define NFS_CACHE_UPCALL_TIMEOUT 15 |
| |
| -static char nfs_cache_getent_prog[NFS_CACHE_UPCALL_PATHLEN] = |
| +static char __ro_umh nfs_cache_getent_prog[NFS_CACHE_UPCALL_PATHLEN] = |
| "/sbin/nfs_cache_getent"; |
| static unsigned long nfs_cache_getent_timeout = NFS_CACHE_UPCALL_TIMEOUT; |
| |
| +#ifndef CONFIG_READONLY_USERMODEHELPER |
| module_param_string(cache_getent, nfs_cache_getent_prog, |
| sizeof(nfs_cache_getent_prog), 0600); |
| MODULE_PARM_DESC(cache_getent, "Path to the client cache upcall program"); |
| +#endif |
| + |
| module_param_named(cache_getent_timeout, nfs_cache_getent_timeout, ulong, 0600); |
| MODULE_PARM_DESC(cache_getent_timeout, "Timeout (in seconds) after which " |
| "the cache upcall is assumed to have failed"); |
| @@ -39,7 +42,7 @@ int nfs_cache_upcall(struct cache_detail |
| NULL |
| }; |
| char *argv[] = { |
| - nfs_cache_getent_prog, |
| + (char *)nfs_cache_getent_prog, |
| cd->name, |
| entry_name, |
| NULL |
| @@ -48,15 +51,18 @@ int nfs_cache_upcall(struct cache_detail |
| |
| if (nfs_cache_getent_prog[0] == '\0') |
| goto out; |
| - ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC); |
| + ret = call_usermodehelper(nfs_cache_getent_prog, argv, envp, |
| + UMH_WAIT_EXEC); |
| /* |
| * Disable the upcall mechanism if we're getting an ENOENT or |
| * EACCES error. The admin can re-enable it on the fly by using |
| * sysfs to set the 'cache_getent' parameter once the problem |
| * has been fixed. |
| */ |
| +#ifndef CONFIG_READONLY_USERMODEHELPER |
| if (ret == -ENOENT || ret == -EACCES) |
| nfs_cache_getent_prog[0] = '\0'; |
| +#endif |
| out: |
| return ret > 0 ? 0 : ret; |
| } |
| --- a/include/linux/kobject.h |
| +++ b/include/linux/kobject.h |
| @@ -27,6 +27,7 @@ |
| #include <linux/wait.h> |
| #include <linux/atomic.h> |
| #include <linux/workqueue.h> |
| +#include <linux/kmod.h> |
| |
| #define UEVENT_HELPER_PATH_LEN 256 |
| #define UEVENT_NUM_ENVP 32 /* number of env pointers */ |
| @@ -34,7 +35,7 @@ |
| |
| #ifdef CONFIG_UEVENT_HELPER |
| /* path to the userspace helper executed on an event */ |
| -extern char uevent_helper[]; |
| +extern char __ro_umh uevent_helper[]; |
| #endif |
| |
| /* counter to tag the uevent, read only except for the kobject core */ |
| --- a/include/linux/reboot.h |
| +++ b/include/linux/reboot.h |
| @@ -3,6 +3,7 @@ |
| |
| |
| #include <linux/notifier.h> |
| +#include <linux/kmod.h> |
| #include <uapi/linux/reboot.h> |
| |
| #define SYS_DOWN 0x0001 /* Notify of system down */ |
| @@ -68,7 +69,7 @@ extern int C_A_D; /* for sysctl */ |
| void ctrl_alt_del(void); |
| |
| #define POWEROFF_CMD_PATH_LEN 256 |
| -extern char poweroff_cmd[POWEROFF_CMD_PATH_LEN]; |
| +extern char __ro_umh poweroff_cmd[]; |
| |
| extern void orderly_poweroff(bool force); |
| extern void orderly_reboot(void); |
| --- a/kernel/ksysfs.c |
| +++ b/kernel/ksysfs.c |
| @@ -44,6 +44,7 @@ static ssize_t uevent_helper_show(struct |
| { |
| return sprintf(buf, "%s\n", uevent_helper); |
| } |
| +#ifndef CONFIG_READONLY_USERMODEHELPER |
| static ssize_t uevent_helper_store(struct kobject *kobj, |
| struct kobj_attribute *attr, |
| const char *buf, size_t count) |
| @@ -57,7 +58,10 @@ static ssize_t uevent_helper_store(struc |
| return count; |
| } |
| KERNEL_ATTR_RW(uevent_helper); |
| -#endif |
| +#else |
| +KERNEL_ATTR_RO(uevent_helper); |
| +#endif /* CONFIG_READONLY_USERMODEHELPER */ |
| +#endif /* CONFIG_UEVENT_HELPER */ |
| |
| #ifdef CONFIG_PROFILING |
| static ssize_t profiling_show(struct kobject *kobj, |
| --- a/kernel/reboot.c |
| +++ b/kernel/reboot.c |
| @@ -386,7 +386,7 @@ void ctrl_alt_del(void) |
| kill_cad_pid(SIGINT, 1); |
| } |
| |
| -char poweroff_cmd[POWEROFF_CMD_PATH_LEN] = "/sbin/poweroff"; |
| +char __ro_umh poweroff_cmd[POWEROFF_CMD_PATH_LEN] = "/sbin/poweroff"; |
| static const char reboot_cmd[] = "/sbin/reboot"; |
| |
| static int run_cmd(const char *cmd) |
| --- a/kernel/sysctl.c |
| +++ b/kernel/sysctl.c |
| @@ -663,6 +663,7 @@ static struct ctl_table kern_table[] = { |
| }, |
| #endif |
| #ifdef CONFIG_UEVENT_HELPER |
| +#ifndef CONFIG_READONLY_USERMODEHELPER |
| { |
| .procname = "hotplug", |
| .data = &uevent_helper, |
| @@ -671,6 +672,7 @@ static struct ctl_table kern_table[] = { |
| .proc_handler = proc_dostring, |
| }, |
| #endif |
| +#endif |
| #ifdef CONFIG_CHR_DEV_SG |
| { |
| .procname = "sg-big-buff", |
| @@ -1080,6 +1082,7 @@ static struct ctl_table kern_table[] = { |
| .proc_handler = proc_dointvec, |
| }, |
| #endif |
| +#ifndef CONFIG_READONLY_USERMODEHELPER |
| { |
| .procname = "poweroff_cmd", |
| .data = &poweroff_cmd, |
| @@ -1087,6 +1090,7 @@ static struct ctl_table kern_table[] = { |
| .mode = 0644, |
| .proc_handler = proc_dostring, |
| }, |
| +#endif |
| #ifdef CONFIG_KEYS |
| { |
| .procname = "keys", |
| --- a/lib/kobject_uevent.c |
| +++ b/lib/kobject_uevent.c |
| @@ -29,7 +29,7 @@ |
| |
| u64 uevent_seqnum; |
| #ifdef CONFIG_UEVENT_HELPER |
| -char uevent_helper[UEVENT_HELPER_PATH_LEN] = CONFIG_UEVENT_HELPER_PATH; |
| +char __ro_umh uevent_helper[UEVENT_HELPER_PATH_LEN] = CONFIG_UEVENT_HELPER_PATH; |
| #endif |
| #ifdef CONFIG_NET |
| struct uevent_sock { |
| @@ -137,7 +137,7 @@ static int init_uevent_argv(struct kobj_ |
| return -ENOMEM; |
| } |
| |
| - env->argv[0] = uevent_helper; |
| + env->argv[0] = (char *)uevent_helper; |
| env->argv[1] = &env->buf[env->buflen]; |
| env->argv[2] = NULL; |
| |