Linux Audio

Check our new training course

Loading...
v5.4
  1// SPDX-License-Identifier: GPL-2.0
  2#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  3#include <linux/init.h>
  4#include <linux/module.h>
  5#include <linux/umh.h>
  6#include <linux/bpfilter.h>
  7#include <linux/sched.h>
  8#include <linux/sched/signal.h>
  9#include <linux/fs.h>
 10#include <linux/file.h>
 11#include "msgfmt.h"
 12
 13extern char bpfilter_umh_start;
 14extern char bpfilter_umh_end;
 15
 16static void shutdown_umh(void)
 17{
 18	struct task_struct *tsk;
 
 19
 20	if (bpfilter_ops.stop)
 21		return;
 22
 23	tsk = get_pid_task(find_vpid(bpfilter_ops.info.pid), PIDTYPE_PID);
 24	if (tsk) {
 25		send_sig(SIGKILL, tsk, 1);
 26		put_task_struct(tsk);
 27	}
 28}
 29
 30static void __stop_umh(void)
 31{
 32	if (IS_ENABLED(CONFIG_INET))
 33		shutdown_umh();
 34}
 35
 36static int __bpfilter_process_sockopt(struct sock *sk, int optname,
 37				      char __user *optval,
 38				      unsigned int optlen, bool is_set)
 39{
 40	struct mbox_request req;
 41	struct mbox_reply reply;
 42	loff_t pos;
 43	ssize_t n;
 44	int ret = -EFAULT;
 45
 46	req.is_set = is_set;
 47	req.pid = current->pid;
 48	req.cmd = optname;
 49	req.addr = (long __force __user)optval;
 50	req.len = optlen;
 51	if (!bpfilter_ops.info.pid)
 52		goto out;
 53	n = __kernel_write(bpfilter_ops.info.pipe_to_umh, &req, sizeof(req),
 54			   &pos);
 55	if (n != sizeof(req)) {
 56		pr_err("write fail %zd\n", n);
 57		__stop_umh();
 58		ret = -EFAULT;
 59		goto out;
 60	}
 61	pos = 0;
 62	n = kernel_read(bpfilter_ops.info.pipe_from_umh, &reply, sizeof(reply),
 63			&pos);
 64	if (n != sizeof(reply)) {
 65		pr_err("read fail %zd\n", n);
 66		__stop_umh();
 67		ret = -EFAULT;
 68		goto out;
 69	}
 70	ret = reply.status;
 71out:
 72	return ret;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 73}
 74
 75static int start_umh(void)
 76{
 
 77	int err;
 78
 79	/* fork usermode process */
 80	err = fork_usermode_blob(&bpfilter_umh_start,
 81				 &bpfilter_umh_end - &bpfilter_umh_start,
 82				 &bpfilter_ops.info);
 83	if (err)
 84		return err;
 85	bpfilter_ops.stop = false;
 86	pr_info("Loaded bpfilter_umh pid %d\n", bpfilter_ops.info.pid);
 87
 88	/* health check that usermode process started correctly */
 89	if (__bpfilter_process_sockopt(NULL, 0, NULL, 0, 0) != 0) {
 90		shutdown_umh();
 91		return -EFAULT;
 92	}
 93
 94	return 0;
 95}
 96
 97static int __init load_umh(void)
 98{
 99	int err;
100
 
 
 
 
 
 
101	mutex_lock(&bpfilter_ops.lock);
102	if (!bpfilter_ops.stop) {
103		err = -EFAULT;
104		goto out;
105	}
106	err = start_umh();
107	if (!err && IS_ENABLED(CONFIG_INET)) {
108		bpfilter_ops.sockopt = &__bpfilter_process_sockopt;
109		bpfilter_ops.start = &start_umh;
110	}
111out:
112	mutex_unlock(&bpfilter_ops.lock);
 
 
113	return err;
114}
115
116static void __exit fini_umh(void)
117{
118	mutex_lock(&bpfilter_ops.lock);
119	if (IS_ENABLED(CONFIG_INET)) {
120		shutdown_umh();
121		bpfilter_ops.start = NULL;
122		bpfilter_ops.sockopt = NULL;
123	}
124	mutex_unlock(&bpfilter_ops.lock);
 
 
125}
126module_init(load_umh);
127module_exit(fini_umh);
128MODULE_LICENSE("GPL");
v6.2
  1// SPDX-License-Identifier: GPL-2.0
  2#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  3#include <linux/init.h>
  4#include <linux/module.h>
  5#include <linux/umh.h>
  6#include <linux/bpfilter.h>
  7#include <linux/sched.h>
  8#include <linux/sched/signal.h>
  9#include <linux/fs.h>
 10#include <linux/file.h>
 11#include "msgfmt.h"
 12
 13extern char bpfilter_umh_start;
 14extern char bpfilter_umh_end;
 15
 16static void shutdown_umh(void)
 17{
 18	struct umd_info *info = &bpfilter_ops.info;
 19	struct pid *tgid = info->tgid;
 20
 21	if (tgid) {
 22		kill_pid(tgid, SIGKILL, 1);
 23		wait_event(tgid->wait_pidfd, thread_group_exited(tgid));
 24		bpfilter_umh_cleanup(info);
 
 
 
 25	}
 26}
 27
 28static void __stop_umh(void)
 29{
 30	if (IS_ENABLED(CONFIG_INET))
 31		shutdown_umh();
 32}
 33
 34static int bpfilter_send_req(struct mbox_request *req)
 
 
 35{
 
 36	struct mbox_reply reply;
 37	loff_t pos = 0;
 38	ssize_t n;
 
 39
 40	if (!bpfilter_ops.info.tgid)
 41		return -EFAULT;
 42	pos = 0;
 43	n = kernel_write(bpfilter_ops.info.pipe_to_umh, req, sizeof(*req),
 
 
 
 
 44			   &pos);
 45	if (n != sizeof(*req)) {
 46		pr_err("write fail %zd\n", n);
 47		goto stop;
 
 
 48	}
 49	pos = 0;
 50	n = kernel_read(bpfilter_ops.info.pipe_from_umh, &reply, sizeof(reply),
 51			&pos);
 52	if (n != sizeof(reply)) {
 53		pr_err("read fail %zd\n", n);
 54		goto stop;
 55	}
 56	return reply.status;
 57stop:
 58	__stop_umh();
 59	return -EFAULT;
 60}
 61
 62static int bpfilter_process_sockopt(struct sock *sk, int optname,
 63				    sockptr_t optval, unsigned int optlen,
 64				    bool is_set)
 65{
 66	struct mbox_request req = {
 67		.is_set		= is_set,
 68		.pid		= current->pid,
 69		.cmd		= optname,
 70		.addr		= (uintptr_t)optval.user,
 71		.len		= optlen,
 72	};
 73	if (sockptr_is_kernel(optval)) {
 74		pr_err("kernel access not supported\n");
 75		return -EFAULT;
 76	}
 77	return bpfilter_send_req(&req);
 78}
 79
 80static int start_umh(void)
 81{
 82	struct mbox_request req = { .pid = current->pid };
 83	int err;
 84
 85	/* fork usermode process */
 86	err = fork_usermode_driver(&bpfilter_ops.info);
 
 
 87	if (err)
 88		return err;
 89	pr_info("Loaded bpfilter_umh pid %d\n", pid_nr(bpfilter_ops.info.tgid));
 
 90
 91	/* health check that usermode process started correctly */
 92	if (bpfilter_send_req(&req) != 0) {
 93		shutdown_umh();
 94		return -EFAULT;
 95	}
 96
 97	return 0;
 98}
 99
100static int __init load_umh(void)
101{
102	int err;
103
104	err = umd_load_blob(&bpfilter_ops.info,
105			    &bpfilter_umh_start,
106			    &bpfilter_umh_end - &bpfilter_umh_start);
107	if (err)
108		return err;
109
110	mutex_lock(&bpfilter_ops.lock);
 
 
 
 
111	err = start_umh();
112	if (!err && IS_ENABLED(CONFIG_INET)) {
113		bpfilter_ops.sockopt = &bpfilter_process_sockopt;
114		bpfilter_ops.start = &start_umh;
115	}
 
116	mutex_unlock(&bpfilter_ops.lock);
117	if (err)
118		umd_unload_blob(&bpfilter_ops.info);
119	return err;
120}
121
122static void __exit fini_umh(void)
123{
124	mutex_lock(&bpfilter_ops.lock);
125	if (IS_ENABLED(CONFIG_INET)) {
126		shutdown_umh();
127		bpfilter_ops.start = NULL;
128		bpfilter_ops.sockopt = NULL;
129	}
130	mutex_unlock(&bpfilter_ops.lock);
131
132	umd_unload_blob(&bpfilter_ops.info);
133}
134module_init(load_umh);
135module_exit(fini_umh);
136MODULE_LICENSE("GPL");