The commit is pushed to "branch-rh8-4.18.0-240.1.1.vz8.5.x-ovz" and will appear 
at https://src.openvz.org/scm/ovz/vzkernel.git
after rh8-4.18.0-240.1.1.vz8.5.32
------>
commit f30df88ed6768c9b75417b58a0f8e16950baf28f
Author: Kirill Tkhai <[email protected]>
Date:   Mon May 24 16:20:33 2021 +0300

    ve/netfilter: Add autoloading of sockopt modules
    
    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 vz7 commit 70ae98e1c73b ("ve/netfilter: Add
    autoloading of sockopt modules"))
    
    CAP_VE_NET_ADMIN -> CAP_NET_ADMIN
    
    +++
    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 vz7 commit d14ac53542dc ("ve/netfilter/cred: add
    ve_capable to check capabilities relative to the current VE (v2)"))
    
    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);
 
_______________________________________________
Devel mailing list
[email protected]
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to