diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2016-12-11 18:15:35 +0100 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2016-12-11 18:15:35 +0100 |
commit | 22276c57445de5b29e143affdabe72576ab8dce3 (patch) | |
tree | 14754e08a6fafa472065b31afe5123c47281bb58 | |
parent | 946cb48082b0bbff0bb96b3f816d0327bf409d79 (diff) | |
download | patches-22276c57445de5b29e143affdabe72576ab8dce3.tar.gz |
usermode helper patches added
-rw-r--r-- | 0001-kmod-make-usermodehelper-path-a-const-string.patch | 61 | ||||
-rw-r--r-- | 0002-drbd-rename-usermode_helper-to-drbd_usermode_helper.patch | 112 | ||||
-rw-r--r-- | 0003-Make-static-usermode-helper-binaries-constant.patch | 181 | ||||
-rw-r--r-- | 0004-Introduce-CONFIG_READONLY_USERMODEHELPER.patch | 396 | ||||
-rw-r--r-- | c09.patch | 4 | ||||
-rw-r--r-- | series | 4 |
6 files changed, 756 insertions, 2 deletions
diff --git a/0001-kmod-make-usermodehelper-path-a-const-string.patch b/0001-kmod-make-usermodehelper-path-a-const-string.patch new file mode 100644 index 00000000000000..d7a9f87974dcf0 --- /dev/null +++ b/0001-kmod-make-usermodehelper-path-a-const-string.patch @@ -0,0 +1,61 @@ +From 359179eb6145c5982a958367197ca4b785b6b15f Mon Sep 17 00:00:00 2001 +From: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Date: Sun, 11 Dec 2016 09:44:42 +0100 +Subject: [PATCH 1/4] kmod: make usermodehelper path a const string + +This is in preparation for making it so that usermode helper programs +can't be changed, if desired, by userspace. We will tackle the mess of +cleaning up the write-ability of argv and env later, that's going to +take more work, for much less gain... + +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + include/linux/kmod.h | 7 ++++--- + kernel/kmod.c | 4 ++-- + 2 files changed, 6 insertions(+), 5 deletions(-) + +--- a/include/linux/kmod.h ++++ b/include/linux/kmod.h +@@ -56,7 +56,7 @@ struct file; + struct subprocess_info { + struct work_struct work; + struct completion *complete; +- char *path; ++ const char *path; + char **argv; + char **envp; + int wait; +@@ -67,10 +67,11 @@ struct subprocess_info { + }; + + extern int +-call_usermodehelper(char *path, char **argv, char **envp, int wait); ++call_usermodehelper(const char *path, char **argv, char **envp, int wait); + + extern struct subprocess_info * +-call_usermodehelper_setup(char *path, char **argv, char **envp, gfp_t gfp_mask, ++call_usermodehelper_setup(const char *path, char **argv, char **envp, ++ gfp_t gfp_mask, + int (*init)(struct subprocess_info *info, struct cred *new), + void (*cleanup)(struct subprocess_info *), void *data); + +--- a/kernel/kmod.c ++++ b/kernel/kmod.c +@@ -516,7 +516,7 @@ static void helper_unlock(void) + * Function must be runnable in either a process context or the + * context in which call_usermodehelper_exec is called. + */ +-struct subprocess_info *call_usermodehelper_setup(char *path, char **argv, ++struct subprocess_info *call_usermodehelper_setup(const char *path, char **argv, + char **envp, gfp_t gfp_mask, + int (*init)(struct subprocess_info *info, struct cred *new), + void (*cleanup)(struct subprocess_info *info), +@@ -613,7 +613,7 @@ EXPORT_SYMBOL(call_usermodehelper_exec); + * This function is the equivalent to use call_usermodehelper_setup() and + * call_usermodehelper_exec(). + */ +-int call_usermodehelper(char *path, char **argv, char **envp, int wait) ++int call_usermodehelper(const char *path, char **argv, char **envp, int wait) + { + struct subprocess_info *info; + gfp_t gfp_mask = (wait == UMH_NO_WAIT) ? GFP_ATOMIC : GFP_KERNEL; diff --git a/0002-drbd-rename-usermode_helper-to-drbd_usermode_helper.patch b/0002-drbd-rename-usermode_helper-to-drbd_usermode_helper.patch new file mode 100644 index 00000000000000..bf5e0a9db50a1d --- /dev/null +++ b/0002-drbd-rename-usermode_helper-to-drbd_usermode_helper.patch @@ -0,0 +1,112 @@ +From 391148315fe8357ae67131c4fef5bb539852cfea Mon Sep 17 00:00:00 2001 +From: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Date: Sun, 11 Dec 2016 10:39:09 +0100 +Subject: [PATCH 2/4] drbd: rename "usermode_helper" to "drbd_usermode_helper" + +Nothing like having a very generic global variable in a tiny driver +subsystem to make a mess of the global namespace... + +Anyway, clean it up in anticipation of making drbd_usermode_helper +read-only in a future patch. + +Note, there are many other "generic" named global variables in the drbd +subsystem, someone should fix those up one day before they hit a linking +error. + +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + drivers/block/drbd/drbd_int.h | 2 +- + drivers/block/drbd/drbd_main.c | 4 ++-- + drivers/block/drbd/drbd_nl.c | 20 ++++++++++---------- + 3 files changed, 13 insertions(+), 13 deletions(-) + +--- 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 usermode_helper[]; ++extern char 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 +@@ -108,9 +108,9 @@ int proc_details; /* Detail level + + /* Module parameter for setting the user mode helper program + * to run. Default is /sbin/drbdadm */ +-char usermode_helper[80] = "/sbin/drbdadm"; ++char drbd_usermode_helper[80] = "/sbin/drbdadm"; + +-module_param_string(usermode_helper, usermode_helper, sizeof(usermode_helper), 0644); ++module_param_string(usermode_helper, drbd_usermode_helper, sizeof(drbd_usermode_helper), 0644); + + /* 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[] = {usermode_helper, cmd, mb, NULL }; ++ char *argv[] = {drbd_usermode_helper, cmd, mb, NULL }; + struct drbd_connection *connection = first_peer_device(device)->connection; + struct sib_info sib; + int ret; +@@ -359,19 +359,19 @@ int drbd_khelper(struct drbd_device *dev + * write out any unsynced meta data changes now */ + drbd_md_sync(device); + +- drbd_info(device, "helper command: %s %s %s\n", usermode_helper, cmd, mb); ++ drbd_info(device, "helper command: %s %s %s\n", drbd_usermode_helper, cmd, mb); + sib.sib_reason = SIB_HELPER_PRE; + sib.helper_name = cmd; + drbd_bcast_event(device, &sib); + notify_helper(NOTIFY_CALL, device, connection, cmd, 0); +- ret = call_usermodehelper(usermode_helper, argv, envp, UMH_WAIT_PROC); ++ ret = call_usermodehelper(drbd_usermode_helper, argv, envp, UMH_WAIT_PROC); + if (ret) + drbd_warn(device, "helper command: %s %s %s exit code %u (0x%x)\n", +- usermode_helper, cmd, mb, ++ drbd_usermode_helper, cmd, mb, + (ret >> 8) & 0xff, ret); + else + drbd_info(device, "helper command: %s %s %s exit code %u (0x%x)\n", +- usermode_helper, cmd, mb, ++ drbd_usermode_helper, cmd, mb, + (ret >> 8) & 0xff, ret); + sib.sib_reason = SIB_HELPER_POST; + sib.helper_exit_code = ret; +@@ -396,24 +396,24 @@ enum drbd_peer_state conn_khelper(struct + (char[60]) { }, /* address */ + NULL }; + char *resource_name = connection->resource->name; +- char *argv[] = {usermode_helper, cmd, resource_name, NULL }; ++ char *argv[] = {drbd_usermode_helper, cmd, resource_name, NULL }; + int ret; + + setup_khelper_env(connection, envp); + conn_md_sync(connection); + +- drbd_info(connection, "helper command: %s %s %s\n", usermode_helper, cmd, resource_name); ++ drbd_info(connection, "helper command: %s %s %s\n", drbd_usermode_helper, cmd, resource_name); + /* TODO: conn_bcast_event() ?? */ + notify_helper(NOTIFY_CALL, NULL, connection, cmd, 0); + +- ret = call_usermodehelper(usermode_helper, argv, envp, UMH_WAIT_PROC); ++ ret = call_usermodehelper(drbd_usermode_helper, argv, envp, UMH_WAIT_PROC); + if (ret) + drbd_warn(connection, "helper command: %s %s %s exit code %u (0x%x)\n", +- usermode_helper, cmd, resource_name, ++ drbd_usermode_helper, cmd, resource_name, + (ret >> 8) & 0xff, ret); + else + drbd_info(connection, "helper command: %s %s %s exit code %u (0x%x)\n", +- usermode_helper, cmd, resource_name, ++ drbd_usermode_helper, cmd, resource_name, + (ret >> 8) & 0xff, ret); + /* TODO: conn_bcast_event() ?? */ + notify_helper(NOTIFY_RESPONSE, NULL, connection, cmd, ret); diff --git a/0003-Make-static-usermode-helper-binaries-constant.patch b/0003-Make-static-usermode-helper-binaries-constant.patch new file mode 100644 index 00000000000000..53ad93571e77e5 --- /dev/null +++ b/0003-Make-static-usermode-helper-binaries-constant.patch @@ -0,0 +1,181 @@ +From b8cc8ef7094cbaf916b87573efa3c31727bd6b2d Mon Sep 17 00:00:00 2001 +From: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Date: Sun, 11 Dec 2016 18:00:43 +0100 +Subject: [PATCH 3/4] Make static usermode helper binaries constant + +There are a number of usermode helper binaries that are "hard coded" in +the kernel today, so mark them as "const" to make it harder for someone +to change where the variables point to. + +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + drivers/macintosh/windfarm_core.c | 2 +- + drivers/net/hamradio/baycom_epp.c | 2 +- + drivers/pnp/pnpbios/core.c | 5 +++-- + drivers/staging/greybus/svc_watchdog.c | 4 ++-- + drivers/staging/rtl8192e/rtl8192e/rtl_dm.c | 6 +++--- + fs/nfsd/nfs4layouts.c | 6 ++++-- + security/keys/request_key.c | 7 ++++--- + 7 files changed, 18 insertions(+), 14 deletions(-) + +--- a/drivers/macintosh/windfarm_core.c ++++ b/drivers/macintosh/windfarm_core.c +@@ -74,7 +74,7 @@ static inline void wf_notify(int event, + + static int wf_critical_overtemp(void) + { +- static char * critical_overtemp_path = "/sbin/critical_overtemp"; ++ static const char * critical_overtemp_path = "/sbin/critical_overtemp"; + char *argv[] = { critical_overtemp_path, NULL }; + static char *envp[] = { "HOME=/", + "TERM=linux", +--- a/drivers/net/hamradio/baycom_epp.c ++++ b/drivers/net/hamradio/baycom_epp.c +@@ -299,7 +299,7 @@ static inline void baycom_int_freq(struc + * eppconfig_path should be setable via /proc/sys. + */ + +-static char eppconfig_path[256] = "/usr/sbin/eppfpga"; ++static const char eppconfig_path[256] = "/usr/sbin/eppfpga"; + + static char *envp[] = { "HOME=/", "TERM=linux", "PATH=/usr/bin:/bin", NULL }; + +--- a/drivers/pnp/pnpbios/core.c ++++ b/drivers/pnp/pnpbios/core.c +@@ -98,6 +98,7 @@ static struct completion unload_sem; + */ + static int pnp_dock_event(int dock, struct pnp_docking_station_info *info) + { ++ static const char *sbin_pnpbios = "/sbin/pnpbios"; + char *argv[3], **envp, *buf, *scratch; + int i = 0, value; + +@@ -112,7 +113,7 @@ static int pnp_dock_event(int dock, stru + * integrated into the driver core and use the usual infrastructure + * like sysfs and uevents + */ +- argv[0] = "/sbin/pnpbios"; ++ argv[0] = sbin_pnpbios; + argv[1] = "dock"; + argv[2] = NULL; + +@@ -139,7 +140,7 @@ static int pnp_dock_event(int dock, stru + info->location_id, info->serial, info->capabilities); + envp[i] = NULL; + +- value = call_usermodehelper(argv [0], argv, envp, UMH_WAIT_EXEC); ++ value = call_usermodehelper(sbin_pnpbios, argv, envp, UMH_WAIT_EXEC); + kfree(buf); + kfree(envp); + return 0; +--- a/drivers/staging/greybus/svc_watchdog.c ++++ b/drivers/staging/greybus/svc_watchdog.c +@@ -44,14 +44,14 @@ static int svc_watchdog_pm_notifier(stru + + static void greybus_reset(struct work_struct *work) + { +- static char start_path[256] = "/system/bin/start"; ++ static const char start_path[256] = "/system/bin/start"; + static char *envp[] = { + "HOME=/", + "PATH=/sbin:/vendor/bin:/system/sbin:/system/bin:/system/xbin", + NULL, + }; + static char *argv[] = { +- start_path, ++ (char *)start_path, + "unipro_reset", + NULL, + }; +--- a/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c ++++ b/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c +@@ -268,7 +268,7 @@ void rtl92e_dm_watchdog(struct net_devic + static void _rtl92e_dm_check_ac_dc_power(struct net_device *dev) + { + struct r8192_priv *priv = rtllib_priv(dev); +- static char *ac_dc_script = "/etc/acpi/wireless-rtl-ac-dc-power.sh"; ++ static const char *ac_dc_script = "/etc/acpi/wireless-rtl-ac-dc-power.sh"; + char *argv[] = {ac_dc_script, DRV_NAME, NULL}; + static char *envp[] = {"HOME=/", + "TERM=linux", +@@ -1823,7 +1823,7 @@ static void _rtl92e_dm_check_rf_ctrl_gpi + enum rt_rf_power_state eRfPowerStateToSet; + bool bActuallySet = false; + char *argv[3]; +- static char *RadioPowerPath = "/etc/acpi/events/RadioPower.sh"; ++ static const char *RadioPowerPath = "/etc/acpi/events/RadioPower.sh"; + static char *envp[] = {"HOME=/", "TERM=linux", "PATH=/usr/bin:/bin", + NULL}; + +@@ -1862,7 +1862,7 @@ static void _rtl92e_dm_check_rf_ctrl_gpi + else + argv[1] = "RFON"; + +- argv[0] = RadioPowerPath; ++ argv[0] = (char *)RadioPowerPath; + argv[2] = NULL; + call_usermodehelper(RadioPowerPath, argv, envp, UMH_WAIT_PROC); + } +--- a/fs/nfsd/nfs4layouts.c ++++ b/fs/nfsd/nfs4layouts.c +@@ -613,6 +613,7 @@ nfsd4_cb_layout_fail(struct nfs4_layout_ + { + struct nfs4_client *clp = ls->ls_stid.sc_client; + char addr_str[INET6_ADDRSTRLEN]; ++ static const char *nfsd_recall_failed = "/sbin/nfsd-recall-failed"; + static char *envp[] = { + "HOME=/", + "TERM=linux", +@@ -628,12 +629,13 @@ nfsd4_cb_layout_fail(struct nfs4_layout_ + "nfsd: client %s failed to respond to layout recall. " + " Fencing..\n", addr_str); + +- argv[0] = "/sbin/nfsd-recall-failed"; ++ argv[0] = (char *)nfsd_recall_failed; + argv[1] = addr_str; + argv[2] = ls->ls_file->f_path.mnt->mnt_sb->s_id; + argv[3] = NULL; + +- error = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC); ++ error = call_usermodehelper(nfsd_recall_failed, argv, envp, ++ UMH_WAIT_PROC); + if (error) { + printk(KERN_ERR "nfsd: fence failed for client %s: %d!\n", + addr_str, error); +--- a/security/keys/request_key.c ++++ b/security/keys/request_key.c +@@ -72,7 +72,7 @@ static void umh_keys_cleanup(struct subp + /* + * Call a usermode helper with a specific session keyring. + */ +-static int call_usermodehelper_keys(char *path, char **argv, char **envp, ++static int call_usermodehelper_keys(const char *path, char **argv, char **envp, + struct key *session_keyring, int wait) + { + struct subprocess_info *info; +@@ -95,6 +95,7 @@ static int call_sbin_request_key(struct + const char *op, + void *aux) + { ++ static const char *request_key = "/sbin/request-key"; + const struct cred *cred = current_cred(); + key_serial_t prkey, sskey; + struct key *key = cons->key, *authkey = cons->authkey, *keyring, +@@ -161,7 +162,7 @@ static int call_sbin_request_key(struct + + /* set up the argument list */ + i = 0; +- argv[i++] = "/sbin/request-key"; ++ argv[i++] = (char *)request_key; + argv[i++] = (char *) op; + argv[i++] = key_str; + argv[i++] = uid_str; +@@ -172,7 +173,7 @@ static int call_sbin_request_key(struct + argv[i] = NULL; + + /* do it */ +- ret = call_usermodehelper_keys(argv[0], argv, envp, keyring, ++ ret = call_usermodehelper_keys(request_key, argv, envp, keyring, + UMH_WAIT_PROC); + kdebug("usermode -> 0x%x", ret); + if (ret >= 0) { diff --git a/0004-Introduce-CONFIG_READONLY_USERMODEHELPER.patch b/0004-Introduce-CONFIG_READONLY_USERMODEHELPER.patch new file mode 100644 index 00000000000000..883487076ab0fd --- /dev/null +++ b/0004-Introduce-CONFIG_READONLY_USERMODEHELPER.patch @@ -0,0 +1,396 @@ +From 7c7aad8525b5ba93a45853992e199045392fa755 Mon Sep 17 00:00:00 2001 +From: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Date: Sun, 11 Dec 2016 18:06:14 +0100 +Subject: [PATCH 4/4] Introduce CONFIG_READONLY_USERMODEHELPER + +If you can write to kernel memory, an "easy" way to get the kernel to +run any application is to change the pointer of one of the usermode +helper program names. To try to mitigate this, create a new config +option, CONFIG_READONLY_USERMODEHELPER. + +This option only allows "predefined" binaries to be called. A number of +drivers and subsystems allow for the name of the binary to be changed, +and this config option disables that capability, so be aware of that. + +Note: Still a proof-of-concept at this point in time, doesn't cover all +of the call_usermodehelper() calls just yet, including the "fun" of +coredumps, it's still a work in progress. + +Not-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +--- + arch/x86/kernel/cpu/mcheck/mce.c | 12 +++++++--- + drivers/block/drbd/drbd_int.h | 6 ++++- + drivers/block/drbd/drbd_main.c | 5 ++++ + drivers/staging/lustre/include/linux/libcfs/libcfs.h | 2 + + drivers/staging/lustre/lnet/libcfs/linux/linux-debug.c | 11 ++++++++- + drivers/staging/lustre/lnet/libcfs/module.c | 2 + + drivers/video/fbdev/uvesafb.c | 19 ++++++++++++----- + fs/nfs/cache_lib.c | 12 ++++++++-- + include/linux/reboot.h | 2 + + kernel/ksysfs.c | 6 ++++- + kernel/reboot.c | 3 ++ + kernel/sysctl.c | 4 +++ + lib/kobject_uevent.c | 3 ++ + security/Kconfig | 17 +++++++++++++++ + 14 files changed, 89 insertions(+), 15 deletions(-) + +--- a/arch/x86/kernel/cpu/mcheck/mce.c ++++ b/arch/x86/kernel/cpu/mcheck/mce.c +@@ -2283,15 +2283,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; + +@@ -2304,6 +2305,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, +@@ -2361,7 +2366,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,11 @@ extern int fault_rate; + extern int fault_devs; + #endif + +-extern char drbd_usermode_helper[]; ++extern ++#ifdef CONFIG_READONLY_USERMODEHELPER ++ const ++#endif ++ char 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 +@@ -108,9 +108,14 @@ int proc_details; /* Detail level + + /* Module parameter for setting the user mode helper program + * to run. Default is /sbin/drbdadm */ ++#ifdef CONFIG_READONLY_USERMODEHELPER ++const ++#endif + char 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/staging/lustre/include/linux/libcfs/libcfs.h ++++ b/drivers/staging/lustre/include/linux/libcfs/libcfs.h +@@ -125,8 +125,10 @@ extern struct miscdevice libcfs_dev; + /** + * The path of debug log dump upcall script. + */ ++#ifndef CONFIG_READONLY_USERMODEHELPER + extern char lnet_upcall[1024]; + extern char lnet_debug_log_upcall[1024]; ++#endif + + extern struct cfs_wi_sched *cfs_sched_rehash; + +--- a/drivers/staging/lustre/lnet/libcfs/linux/linux-debug.c ++++ b/drivers/staging/lustre/lnet/libcfs/linux/linux-debug.c +@@ -57,7 +57,14 @@ + + #include <linux/kallsyms.h> + ++#ifdef CONFIG_READONLY_USERMODEHELPER ++static const + char lnet_upcall[1024] = "/usr/lib/lustre/lnet_upcall"; ++#endif ++ ++#ifdef CONFIG_READONLY_USERMODEHELPER ++static const ++#endif + char lnet_debug_log_upcall[1024] = "/usr/lib/lustre/lnet_debug_log_upcall"; + + /** +@@ -74,7 +81,7 @@ void libcfs_run_debug_log_upcall(char *f + "PATH=/sbin:/bin:/usr/sbin:/usr/bin", + NULL}; + +- argv[0] = lnet_debug_log_upcall; ++ argv[0] = (char *)lnet_debug_log_upcall; + + LASSERTF(file, "called on a null filename\n"); + argv[1] = file; /* only need to pass the path of the file */ +@@ -100,7 +107,7 @@ void libcfs_run_upcall(char **argv) + "PATH=/sbin:/bin:/usr/sbin:/usr/bin", + NULL}; + +- argv[0] = lnet_upcall; ++ argv[0] = (char *)lnet_upcall; + argc = 1; + while (argv[argc]) + argc++; +--- a/drivers/staging/lustre/lnet/libcfs/module.c ++++ b/drivers/staging/lustre/lnet/libcfs/module.c +@@ -366,6 +366,7 @@ static struct ctl_table lnet_table[] = { + .proc_handler = &proc_cpt_table, + }, + ++#ifndef CONFIG_READONLY_USERMODEHELPER + { + .procname = "upcall", + .data = lnet_upcall, +@@ -380,6 +381,7 @@ static struct ctl_table lnet_table[] = { + .mode = 0644, + .proc_handler = &proc_dostring, + }, ++#endif + { + .procname = "catastrophe", + .data = &libcfs_catastrophe, +--- a/drivers/video/fbdev/uvesafb.c ++++ b/drivers/video/fbdev/uvesafb.c +@@ -30,7 +30,11 @@ static struct cb_id uvesafb_cn_id = { + .idx = CN_IDX_V86D, + .val = CN_VAL_V86D_UVESAFB + }; ++#ifdef CONFIG_READONLY_USERMODEHELPER ++static const char v86d_path[PATH_MAX] = "/sbin/v86d"; ++#else + static char v86d_path[PATH_MAX] = "/sbin/v86d"; ++#endif + static char v86d_started; /* has v86d been started by uvesafb? */ + + static const struct fb_fix_screeninfo uvesafb_fix = { +@@ -114,7 +118,7 @@ static int uvesafb_helper_start(void) + }; + + char *argv[] = { +- v86d_path, ++ (char *)v86d_path, + NULL, + }; + +@@ -1883,19 +1887,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 +2024,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,20 @@ + #define NFS_CACHE_UPCALL_PATHLEN 256 + #define NFS_CACHE_UPCALL_TIMEOUT 15 + ++#ifdef CONFIG_READONLY_USERMODEHELPER ++static const char nfs_cache_getent_prog[NFS_CACHE_UPCALL_PATHLEN] = ++#else + static char nfs_cache_getent_prog[NFS_CACHE_UPCALL_PATHLEN] = ++#endif + "/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 +46,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,7 +55,8 @@ 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 +--- a/include/linux/reboot.h ++++ b/include/linux/reboot.h +@@ -68,7 +68,9 @@ extern int C_A_D; /* for sysctl */ + void ctrl_alt_del(void); + + #define POWEROFF_CMD_PATH_LEN 256 ++#ifndef CONFIG_READONLY_USERMODEHELPER + extern char poweroff_cmd[POWEROFF_CMD_PATH_LEN]; ++#endif + + 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,6 +386,9 @@ void ctrl_alt_del(void) + kill_cad_pid(SIGINT, 1); + } + ++#ifdef CONFIG_READONLY_USERMODEHELPER ++static const ++#endif + char poweroff_cmd[POWEROFF_CMD_PATH_LEN] = "/sbin/poweroff"; + static const char reboot_cmd[] = "/sbin/reboot"; + +--- a/kernel/sysctl.c ++++ b/kernel/sysctl.c +@@ -669,6 +669,7 @@ static struct ctl_table kern_table[] = { + }, + #endif + #ifdef CONFIG_UEVENT_HELPER ++#ifndef CONFIG_READONLY_USERMODEHELPER + { + .procname = "hotplug", + .data = &uevent_helper, +@@ -677,6 +678,7 @@ static struct ctl_table kern_table[] = { + .proc_handler = proc_dostring, + }, + #endif ++#endif + #ifdef CONFIG_CHR_DEV_SG + { + .procname = "sg-big-buff", +@@ -1093,6 +1095,7 @@ static struct ctl_table kern_table[] = { + .proc_handler = proc_dointvec, + }, + #endif ++#ifndef CONFIG_READONLY_USERMODEHELPER + { + .procname = "poweroff_cmd", + .data = &poweroff_cmd, +@@ -1100,6 +1103,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,6 +29,9 @@ + + u64 uevent_seqnum; + #ifdef CONFIG_UEVENT_HELPER ++#ifdef CONFIG_READONLY_USERMODEHELPER ++const ++#endif + char uevent_helper[UEVENT_HELPER_PATH_LEN] = CONFIG_UEVENT_HELPER_PATH; + #endif + #ifdef CONFIG_NET +--- a/security/Kconfig ++++ b/security/Kconfig +@@ -158,6 +158,23 @@ config HARDENED_USERCOPY_PAGESPAN + been removed. This config is intended to be used only while + trying to find such users. + ++config READONLY_USERMODEHELPER ++ bool "Make User Mode Helper program names read-only" ++ default N ++ help ++ Some user mode helper program names can be changed at runtime ++ by userspace programs. Prevent this from happening by "hard ++ coding" all user mode helper program names at kernel build ++ time, moving the names into read-only memory, making it harder ++ for any arbritrary program to be run as root if something were ++ to go wrong. ++ ++ Note, some subsystems and drivers allow their user mode helper ++ binary to be changed with a module parameter, sysctl, sysfs ++ file, or some combination of these. Enabling this option ++ prevents the binary name to be changed, which might not be ++ good for some systems. ++ + source security/selinux/Kconfig + source security/smack/Kconfig + source security/tomoyo/Kconfig diff --git a/c09.patch b/c09.patch index d6cca560e1da40..bf2461b55dd8f1 100644 --- a/c09.patch +++ b/c09.patch @@ -36,7 +36,7 @@ return -EINVAL; } -+static CLASS_ATTRIBUTE_WO(add); ++static CLASS_ATTR_WO(add); -static ssize_t class_pktcdvd_store_remove(struct class *c, - struct class_attribute *attr, @@ -51,7 +51,7 @@ } return -EINVAL; } -+static CLASS_ATTRIBUTE_WO(remove); ++static CLASS_ATTR_WO(remove); -static struct class_attribute class_pktcdvd_attrs[] = { - __ATTR(add, 0200, NULL, class_pktcdvd_store_add), @@ -1,3 +1,7 @@ +0001-kmod-make-usermodehelper-path-a-const-string.patch +0002-drbd-rename-usermode_helper-to-drbd_usermode_helper.patch +0003-Make-static-usermode-helper-binaries-constant.patch +0004-Introduce-CONFIG_READONLY_USERMODEHELPER.patch usb-core-add-missing-license-information.patch ## broken patch! |