Skip to content

Commit 884c5e6

Browse files
committed
umh: Separate the user mode driver and the user mode helper support
This makes it clear which code is part of the core user mode helper support and which code is needed to implement user mode drivers. This makes the kernel smaller for everyone who does not use a usermode driver. v1: https://lkml.kernel.org/r/[email protected] v2: https://lkml.kernel.org/r/[email protected] Link: https://lkml.kernel.org/r/[email protected] Reviewed-by: Greg Kroah-Hartman <[email protected]> Acked-by: Alexei Starovoitov <[email protected]> Tested-by: Alexei Starovoitov <[email protected]> Signed-off-by: "Eric W. Biederman" <[email protected]>
1 parent 21d5982 commit 884c5e6

File tree

8 files changed

+179
-158
lines changed

8 files changed

+179
-158
lines changed

include/linux/bpfilter.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#define _LINUX_BPFILTER_H
44

55
#include <uapi/linux/bpfilter.h>
6-
#include <linux/umh.h>
6+
#include <linux/usermode_driver.h>
77

88
struct sock;
99
int bpfilter_ip_set_sockopt(struct sock *sk, int optname, char __user *optval,

include/linux/sched.h

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2020,14 +2020,6 @@ static inline void rseq_execve(struct task_struct *t)
20202020

20212021
#endif
20222022

2023-
void __exit_umh(struct task_struct *tsk);
2024-
2025-
static inline void exit_umh(struct task_struct *tsk)
2026-
{
2027-
if (unlikely(tsk->flags & PF_UMH))
2028-
__exit_umh(tsk);
2029-
}
2030-
20312023
#ifdef CONFIG_DEBUG_RSEQ
20322024

20332025
void rseq_syscall(struct pt_regs *regs);

include/linux/umh.h

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -39,16 +39,6 @@ call_usermodehelper_setup(const char *path, char **argv, char **envp,
3939
int (*init)(struct subprocess_info *info, struct cred *new),
4040
void (*cleanup)(struct subprocess_info *), void *data);
4141

42-
struct umh_info {
43-
const char *cmdline;
44-
struct file *pipe_to_umh;
45-
struct file *pipe_from_umh;
46-
struct list_head list;
47-
void (*cleanup)(struct umh_info *info);
48-
pid_t pid;
49-
};
50-
int fork_usermode_blob(void *data, size_t len, struct umh_info *info);
51-
5242
extern int
5343
call_usermodehelper_exec(struct subprocess_info *info, int wait);
5444

include/linux/usermode_driver.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#ifndef __LINUX_USERMODE_DRIVER_H__
2+
#define __LINUX_USERMODE_DRIVER_H__
3+
4+
#include <linux/umh.h>
5+
6+
#ifdef CONFIG_BPFILTER
7+
void __exit_umh(struct task_struct *tsk);
8+
9+
static inline void exit_umh(struct task_struct *tsk)
10+
{
11+
if (unlikely(tsk->flags & PF_UMH))
12+
__exit_umh(tsk);
13+
}
14+
#else
15+
static inline void exit_umh(struct task_struct *tsk)
16+
{
17+
}
18+
#endif
19+
20+
struct umh_info {
21+
const char *cmdline;
22+
struct file *pipe_to_umh;
23+
struct file *pipe_from_umh;
24+
struct list_head list;
25+
void (*cleanup)(struct umh_info *info);
26+
pid_t pid;
27+
};
28+
int fork_usermode_blob(void *data, size_t len, struct umh_info *info);
29+
30+
#endif /* __LINUX_USERMODE_DRIVER_H__ */

kernel/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ obj-y = fork.o exec_domain.o panic.o \
1212
notifier.o ksysfs.o cred.o reboot.o \
1313
async.o range.o smpboot.o ucount.o
1414

15+
obj-$(CONFIG_BPFILTER) += usermode_driver.o
1516
obj-$(CONFIG_MODULES) += kmod.o
1617
obj-$(CONFIG_MULTIUSER) += groups.o
1718

kernel/exit.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
#include <linux/random.h>
6464
#include <linux/rcuwait.h>
6565
#include <linux/compat.h>
66+
#include <linux/usermode_driver.h>
6667

6768
#include <linux/uaccess.h>
6869
#include <asm/unistd.h>

kernel/umh.c

Lines changed: 0 additions & 139 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,6 @@
2626
#include <linux/ptrace.h>
2727
#include <linux/async.h>
2828
#include <linux/uaccess.h>
29-
#include <linux/shmem_fs.h>
30-
#include <linux/pipe_fs_i.h>
3129

3230
#include <trace/events/module.h>
3331

@@ -38,8 +36,6 @@ static kernel_cap_t usermodehelper_bset = CAP_FULL_SET;
3836
static kernel_cap_t usermodehelper_inheritable = CAP_FULL_SET;
3937
static DEFINE_SPINLOCK(umh_sysctl_lock);
4038
static DECLARE_RWSEM(umhelper_sem);
41-
static LIST_HEAD(umh_list);
42-
static DEFINE_MUTEX(umh_list_lock);
4339

4440
static void call_usermodehelper_freeinfo(struct subprocess_info *info)
4541
{
@@ -402,121 +398,6 @@ struct subprocess_info *call_usermodehelper_setup(const char *path, char **argv,
402398
}
403399
EXPORT_SYMBOL(call_usermodehelper_setup);
404400

405-
static int umd_setup(struct subprocess_info *info, struct cred *new)
406-
{
407-
struct umh_info *umh_info = info->data;
408-
struct file *from_umh[2];
409-
struct file *to_umh[2];
410-
int err;
411-
412-
/* create pipe to send data to umh */
413-
err = create_pipe_files(to_umh, 0);
414-
if (err)
415-
return err;
416-
err = replace_fd(0, to_umh[0], 0);
417-
fput(to_umh[0]);
418-
if (err < 0) {
419-
fput(to_umh[1]);
420-
return err;
421-
}
422-
423-
/* create pipe to receive data from umh */
424-
err = create_pipe_files(from_umh, 0);
425-
if (err) {
426-
fput(to_umh[1]);
427-
replace_fd(0, NULL, 0);
428-
return err;
429-
}
430-
err = replace_fd(1, from_umh[1], 0);
431-
fput(from_umh[1]);
432-
if (err < 0) {
433-
fput(to_umh[1]);
434-
replace_fd(0, NULL, 0);
435-
fput(from_umh[0]);
436-
return err;
437-
}
438-
439-
umh_info->pipe_to_umh = to_umh[1];
440-
umh_info->pipe_from_umh = from_umh[0];
441-
umh_info->pid = task_pid_nr(current);
442-
current->flags |= PF_UMH;
443-
return 0;
444-
}
445-
446-
static void umd_cleanup(struct subprocess_info *info)
447-
{
448-
struct umh_info *umh_info = info->data;
449-
450-
/* cleanup if umh_setup() was successful but exec failed */
451-
if (info->retval) {
452-
fput(umh_info->pipe_to_umh);
453-
fput(umh_info->pipe_from_umh);
454-
}
455-
}
456-
457-
/**
458-
* fork_usermode_blob - fork a blob of bytes as a usermode process
459-
* @data: a blob of bytes that can be do_execv-ed as a file
460-
* @len: length of the blob
461-
* @info: information about usermode process (shouldn't be NULL)
462-
*
463-
* If info->cmdline is set it will be used as command line for the
464-
* user process, else "usermodehelper" is used.
465-
*
466-
* Returns either negative error or zero which indicates success
467-
* in executing a blob of bytes as a usermode process. In such
468-
* case 'struct umh_info *info' is populated with two pipes
469-
* and a pid of the process. The caller is responsible for health
470-
* check of the user process, killing it via pid, and closing the
471-
* pipes when user process is no longer needed.
472-
*/
473-
int fork_usermode_blob(void *data, size_t len, struct umh_info *info)
474-
{
475-
const char *cmdline = (info->cmdline) ? info->cmdline : "usermodehelper";
476-
struct subprocess_info *sub_info;
477-
char **argv = NULL;
478-
struct file *file;
479-
ssize_t written;
480-
loff_t pos = 0;
481-
int err;
482-
483-
file = shmem_kernel_file_setup("", len, 0);
484-
if (IS_ERR(file))
485-
return PTR_ERR(file);
486-
487-
written = kernel_write(file, data, len, &pos);
488-
if (written != len) {
489-
err = written;
490-
if (err >= 0)
491-
err = -ENOMEM;
492-
goto out;
493-
}
494-
495-
err = -ENOMEM;
496-
argv = argv_split(GFP_KERNEL, cmdline, NULL);
497-
if (!argv)
498-
goto out;
499-
500-
sub_info = call_usermodehelper_setup("none", argv, NULL, GFP_KERNEL,
501-
umd_setup, umd_cleanup, info);
502-
if (!sub_info)
503-
goto out;
504-
505-
sub_info->file = file;
506-
err = call_usermodehelper_exec(sub_info, UMH_WAIT_EXEC);
507-
if (!err) {
508-
mutex_lock(&umh_list_lock);
509-
list_add(&info->list, &umh_list);
510-
mutex_unlock(&umh_list_lock);
511-
}
512-
out:
513-
if (argv)
514-
argv_free(argv);
515-
fput(file);
516-
return err;
517-
}
518-
EXPORT_SYMBOL_GPL(fork_usermode_blob);
519-
520401
/**
521402
* call_usermodehelper_exec - start a usermode application
522403
* @sub_info: information about the subprocessa
@@ -678,26 +559,6 @@ static int proc_cap_handler(struct ctl_table *table, int write,
678559
return 0;
679560
}
680561

681-
void __exit_umh(struct task_struct *tsk)
682-
{
683-
struct umh_info *info;
684-
pid_t pid = tsk->pid;
685-
686-
mutex_lock(&umh_list_lock);
687-
list_for_each_entry(info, &umh_list, list) {
688-
if (info->pid == pid) {
689-
list_del(&info->list);
690-
mutex_unlock(&umh_list_lock);
691-
goto out;
692-
}
693-
}
694-
mutex_unlock(&umh_list_lock);
695-
return;
696-
out:
697-
if (info->cleanup)
698-
info->cleanup(info);
699-
}
700-
701562
struct ctl_table usermodehelper_table[] = {
702563
{
703564
.procname = "bset",

0 commit comments

Comments
 (0)