Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0003 #include <linux/init.h>
0004 #include <linux/module.h>
0005 #include <linux/umh.h>
0006 #include <linux/bpfilter.h>
0007 #include <linux/sched.h>
0008 #include <linux/sched/signal.h>
0009 #include <linux/fs.h>
0010 #include <linux/file.h>
0011 #include "msgfmt.h"
0012 
0013 extern char bpfilter_umh_start;
0014 extern char bpfilter_umh_end;
0015 
0016 static void shutdown_umh(void)
0017 {
0018     struct umd_info *info = &bpfilter_ops.info;
0019     struct pid *tgid = info->tgid;
0020 
0021     if (tgid) {
0022         kill_pid(tgid, SIGKILL, 1);
0023         wait_event(tgid->wait_pidfd, thread_group_exited(tgid));
0024         bpfilter_umh_cleanup(info);
0025     }
0026 }
0027 
0028 static void __stop_umh(void)
0029 {
0030     if (IS_ENABLED(CONFIG_INET))
0031         shutdown_umh();
0032 }
0033 
0034 static int bpfilter_send_req(struct mbox_request *req)
0035 {
0036     struct mbox_reply reply;
0037     loff_t pos = 0;
0038     ssize_t n;
0039 
0040     if (!bpfilter_ops.info.tgid)
0041         return -EFAULT;
0042     pos = 0;
0043     n = kernel_write(bpfilter_ops.info.pipe_to_umh, req, sizeof(*req),
0044                &pos);
0045     if (n != sizeof(*req)) {
0046         pr_err("write fail %zd\n", n);
0047         goto stop;
0048     }
0049     pos = 0;
0050     n = kernel_read(bpfilter_ops.info.pipe_from_umh, &reply, sizeof(reply),
0051             &pos);
0052     if (n != sizeof(reply)) {
0053         pr_err("read fail %zd\n", n);
0054         goto stop;
0055     }
0056     return reply.status;
0057 stop:
0058     __stop_umh();
0059     return -EFAULT;
0060 }
0061 
0062 static int bpfilter_process_sockopt(struct sock *sk, int optname,
0063                     sockptr_t optval, unsigned int optlen,
0064                     bool is_set)
0065 {
0066     struct mbox_request req = {
0067         .is_set     = is_set,
0068         .pid        = current->pid,
0069         .cmd        = optname,
0070         .addr       = (uintptr_t)optval.user,
0071         .len        = optlen,
0072     };
0073     if (sockptr_is_kernel(optval)) {
0074         pr_err("kernel access not supported\n");
0075         return -EFAULT;
0076     }
0077     return bpfilter_send_req(&req);
0078 }
0079 
0080 static int start_umh(void)
0081 {
0082     struct mbox_request req = { .pid = current->pid };
0083     int err;
0084 
0085     /* fork usermode process */
0086     err = fork_usermode_driver(&bpfilter_ops.info);
0087     if (err)
0088         return err;
0089     pr_info("Loaded bpfilter_umh pid %d\n", pid_nr(bpfilter_ops.info.tgid));
0090 
0091     /* health check that usermode process started correctly */
0092     if (bpfilter_send_req(&req) != 0) {
0093         shutdown_umh();
0094         return -EFAULT;
0095     }
0096 
0097     return 0;
0098 }
0099 
0100 static int __init load_umh(void)
0101 {
0102     int err;
0103 
0104     err = umd_load_blob(&bpfilter_ops.info,
0105                 &bpfilter_umh_start,
0106                 &bpfilter_umh_end - &bpfilter_umh_start);
0107     if (err)
0108         return err;
0109 
0110     mutex_lock(&bpfilter_ops.lock);
0111     err = start_umh();
0112     if (!err && IS_ENABLED(CONFIG_INET)) {
0113         bpfilter_ops.sockopt = &bpfilter_process_sockopt;
0114         bpfilter_ops.start = &start_umh;
0115     }
0116     mutex_unlock(&bpfilter_ops.lock);
0117     if (err)
0118         umd_unload_blob(&bpfilter_ops.info);
0119     return err;
0120 }
0121 
0122 static void __exit fini_umh(void)
0123 {
0124     mutex_lock(&bpfilter_ops.lock);
0125     if (IS_ENABLED(CONFIG_INET)) {
0126         shutdown_umh();
0127         bpfilter_ops.start = NULL;
0128         bpfilter_ops.sockopt = NULL;
0129     }
0130     mutex_unlock(&bpfilter_ops.lock);
0131 
0132     umd_unload_blob(&bpfilter_ops.info);
0133 }
0134 module_init(load_umh);
0135 module_exit(fini_umh);
0136 MODULE_LICENSE("GPL");