xref: /openbmc/linux/net/ipv4/bpfilter/sockopt.c (revision 9b68f30b)
1d2ba09c1SAlexei Starovoitov // SPDX-License-Identifier: GPL-2.0
25b4cb650STaehee Yoo #include <linux/init.h>
35b4cb650STaehee Yoo #include <linux/module.h>
4d2ba09c1SAlexei Starovoitov #include <linux/uaccess.h>
5d2ba09c1SAlexei Starovoitov #include <linux/bpfilter.h>
6d2ba09c1SAlexei Starovoitov #include <uapi/linux/bpf.h>
7d2ba09c1SAlexei Starovoitov #include <linux/wait.h>
8d2ba09c1SAlexei Starovoitov #include <linux/kmod.h>
95b4cb650STaehee Yoo #include <linux/fs.h>
105b4cb650STaehee Yoo #include <linux/file.h>
11d2ba09c1SAlexei Starovoitov 
125b4cb650STaehee Yoo struct bpfilter_umh_ops bpfilter_ops;
135b4cb650STaehee Yoo EXPORT_SYMBOL_GPL(bpfilter_ops);
145b4cb650STaehee Yoo 
bpfilter_mbox_request(struct sock * sk,int optname,sockptr_t optval,unsigned int optlen,bool is_set)15b03afaa8SChristoph Hellwig static int bpfilter_mbox_request(struct sock *sk, int optname, sockptr_t optval,
16d2ba09c1SAlexei Starovoitov 				 unsigned int optlen, bool is_set)
17d2ba09c1SAlexei Starovoitov {
1861fbf593STaehee Yoo 	int err;
1971a85084STaehee Yoo 	mutex_lock(&bpfilter_ops.lock);
205b4cb650STaehee Yoo 	if (!bpfilter_ops.sockopt) {
2171a85084STaehee Yoo 		mutex_unlock(&bpfilter_ops.lock);
22752beb5eSKonstantin Khlebnikov 		request_module("bpfilter");
2371a85084STaehee Yoo 		mutex_lock(&bpfilter_ops.lock);
24d2ba09c1SAlexei Starovoitov 
2571a85084STaehee Yoo 		if (!bpfilter_ops.sockopt) {
26752beb5eSKonstantin Khlebnikov 			err = -ENOPROTOOPT;
2771a85084STaehee Yoo 			goto out;
2871a85084STaehee Yoo 		}
29d2ba09c1SAlexei Starovoitov 	}
30e80eb1dcSEric W. Biederman 	if (bpfilter_ops.info.tgid &&
31e80eb1dcSEric W. Biederman 	    thread_group_exited(bpfilter_ops.info.tgid))
32*9b68f30bSJarkko Sakkinen 		umd_cleanup_helper(&bpfilter_ops.info);
33e80eb1dcSEric W. Biederman 
34e80eb1dcSEric W. Biederman 	if (!bpfilter_ops.info.tgid) {
3561fbf593STaehee Yoo 		err = bpfilter_ops.start();
3661fbf593STaehee Yoo 		if (err)
3771a85084STaehee Yoo 			goto out;
3861fbf593STaehee Yoo 	}
3971a85084STaehee Yoo 	err = bpfilter_ops.sockopt(sk, optname, optval, optlen, is_set);
4071a85084STaehee Yoo out:
4171a85084STaehee Yoo 	mutex_unlock(&bpfilter_ops.lock);
4271a85084STaehee Yoo 	return err;
43d2ba09c1SAlexei Starovoitov }
44d2ba09c1SAlexei Starovoitov 
bpfilter_ip_set_sockopt(struct sock * sk,int optname,sockptr_t optval,unsigned int optlen)45b03afaa8SChristoph Hellwig int bpfilter_ip_set_sockopt(struct sock *sk, int optname, sockptr_t optval,
46d2ba09c1SAlexei Starovoitov 			    unsigned int optlen)
47d2ba09c1SAlexei Starovoitov {
48d2ba09c1SAlexei Starovoitov 	return bpfilter_mbox_request(sk, optname, optval, optlen, true);
49d2ba09c1SAlexei Starovoitov }
50d2ba09c1SAlexei Starovoitov 
bpfilter_ip_get_sockopt(struct sock * sk,int optname,char __user * optval,int __user * optlen)51519a8a6cSChristoph Hellwig int bpfilter_ip_get_sockopt(struct sock *sk, int optname, char __user *optval,
52519a8a6cSChristoph Hellwig 			    int __user *optlen)
53d2ba09c1SAlexei Starovoitov {
54519a8a6cSChristoph Hellwig 	int len;
55d2ba09c1SAlexei Starovoitov 
56d2ba09c1SAlexei Starovoitov 	if (get_user(len, optlen))
57d2ba09c1SAlexei Starovoitov 		return -EFAULT;
58519a8a6cSChristoph Hellwig 
59519a8a6cSChristoph Hellwig 	return bpfilter_mbox_request(sk, optname, USER_SOCKPTR(optval), len,
60519a8a6cSChristoph Hellwig 				     false);
61d2ba09c1SAlexei Starovoitov }
625b4cb650STaehee Yoo 
bpfilter_sockopt_init(void)635b4cb650STaehee Yoo static int __init bpfilter_sockopt_init(void)
645b4cb650STaehee Yoo {
6571a85084STaehee Yoo 	mutex_init(&bpfilter_ops.lock);
66e80eb1dcSEric W. Biederman 	bpfilter_ops.info.tgid = NULL;
671199c6c3SEric W. Biederman 	bpfilter_ops.info.driver_name = "bpfilter_umh";
685b4cb650STaehee Yoo 
695b4cb650STaehee Yoo 	return 0;
705b4cb650STaehee Yoo }
713557b3fdSPaul Gortmaker device_initcall(bpfilter_sockopt_init);
72