1457c8996SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
223558693SLuis R. Rodriguez /*
323558693SLuis R. Rodriguez * umh - the kernel usermode helper
423558693SLuis R. Rodriguez */
523558693SLuis R. Rodriguez #include <linux/module.h>
623558693SLuis R. Rodriguez #include <linux/sched.h>
723558693SLuis R. Rodriguez #include <linux/sched/task.h>
823558693SLuis R. Rodriguez #include <linux/binfmts.h>
923558693SLuis R. Rodriguez #include <linux/syscalls.h>
1023558693SLuis R. Rodriguez #include <linux/unistd.h>
1123558693SLuis R. Rodriguez #include <linux/kmod.h>
1223558693SLuis R. Rodriguez #include <linux/slab.h>
1323558693SLuis R. Rodriguez #include <linux/completion.h>
1423558693SLuis R. Rodriguez #include <linux/cred.h>
1523558693SLuis R. Rodriguez #include <linux/file.h>
1623558693SLuis R. Rodriguez #include <linux/fdtable.h>
174013c149SLinus Torvalds #include <linux/fs_struct.h>
1823558693SLuis R. Rodriguez #include <linux/workqueue.h>
1923558693SLuis R. Rodriguez #include <linux/security.h>
2023558693SLuis R. Rodriguez #include <linux/mount.h>
2123558693SLuis R. Rodriguez #include <linux/kernel.h>
2223558693SLuis R. Rodriguez #include <linux/init.h>
2323558693SLuis R. Rodriguez #include <linux/resource.h>
2423558693SLuis R. Rodriguez #include <linux/notifier.h>
2523558693SLuis R. Rodriguez #include <linux/suspend.h>
2623558693SLuis R. Rodriguez #include <linux/rwsem.h>
2723558693SLuis R. Rodriguez #include <linux/ptrace.h>
2823558693SLuis R. Rodriguez #include <linux/async.h>
2923558693SLuis R. Rodriguez #include <linux/uaccess.h>
30e7cb072eSRasmus Villemoes #include <linux/initrd.h>
311fbcaa92SPeter Zijlstra #include <linux/freezer.h>
3223558693SLuis R. Rodriguez
3323558693SLuis R. Rodriguez #include <trace/events/module.h>
3423558693SLuis R. Rodriguez
3523558693SLuis R. Rodriguez static kernel_cap_t usermodehelper_bset = CAP_FULL_SET;
3623558693SLuis R. Rodriguez static kernel_cap_t usermodehelper_inheritable = CAP_FULL_SET;
3723558693SLuis R. Rodriguez static DEFINE_SPINLOCK(umh_sysctl_lock);
3823558693SLuis R. Rodriguez static DECLARE_RWSEM(umhelper_sem);
3923558693SLuis R. Rodriguez
call_usermodehelper_freeinfo(struct subprocess_info * info)4023558693SLuis R. Rodriguez static void call_usermodehelper_freeinfo(struct subprocess_info *info)
4123558693SLuis R. Rodriguez {
4223558693SLuis R. Rodriguez if (info->cleanup)
4323558693SLuis R. Rodriguez (*info->cleanup)(info);
4423558693SLuis R. Rodriguez kfree(info);
4523558693SLuis R. Rodriguez }
4623558693SLuis R. Rodriguez
umh_complete(struct subprocess_info * sub_info)4723558693SLuis R. Rodriguez static void umh_complete(struct subprocess_info *sub_info)
4823558693SLuis R. Rodriguez {
4923558693SLuis R. Rodriguez struct completion *comp = xchg(&sub_info->complete, NULL);
5023558693SLuis R. Rodriguez /*
5123558693SLuis R. Rodriguez * See call_usermodehelper_exec(). If xchg() returns NULL
5223558693SLuis R. Rodriguez * we own sub_info, the UMH_KILLABLE caller has gone away
5323558693SLuis R. Rodriguez * or the caller used UMH_NO_WAIT.
5423558693SLuis R. Rodriguez */
5523558693SLuis R. Rodriguez if (comp)
5623558693SLuis R. Rodriguez complete(comp);
5723558693SLuis R. Rodriguez else
5823558693SLuis R. Rodriguez call_usermodehelper_freeinfo(sub_info);
5923558693SLuis R. Rodriguez }
6023558693SLuis R. Rodriguez
6123558693SLuis R. Rodriguez /*
6223558693SLuis R. Rodriguez * This is the task which runs the usermode application
6323558693SLuis R. Rodriguez */
call_usermodehelper_exec_async(void * data)6423558693SLuis R. Rodriguez static int call_usermodehelper_exec_async(void *data)
6523558693SLuis R. Rodriguez {
6623558693SLuis R. Rodriguez struct subprocess_info *sub_info = data;
6723558693SLuis R. Rodriguez struct cred *new;
6823558693SLuis R. Rodriguez int retval;
6923558693SLuis R. Rodriguez
7023558693SLuis R. Rodriguez spin_lock_irq(¤t->sighand->siglock);
7123558693SLuis R. Rodriguez flush_signal_handlers(current, 1);
7223558693SLuis R. Rodriguez spin_unlock_irq(¤t->sighand->siglock);
7323558693SLuis R. Rodriguez
7423558693SLuis R. Rodriguez /*
754013c149SLinus Torvalds * Initial kernel threads share ther FS with init, in order to
764013c149SLinus Torvalds * get the init root directory. But we've now created a new
774013c149SLinus Torvalds * thread that is going to execve a user process and has its own
784013c149SLinus Torvalds * 'struct fs_struct'. Reset umask to the default.
794013c149SLinus Torvalds */
804013c149SLinus Torvalds current->fs->umask = 0022;
814013c149SLinus Torvalds
824013c149SLinus Torvalds /*
8323558693SLuis R. Rodriguez * Our parent (unbound workqueue) runs with elevated scheduling
8423558693SLuis R. Rodriguez * priority. Avoid propagating that into the userspace child.
8523558693SLuis R. Rodriguez */
8623558693SLuis R. Rodriguez set_user_nice(current, 0);
8723558693SLuis R. Rodriguez
8823558693SLuis R. Rodriguez retval = -ENOMEM;
8923558693SLuis R. Rodriguez new = prepare_kernel_cred(current);
9023558693SLuis R. Rodriguez if (!new)
9123558693SLuis R. Rodriguez goto out;
9223558693SLuis R. Rodriguez
9323558693SLuis R. Rodriguez spin_lock(&umh_sysctl_lock);
9423558693SLuis R. Rodriguez new->cap_bset = cap_intersect(usermodehelper_bset, new->cap_bset);
9523558693SLuis R. Rodriguez new->cap_inheritable = cap_intersect(usermodehelper_inheritable,
9623558693SLuis R. Rodriguez new->cap_inheritable);
9723558693SLuis R. Rodriguez spin_unlock(&umh_sysctl_lock);
9823558693SLuis R. Rodriguez
9923558693SLuis R. Rodriguez if (sub_info->init) {
10023558693SLuis R. Rodriguez retval = sub_info->init(sub_info, new);
10123558693SLuis R. Rodriguez if (retval) {
10223558693SLuis R. Rodriguez abort_creds(new);
10323558693SLuis R. Rodriguez goto out;
10423558693SLuis R. Rodriguez }
10523558693SLuis R. Rodriguez }
10623558693SLuis R. Rodriguez
10723558693SLuis R. Rodriguez commit_creds(new);
10823558693SLuis R. Rodriguez
109e7cb072eSRasmus Villemoes wait_for_initramfs();
110be619f7fSEric W. Biederman retval = kernel_execve(sub_info->path,
111be619f7fSEric W. Biederman (const char *const *)sub_info->argv,
112be619f7fSEric W. Biederman (const char *const *)sub_info->envp);
11323558693SLuis R. Rodriguez out:
11423558693SLuis R. Rodriguez sub_info->retval = retval;
11523558693SLuis R. Rodriguez /*
11623558693SLuis R. Rodriguez * call_usermodehelper_exec_sync() will call umh_complete
11723558693SLuis R. Rodriguez * if UHM_WAIT_PROC.
11823558693SLuis R. Rodriguez */
11923558693SLuis R. Rodriguez if (!(sub_info->wait & UMH_WAIT_PROC))
12023558693SLuis R. Rodriguez umh_complete(sub_info);
12123558693SLuis R. Rodriguez if (!retval)
12223558693SLuis R. Rodriguez return 0;
12323558693SLuis R. Rodriguez do_exit(0);
12423558693SLuis R. Rodriguez }
12523558693SLuis R. Rodriguez
12623558693SLuis R. Rodriguez /* Handles UMH_WAIT_PROC. */
call_usermodehelper_exec_sync(struct subprocess_info * sub_info)12723558693SLuis R. Rodriguez static void call_usermodehelper_exec_sync(struct subprocess_info *sub_info)
12823558693SLuis R. Rodriguez {
12923558693SLuis R. Rodriguez pid_t pid;
13023558693SLuis R. Rodriguez
1318043fc14SChristoph Hellwig /* If SIGCLD is ignored do_wait won't populate the status. */
13223558693SLuis R. Rodriguez kernel_sigaction(SIGCHLD, SIG_DFL);
133343f4c49SEric W. Biederman pid = user_mode_thread(call_usermodehelper_exec_async, sub_info, SIGCHLD);
1348043fc14SChristoph Hellwig if (pid < 0)
13523558693SLuis R. Rodriguez sub_info->retval = pid;
1368043fc14SChristoph Hellwig else
1378043fc14SChristoph Hellwig kernel_wait(pid, &sub_info->retval);
13823558693SLuis R. Rodriguez
13923558693SLuis R. Rodriguez /* Restore default kernel sig handler */
14023558693SLuis R. Rodriguez kernel_sigaction(SIGCHLD, SIG_IGN);
14123558693SLuis R. Rodriguez umh_complete(sub_info);
14223558693SLuis R. Rodriguez }
14323558693SLuis R. Rodriguez
14423558693SLuis R. Rodriguez /*
14523558693SLuis R. Rodriguez * We need to create the usermodehelper kernel thread from a task that is affine
14623558693SLuis R. Rodriguez * to an optimized set of CPUs (or nohz housekeeping ones) such that they
14723558693SLuis R. Rodriguez * inherit a widest affinity irrespective of call_usermodehelper() callers with
14823558693SLuis R. Rodriguez * possibly reduced affinity (eg: per-cpu workqueues). We don't want
14923558693SLuis R. Rodriguez * usermodehelper targets to contend a busy CPU.
15023558693SLuis R. Rodriguez *
15123558693SLuis R. Rodriguez * Unbound workqueues provide such wide affinity and allow to block on
15223558693SLuis R. Rodriguez * UMH_WAIT_PROC requests without blocking pending request (up to some limit).
15323558693SLuis R. Rodriguez *
15423558693SLuis R. Rodriguez * Besides, workqueues provide the privilege level that caller might not have
15523558693SLuis R. Rodriguez * to perform the usermodehelper request.
15623558693SLuis R. Rodriguez *
15723558693SLuis R. Rodriguez */
call_usermodehelper_exec_work(struct work_struct * work)15823558693SLuis R. Rodriguez static void call_usermodehelper_exec_work(struct work_struct *work)
15923558693SLuis R. Rodriguez {
16023558693SLuis R. Rodriguez struct subprocess_info *sub_info =
16123558693SLuis R. Rodriguez container_of(work, struct subprocess_info, work);
16223558693SLuis R. Rodriguez
16323558693SLuis R. Rodriguez if (sub_info->wait & UMH_WAIT_PROC) {
16423558693SLuis R. Rodriguez call_usermodehelper_exec_sync(sub_info);
16523558693SLuis R. Rodriguez } else {
16623558693SLuis R. Rodriguez pid_t pid;
16723558693SLuis R. Rodriguez /*
16823558693SLuis R. Rodriguez * Use CLONE_PARENT to reparent it to kthreadd; we do not
16923558693SLuis R. Rodriguez * want to pollute current->children, and we need a parent
17023558693SLuis R. Rodriguez * that always ignores SIGCHLD to ensure auto-reaping.
17123558693SLuis R. Rodriguez */
172343f4c49SEric W. Biederman pid = user_mode_thread(call_usermodehelper_exec_async, sub_info,
17323558693SLuis R. Rodriguez CLONE_PARENT | SIGCHLD);
17423558693SLuis R. Rodriguez if (pid < 0) {
17523558693SLuis R. Rodriguez sub_info->retval = pid;
17623558693SLuis R. Rodriguez umh_complete(sub_info);
17723558693SLuis R. Rodriguez }
17823558693SLuis R. Rodriguez }
17923558693SLuis R. Rodriguez }
18023558693SLuis R. Rodriguez
18123558693SLuis R. Rodriguez /*
18223558693SLuis R. Rodriguez * If set, call_usermodehelper_exec() will exit immediately returning -EBUSY
18323558693SLuis R. Rodriguez * (used for preventing user land processes from being created after the user
18423558693SLuis R. Rodriguez * land has been frozen during a system-wide hibernation or suspend operation).
18523558693SLuis R. Rodriguez * Should always be manipulated under umhelper_sem acquired for write.
18623558693SLuis R. Rodriguez */
18723558693SLuis R. Rodriguez static enum umh_disable_depth usermodehelper_disabled = UMH_DISABLED;
18823558693SLuis R. Rodriguez
18923558693SLuis R. Rodriguez /* Number of helpers running */
19023558693SLuis R. Rodriguez static atomic_t running_helpers = ATOMIC_INIT(0);
19123558693SLuis R. Rodriguez
19223558693SLuis R. Rodriguez /*
19323558693SLuis R. Rodriguez * Wait queue head used by usermodehelper_disable() to wait for all running
19423558693SLuis R. Rodriguez * helpers to finish.
19523558693SLuis R. Rodriguez */
19623558693SLuis R. Rodriguez static DECLARE_WAIT_QUEUE_HEAD(running_helpers_waitq);
19723558693SLuis R. Rodriguez
19823558693SLuis R. Rodriguez /*
19923558693SLuis R. Rodriguez * Used by usermodehelper_read_lock_wait() to wait for usermodehelper_disabled
20023558693SLuis R. Rodriguez * to become 'false'.
20123558693SLuis R. Rodriguez */
20223558693SLuis R. Rodriguez static DECLARE_WAIT_QUEUE_HEAD(usermodehelper_disabled_waitq);
20323558693SLuis R. Rodriguez
20423558693SLuis R. Rodriguez /*
20523558693SLuis R. Rodriguez * Time to wait for running_helpers to become zero before the setting of
20623558693SLuis R. Rodriguez * usermodehelper_disabled in usermodehelper_disable() fails
20723558693SLuis R. Rodriguez */
20823558693SLuis R. Rodriguez #define RUNNING_HELPERS_TIMEOUT (5 * HZ)
20923558693SLuis R. Rodriguez
usermodehelper_read_trylock(void)21023558693SLuis R. Rodriguez int usermodehelper_read_trylock(void)
21123558693SLuis R. Rodriguez {
21223558693SLuis R. Rodriguez DEFINE_WAIT(wait);
21323558693SLuis R. Rodriguez int ret = 0;
21423558693SLuis R. Rodriguez
21523558693SLuis R. Rodriguez down_read(&umhelper_sem);
21623558693SLuis R. Rodriguez for (;;) {
21723558693SLuis R. Rodriguez prepare_to_wait(&usermodehelper_disabled_waitq, &wait,
21823558693SLuis R. Rodriguez TASK_INTERRUPTIBLE);
21923558693SLuis R. Rodriguez if (!usermodehelper_disabled)
22023558693SLuis R. Rodriguez break;
22123558693SLuis R. Rodriguez
22223558693SLuis R. Rodriguez if (usermodehelper_disabled == UMH_DISABLED)
22323558693SLuis R. Rodriguez ret = -EAGAIN;
22423558693SLuis R. Rodriguez
22523558693SLuis R. Rodriguez up_read(&umhelper_sem);
22623558693SLuis R. Rodriguez
22723558693SLuis R. Rodriguez if (ret)
22823558693SLuis R. Rodriguez break;
22923558693SLuis R. Rodriguez
23023558693SLuis R. Rodriguez schedule();
23123558693SLuis R. Rodriguez try_to_freeze();
23223558693SLuis R. Rodriguez
23323558693SLuis R. Rodriguez down_read(&umhelper_sem);
23423558693SLuis R. Rodriguez }
23523558693SLuis R. Rodriguez finish_wait(&usermodehelper_disabled_waitq, &wait);
23623558693SLuis R. Rodriguez return ret;
23723558693SLuis R. Rodriguez }
23823558693SLuis R. Rodriguez EXPORT_SYMBOL_GPL(usermodehelper_read_trylock);
23923558693SLuis R. Rodriguez
usermodehelper_read_lock_wait(long timeout)24023558693SLuis R. Rodriguez long usermodehelper_read_lock_wait(long timeout)
24123558693SLuis R. Rodriguez {
24223558693SLuis R. Rodriguez DEFINE_WAIT(wait);
24323558693SLuis R. Rodriguez
24423558693SLuis R. Rodriguez if (timeout < 0)
24523558693SLuis R. Rodriguez return -EINVAL;
24623558693SLuis R. Rodriguez
24723558693SLuis R. Rodriguez down_read(&umhelper_sem);
24823558693SLuis R. Rodriguez for (;;) {
24923558693SLuis R. Rodriguez prepare_to_wait(&usermodehelper_disabled_waitq, &wait,
25023558693SLuis R. Rodriguez TASK_UNINTERRUPTIBLE);
25123558693SLuis R. Rodriguez if (!usermodehelper_disabled)
25223558693SLuis R. Rodriguez break;
25323558693SLuis R. Rodriguez
25423558693SLuis R. Rodriguez up_read(&umhelper_sem);
25523558693SLuis R. Rodriguez
25623558693SLuis R. Rodriguez timeout = schedule_timeout(timeout);
25723558693SLuis R. Rodriguez if (!timeout)
25823558693SLuis R. Rodriguez break;
25923558693SLuis R. Rodriguez
26023558693SLuis R. Rodriguez down_read(&umhelper_sem);
26123558693SLuis R. Rodriguez }
26223558693SLuis R. Rodriguez finish_wait(&usermodehelper_disabled_waitq, &wait);
26323558693SLuis R. Rodriguez return timeout;
26423558693SLuis R. Rodriguez }
26523558693SLuis R. Rodriguez EXPORT_SYMBOL_GPL(usermodehelper_read_lock_wait);
26623558693SLuis R. Rodriguez
usermodehelper_read_unlock(void)26723558693SLuis R. Rodriguez void usermodehelper_read_unlock(void)
26823558693SLuis R. Rodriguez {
26923558693SLuis R. Rodriguez up_read(&umhelper_sem);
27023558693SLuis R. Rodriguez }
27123558693SLuis R. Rodriguez EXPORT_SYMBOL_GPL(usermodehelper_read_unlock);
27223558693SLuis R. Rodriguez
27323558693SLuis R. Rodriguez /**
27423558693SLuis R. Rodriguez * __usermodehelper_set_disable_depth - Modify usermodehelper_disabled.
27523558693SLuis R. Rodriguez * @depth: New value to assign to usermodehelper_disabled.
27623558693SLuis R. Rodriguez *
27723558693SLuis R. Rodriguez * Change the value of usermodehelper_disabled (under umhelper_sem locked for
27823558693SLuis R. Rodriguez * writing) and wakeup tasks waiting for it to change.
27923558693SLuis R. Rodriguez */
__usermodehelper_set_disable_depth(enum umh_disable_depth depth)28023558693SLuis R. Rodriguez void __usermodehelper_set_disable_depth(enum umh_disable_depth depth)
28123558693SLuis R. Rodriguez {
28223558693SLuis R. Rodriguez down_write(&umhelper_sem);
28323558693SLuis R. Rodriguez usermodehelper_disabled = depth;
28423558693SLuis R. Rodriguez wake_up(&usermodehelper_disabled_waitq);
28523558693SLuis R. Rodriguez up_write(&umhelper_sem);
28623558693SLuis R. Rodriguez }
28723558693SLuis R. Rodriguez
28823558693SLuis R. Rodriguez /**
28923558693SLuis R. Rodriguez * __usermodehelper_disable - Prevent new helpers from being started.
29023558693SLuis R. Rodriguez * @depth: New value to assign to usermodehelper_disabled.
29123558693SLuis R. Rodriguez *
29223558693SLuis R. Rodriguez * Set usermodehelper_disabled to @depth and wait for running helpers to exit.
29323558693SLuis R. Rodriguez */
__usermodehelper_disable(enum umh_disable_depth depth)29423558693SLuis R. Rodriguez int __usermodehelper_disable(enum umh_disable_depth depth)
29523558693SLuis R. Rodriguez {
29623558693SLuis R. Rodriguez long retval;
29723558693SLuis R. Rodriguez
29823558693SLuis R. Rodriguez if (!depth)
29923558693SLuis R. Rodriguez return -EINVAL;
30023558693SLuis R. Rodriguez
30123558693SLuis R. Rodriguez down_write(&umhelper_sem);
30223558693SLuis R. Rodriguez usermodehelper_disabled = depth;
30323558693SLuis R. Rodriguez up_write(&umhelper_sem);
30423558693SLuis R. Rodriguez
30523558693SLuis R. Rodriguez /*
30623558693SLuis R. Rodriguez * From now on call_usermodehelper_exec() won't start any new
30723558693SLuis R. Rodriguez * helpers, so it is sufficient if running_helpers turns out to
30823558693SLuis R. Rodriguez * be zero at one point (it may be increased later, but that
30923558693SLuis R. Rodriguez * doesn't matter).
31023558693SLuis R. Rodriguez */
31123558693SLuis R. Rodriguez retval = wait_event_timeout(running_helpers_waitq,
31223558693SLuis R. Rodriguez atomic_read(&running_helpers) == 0,
31323558693SLuis R. Rodriguez RUNNING_HELPERS_TIMEOUT);
31423558693SLuis R. Rodriguez if (retval)
31523558693SLuis R. Rodriguez return 0;
31623558693SLuis R. Rodriguez
31723558693SLuis R. Rodriguez __usermodehelper_set_disable_depth(UMH_ENABLED);
31823558693SLuis R. Rodriguez return -EAGAIN;
31923558693SLuis R. Rodriguez }
32023558693SLuis R. Rodriguez
helper_lock(void)32123558693SLuis R. Rodriguez static void helper_lock(void)
32223558693SLuis R. Rodriguez {
32323558693SLuis R. Rodriguez atomic_inc(&running_helpers);
32423558693SLuis R. Rodriguez smp_mb__after_atomic();
32523558693SLuis R. Rodriguez }
32623558693SLuis R. Rodriguez
helper_unlock(void)32723558693SLuis R. Rodriguez static void helper_unlock(void)
32823558693SLuis R. Rodriguez {
32923558693SLuis R. Rodriguez if (atomic_dec_and_test(&running_helpers))
33023558693SLuis R. Rodriguez wake_up(&running_helpers_waitq);
33123558693SLuis R. Rodriguez }
33223558693SLuis R. Rodriguez
33323558693SLuis R. Rodriguez /**
33423558693SLuis R. Rodriguez * call_usermodehelper_setup - prepare to call a usermode helper
33523558693SLuis R. Rodriguez * @path: path to usermode executable
33623558693SLuis R. Rodriguez * @argv: arg vector for process
33723558693SLuis R. Rodriguez * @envp: environment for process
33823558693SLuis R. Rodriguez * @gfp_mask: gfp mask for memory allocation
33923558693SLuis R. Rodriguez * @init: an init function
34048207f7dSzhouchuangao * @cleanup: a cleanup function
34123558693SLuis R. Rodriguez * @data: arbitrary context sensitive data
34223558693SLuis R. Rodriguez *
34323558693SLuis R. Rodriguez * Returns either %NULL on allocation failure, or a subprocess_info
34423558693SLuis R. Rodriguez * structure. This should be passed to call_usermodehelper_exec to
34523558693SLuis R. Rodriguez * exec the process and free the structure.
34623558693SLuis R. Rodriguez *
34723558693SLuis R. Rodriguez * The init function is used to customize the helper process prior to
34823558693SLuis R. Rodriguez * exec. A non-zero return code causes the process to error out, exit,
34923558693SLuis R. Rodriguez * and return the failure to the calling process
35023558693SLuis R. Rodriguez *
35148207f7dSzhouchuangao * The cleanup function is just before the subprocess_info is about to
35223558693SLuis R. Rodriguez * be freed. This can be used for freeing the argv and envp. The
35323558693SLuis R. Rodriguez * Function must be runnable in either a process context or the
35423558693SLuis R. Rodriguez * context in which call_usermodehelper_exec is called.
35523558693SLuis R. Rodriguez */
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),void * data)35623558693SLuis R. Rodriguez struct subprocess_info *call_usermodehelper_setup(const char *path, char **argv,
35723558693SLuis R. Rodriguez char **envp, gfp_t gfp_mask,
35823558693SLuis R. Rodriguez int (*init)(struct subprocess_info *info, struct cred *new),
35923558693SLuis R. Rodriguez void (*cleanup)(struct subprocess_info *info),
36023558693SLuis R. Rodriguez void *data)
36123558693SLuis R. Rodriguez {
36223558693SLuis R. Rodriguez struct subprocess_info *sub_info;
36323558693SLuis R. Rodriguez sub_info = kzalloc(sizeof(struct subprocess_info), gfp_mask);
36423558693SLuis R. Rodriguez if (!sub_info)
36523558693SLuis R. Rodriguez goto out;
36623558693SLuis R. Rodriguez
36723558693SLuis R. Rodriguez INIT_WORK(&sub_info->work, call_usermodehelper_exec_work);
36823558693SLuis R. Rodriguez
36923558693SLuis R. Rodriguez #ifdef CONFIG_STATIC_USERMODEHELPER
37023558693SLuis R. Rodriguez sub_info->path = CONFIG_STATIC_USERMODEHELPER_PATH;
37123558693SLuis R. Rodriguez #else
37223558693SLuis R. Rodriguez sub_info->path = path;
37323558693SLuis R. Rodriguez #endif
37423558693SLuis R. Rodriguez sub_info->argv = argv;
37523558693SLuis R. Rodriguez sub_info->envp = envp;
37623558693SLuis R. Rodriguez
37723558693SLuis R. Rodriguez sub_info->cleanup = cleanup;
37823558693SLuis R. Rodriguez sub_info->init = init;
37923558693SLuis R. Rodriguez sub_info->data = data;
38023558693SLuis R. Rodriguez out:
38123558693SLuis R. Rodriguez return sub_info;
38223558693SLuis R. Rodriguez }
38323558693SLuis R. Rodriguez EXPORT_SYMBOL(call_usermodehelper_setup);
38423558693SLuis R. Rodriguez
38523558693SLuis R. Rodriguez /**
38623558693SLuis R. Rodriguez * call_usermodehelper_exec - start a usermode application
38748207f7dSzhouchuangao * @sub_info: information about the subprocess
38823558693SLuis R. Rodriguez * @wait: wait for the application to finish and return status.
38923558693SLuis R. Rodriguez * when UMH_NO_WAIT don't wait at all, but you get no useful error back
39023558693SLuis R. Rodriguez * when the program couldn't be exec'ed. This makes it safe to call
39123558693SLuis R. Rodriguez * from interrupt context.
39223558693SLuis R. Rodriguez *
39323558693SLuis R. Rodriguez * Runs a user-space application. The application is started
39423558693SLuis R. Rodriguez * asynchronously if wait is not set, and runs as a child of system workqueues.
39523558693SLuis R. Rodriguez * (ie. it runs with full root capabilities and optimized affinity).
3963740d93eSLuis Chamberlain *
3973740d93eSLuis Chamberlain * Note: successful return value does not guarantee the helper was called at
3983740d93eSLuis Chamberlain * all. You can't rely on sub_info->{init,cleanup} being called even for
3993740d93eSLuis Chamberlain * UMH_WAIT_* wait modes as STATIC_USERMODEHELPER_PATH="" turns all helpers
4003740d93eSLuis Chamberlain * into a successful no-op.
40123558693SLuis R. Rodriguez */
call_usermodehelper_exec(struct subprocess_info * sub_info,int wait)40223558693SLuis R. Rodriguez int call_usermodehelper_exec(struct subprocess_info *sub_info, int wait)
40323558693SLuis R. Rodriguez {
404f5d39b02SPeter Zijlstra unsigned int state = TASK_UNINTERRUPTIBLE;
40523558693SLuis R. Rodriguez DECLARE_COMPLETION_ONSTACK(done);
40623558693SLuis R. Rodriguez int retval = 0;
40723558693SLuis R. Rodriguez
40823558693SLuis R. Rodriguez if (!sub_info->path) {
40923558693SLuis R. Rodriguez call_usermodehelper_freeinfo(sub_info);
41023558693SLuis R. Rodriguez return -EINVAL;
41123558693SLuis R. Rodriguez }
41223558693SLuis R. Rodriguez helper_lock();
41323558693SLuis R. Rodriguez if (usermodehelper_disabled) {
41423558693SLuis R. Rodriguez retval = -EBUSY;
41523558693SLuis R. Rodriguez goto out;
41623558693SLuis R. Rodriguez }
41723558693SLuis R. Rodriguez
41823558693SLuis R. Rodriguez /*
41923558693SLuis R. Rodriguez * If there is no binary for us to call, then just return and get out of
42023558693SLuis R. Rodriguez * here. This allows us to set STATIC_USERMODEHELPER_PATH to "" and
42123558693SLuis R. Rodriguez * disable all call_usermodehelper() calls.
42223558693SLuis R. Rodriguez */
42323558693SLuis R. Rodriguez if (strlen(sub_info->path) == 0)
42423558693SLuis R. Rodriguez goto out;
42523558693SLuis R. Rodriguez
42623558693SLuis R. Rodriguez /*
42723558693SLuis R. Rodriguez * Set the completion pointer only if there is a waiter.
42823558693SLuis R. Rodriguez * This makes it possible to use umh_complete to free
42923558693SLuis R. Rodriguez * the data structure in case of UMH_NO_WAIT.
43023558693SLuis R. Rodriguez */
43123558693SLuis R. Rodriguez sub_info->complete = (wait == UMH_NO_WAIT) ? NULL : &done;
43223558693SLuis R. Rodriguez sub_info->wait = wait;
43323558693SLuis R. Rodriguez
43423558693SLuis R. Rodriguez queue_work(system_unbound_wq, &sub_info->work);
43523558693SLuis R. Rodriguez if (wait == UMH_NO_WAIT) /* task has freed sub_info */
43623558693SLuis R. Rodriguez goto unlock;
43723558693SLuis R. Rodriguez
438f5d39b02SPeter Zijlstra if (wait & UMH_FREEZABLE)
439f5d39b02SPeter Zijlstra state |= TASK_FREEZABLE;
440f5d39b02SPeter Zijlstra
441eedeb787SPeter Zijlstra if (wait & UMH_KILLABLE) {
442eedeb787SPeter Zijlstra retval = wait_for_completion_state(&done, state | TASK_KILLABLE);
44323558693SLuis R. Rodriguez if (!retval)
44423558693SLuis R. Rodriguez goto wait_done;
44523558693SLuis R. Rodriguez
44623558693SLuis R. Rodriguez /* umh_complete() will see NULL and free sub_info */
44723558693SLuis R. Rodriguez if (xchg(&sub_info->complete, NULL))
44823558693SLuis R. Rodriguez goto unlock;
449eedeb787SPeter Zijlstra
450eedeb787SPeter Zijlstra /*
451eedeb787SPeter Zijlstra * fallthrough; in case of -ERESTARTSYS now do uninterruptible
452eedeb787SPeter Zijlstra * wait_for_completion_state(). Since umh_complete() shall call
453eedeb787SPeter Zijlstra * complete() in a moment if xchg() above returned NULL, this
454eedeb787SPeter Zijlstra * uninterruptible wait_for_completion_state() will not block
455eedeb787SPeter Zijlstra * SIGKILL'ed processes for long.
456eedeb787SPeter Zijlstra */
45723558693SLuis R. Rodriguez }
458eedeb787SPeter Zijlstra wait_for_completion_state(&done, state);
45923558693SLuis R. Rodriguez
46023558693SLuis R. Rodriguez wait_done:
46123558693SLuis R. Rodriguez retval = sub_info->retval;
46223558693SLuis R. Rodriguez out:
46323558693SLuis R. Rodriguez call_usermodehelper_freeinfo(sub_info);
46423558693SLuis R. Rodriguez unlock:
46523558693SLuis R. Rodriguez helper_unlock();
46623558693SLuis R. Rodriguez return retval;
46723558693SLuis R. Rodriguez }
46823558693SLuis R. Rodriguez EXPORT_SYMBOL(call_usermodehelper_exec);
46923558693SLuis R. Rodriguez
47023558693SLuis R. Rodriguez /**
47123558693SLuis R. Rodriguez * call_usermodehelper() - prepare and start a usermode application
47223558693SLuis R. Rodriguez * @path: path to usermode executable
47323558693SLuis R. Rodriguez * @argv: arg vector for process
47423558693SLuis R. Rodriguez * @envp: environment for process
47523558693SLuis R. Rodriguez * @wait: wait for the application to finish and return status.
47623558693SLuis R. Rodriguez * when UMH_NO_WAIT don't wait at all, but you get no useful error back
47723558693SLuis R. Rodriguez * when the program couldn't be exec'ed. This makes it safe to call
47823558693SLuis R. Rodriguez * from interrupt context.
47923558693SLuis R. Rodriguez *
48023558693SLuis R. Rodriguez * This function is the equivalent to use call_usermodehelper_setup() and
48123558693SLuis R. Rodriguez * call_usermodehelper_exec().
48223558693SLuis R. Rodriguez */
call_usermodehelper(const char * path,char ** argv,char ** envp,int wait)48323558693SLuis R. Rodriguez int call_usermodehelper(const char *path, char **argv, char **envp, int wait)
48423558693SLuis R. Rodriguez {
48523558693SLuis R. Rodriguez struct subprocess_info *info;
48623558693SLuis R. Rodriguez gfp_t gfp_mask = (wait == UMH_NO_WAIT) ? GFP_ATOMIC : GFP_KERNEL;
48723558693SLuis R. Rodriguez
48823558693SLuis R. Rodriguez info = call_usermodehelper_setup(path, argv, envp, gfp_mask,
48923558693SLuis R. Rodriguez NULL, NULL, NULL);
49023558693SLuis R. Rodriguez if (info == NULL)
49123558693SLuis R. Rodriguez return -ENOMEM;
49223558693SLuis R. Rodriguez
49323558693SLuis R. Rodriguez return call_usermodehelper_exec(info, wait);
49423558693SLuis R. Rodriguez }
49523558693SLuis R. Rodriguez EXPORT_SYMBOL(call_usermodehelper);
49623558693SLuis R. Rodriguez
497*554588e8SArnd Bergmann #if defined(CONFIG_SYSCTL)
proc_cap_handler(struct ctl_table * table,int write,void * buffer,size_t * lenp,loff_t * ppos)49823558693SLuis R. Rodriguez static int proc_cap_handler(struct ctl_table *table, int write,
49932927393SChristoph Hellwig void *buffer, size_t *lenp, loff_t *ppos)
50023558693SLuis R. Rodriguez {
50123558693SLuis R. Rodriguez struct ctl_table t;
502f122a08bSLinus Torvalds unsigned long cap_array[2];
503f122a08bSLinus Torvalds kernel_cap_t new_cap, *cap;
504f122a08bSLinus Torvalds int err;
50523558693SLuis R. Rodriguez
50623558693SLuis R. Rodriguez if (write && (!capable(CAP_SETPCAP) ||
50723558693SLuis R. Rodriguez !capable(CAP_SYS_MODULE)))
50823558693SLuis R. Rodriguez return -EPERM;
50923558693SLuis R. Rodriguez
51023558693SLuis R. Rodriguez /*
51123558693SLuis R. Rodriguez * convert from the global kernel_cap_t to the ulong array to print to
51223558693SLuis R. Rodriguez * userspace if this is a read.
513e7783615SLinus Torvalds *
514e7783615SLinus Torvalds * Legacy format: capabilities are exposed as two 32-bit values
51523558693SLuis R. Rodriguez */
516e7783615SLinus Torvalds cap = table->data;
51723558693SLuis R. Rodriguez spin_lock(&umh_sysctl_lock);
518f122a08bSLinus Torvalds cap_array[0] = (u32) cap->val;
519f122a08bSLinus Torvalds cap_array[1] = cap->val >> 32;
52023558693SLuis R. Rodriguez spin_unlock(&umh_sysctl_lock);
52123558693SLuis R. Rodriguez
52223558693SLuis R. Rodriguez t = *table;
52323558693SLuis R. Rodriguez t.data = &cap_array;
52423558693SLuis R. Rodriguez
52523558693SLuis R. Rodriguez /*
52623558693SLuis R. Rodriguez * actually read or write and array of ulongs from userspace. Remember
52723558693SLuis R. Rodriguez * these are least significant 32 bits first
52823558693SLuis R. Rodriguez */
52923558693SLuis R. Rodriguez err = proc_doulongvec_minmax(&t, write, buffer, lenp, ppos);
53023558693SLuis R. Rodriguez if (err < 0)
53123558693SLuis R. Rodriguez return err;
53223558693SLuis R. Rodriguez
533f122a08bSLinus Torvalds new_cap.val = (u32)cap_array[0];
534f122a08bSLinus Torvalds new_cap.val += (u64)cap_array[1] << 32;
53523558693SLuis R. Rodriguez
53623558693SLuis R. Rodriguez /*
53723558693SLuis R. Rodriguez * Drop everything not in the new_cap (but don't add things)
53823558693SLuis R. Rodriguez */
53923558693SLuis R. Rodriguez if (write) {
5408c703d66SChristophe JAILLET spin_lock(&umh_sysctl_lock);
541f122a08bSLinus Torvalds *cap = cap_intersect(*cap, new_cap);
54223558693SLuis R. Rodriguez spin_unlock(&umh_sysctl_lock);
5438c703d66SChristophe JAILLET }
54423558693SLuis R. Rodriguez
54523558693SLuis R. Rodriguez return 0;
54623558693SLuis R. Rodriguez }
54723558693SLuis R. Rodriguez
548861dc0b4SLuis Chamberlain static struct ctl_table usermodehelper_table[] = {
54923558693SLuis R. Rodriguez {
55023558693SLuis R. Rodriguez .procname = "bset",
551e7783615SLinus Torvalds .data = &usermodehelper_bset,
552f122a08bSLinus Torvalds .maxlen = 2 * sizeof(unsigned long),
55323558693SLuis R. Rodriguez .mode = 0600,
55423558693SLuis R. Rodriguez .proc_handler = proc_cap_handler,
55523558693SLuis R. Rodriguez },
55623558693SLuis R. Rodriguez {
55723558693SLuis R. Rodriguez .procname = "inheritable",
558e7783615SLinus Torvalds .data = &usermodehelper_inheritable,
559f122a08bSLinus Torvalds .maxlen = 2 * sizeof(unsigned long),
56023558693SLuis R. Rodriguez .mode = 0600,
56123558693SLuis R. Rodriguez .proc_handler = proc_cap_handler,
56223558693SLuis R. Rodriguez },
56323558693SLuis R. Rodriguez { }
56423558693SLuis R. Rodriguez };
565861dc0b4SLuis Chamberlain
init_umh_sysctls(void)566861dc0b4SLuis Chamberlain static int __init init_umh_sysctls(void)
567861dc0b4SLuis Chamberlain {
568861dc0b4SLuis Chamberlain register_sysctl_init("kernel/usermodehelper", usermodehelper_table);
569861dc0b4SLuis Chamberlain return 0;
570861dc0b4SLuis Chamberlain }
571861dc0b4SLuis Chamberlain early_initcall(init_umh_sysctls);
572861dc0b4SLuis Chamberlain #endif /* CONFIG_SYSCTL */
573