From: Kirill Tkhai <[email protected]> Patchset description:
Port autoloading of netfilter modules functuonality https://jira.sw.ru/browse/PSBM-28910 Signed-off-by: Kirill Tkhai <[email protected]> Kirill Tkhai (4): kmod: Move check of VE permitions from __call_usermodehelper_exec() to upper functions kmod: Port autoloading from CT netfilter: Add autoloading of sockopt modules netfilter: Check for permittions while looking for target and match (cherry picked from commit 70ae98e1c73b89e4be4248da2700092598da8c53) CAP_VE_NET_ADMIN -> CAP_NET_ADMIN --- combined with: ve/netfilter/cred: add ve_capable to check capabilities relative to the current VE (v2) We want to allow a few operations in VE. Currently we use nsown_capable, but it's wrong, because in this case we allow these operations in any user namespace. v2: take ve0->cred if the currect ve isn't running https://jira.sw.ru/browse/PSBM-39077 Signed-off-by: Andrew Vagin <[email protected]> Reviewed-by: Vladimir Davydov <[email protected]> (cherry picked from commit d14ac53542dcea9e8db67b3f989a57e42b0de093) VZ 8 rebase part https://jira.sw.ru/browse/PSBM-127783 Signed-off-by: Alexander Mikhalitsyn <[email protected]> --- net/netfilter/nf_sockopt.c | 76 +++++++++++++++++++++++++++++++++++++- 1 file changed, 74 insertions(+), 2 deletions(-) diff --git a/net/netfilter/nf_sockopt.c b/net/netfilter/nf_sockopt.c index 46cb3786e0ec..83358cfefdb7 100644 --- a/net/netfilter/nf_sockopt.c +++ b/net/netfilter/nf_sockopt.c @@ -7,6 +7,11 @@ #include <linux/mutex.h> #include <net/sock.h> +#ifdef CONFIG_VE_IPTABLES +#include <linux/netfilter_ipv4/ip_tables.h> +#include <linux/netfilter_ipv6/ip6_tables.h> +#endif /* CONFIG_VE_IPTABLES */ + #include "nf_internals.h" /* Sockopts only registered and called from user context, so @@ -88,6 +93,73 @@ static struct nf_sockopt_ops *nf_sockopt_find(struct sock *sk, u_int8_t pf, mutex_unlock(&nf_sockopt_mutex); return ops; } +#ifdef CONFIG_VE_IPTABLES +static int sockopt_module_fits(u_int8_t pf, int val, int get, + u_int8_t mod_pf, + int set_optmin, int set_optmax, + int get_optmin, int get_optmax) +{ + if (pf != mod_pf) + return 0; + if (get) + return val >= get_optmin && val < get_optmax; + else + return val >= set_optmin && val < set_optmax; +} + +static int ve0_load_sockopt_module(struct net *net, u8 pf, int val, int get) +{ + const char *name; + int ret = -EPERM; + + if (!ve_capable(CAP_NET_ADMIN)) + goto out; + + if (sockopt_module_fits(pf, val, get, PF_INET, + IPT_BASE_CTL, IPT_SO_SET_MAX + 1, + IPT_BASE_CTL, IPT_SO_GET_MAX + 1)) { + name = "ip_tables"; + } else if (sockopt_module_fits(pf, val, get, PF_INET6, + IP6T_BASE_CTL, IP6T_SO_SET_MAX + 1, + IP6T_BASE_CTL, IP6T_SO_GET_MAX + 1)) { + name = "ip6_tables"; + } else { + ret = -EINVAL; + goto out; + } + /* + * Currently loaded modules are free of locks used during + * their initialization. So, if you add one more module + * here research it before. Maybe you will have to use + * nowait module request in the function below. + */ + ret = request_module(name); +out: + return ret; +} + +static struct nf_sockopt_ops *nf_sockopt_find_ve(struct sock *sk, u_int8_t pf, + int val, int get) +{ + struct nf_sockopt_ops *ops = nf_sockopt_find(sk, pf, val, get); + + if (!IS_ERR(ops) || ve_is_super(get_exec_env())) + return ops; + + /* + * Containers are not able to load appropriate modules + * from userspace. We tricky help them here. For containers + * this looks like module is already loaded or driver + * is built in kernel. + */ + if (ve0_load_sockopt_module(sock_net(sk), pf, val, get) != 0) + return ops; + + return nf_sockopt_find(sk, pf, val, get); +} +#else /* !CONFIG_VE_IPTABLES */ +#define nf_sockopt_find_ve(sk, pf, val, get) nf_sockopt_find(sk, pf, val, get) +#endif /* !CONFIG_VE_IPTABLES */ /* Call get/setsockopt() */ static int nf_sockopt(struct sock *sk, u_int8_t pf, int val, @@ -96,7 +168,7 @@ static int nf_sockopt(struct sock *sk, u_int8_t pf, int val, struct nf_sockopt_ops *ops; int ret; - ops = nf_sockopt_find(sk, pf, val, get); + ops = nf_sockopt_find_ve(sk, pf, val, get); if (IS_ERR(ops)) return PTR_ERR(ops); @@ -130,7 +202,7 @@ static int compat_nf_sockopt(struct sock *sk, u_int8_t pf, int val, struct nf_sockopt_ops *ops; int ret; - ops = nf_sockopt_find(sk, pf, val, get); + ops = nf_sockopt_find_ve(sk, pf, val, get); if (IS_ERR(ops)) return PTR_ERR(ops); -- 2.28.0 _______________________________________________ Devel mailing list [email protected] https://lists.openvz.org/mailman/listinfo/devel
