ipvs: fix WARNING in ip_vs_app_net_cleanup()
[platform/kernel/linux-rpi.git] / net / netfilter / nft_socket.c
index d601974..9ad9cc0 100644 (file)
@@ -36,12 +36,11 @@ static void nft_socket_wildcard(const struct nft_pktinfo *pkt,
 
 #ifdef CONFIG_SOCK_CGROUP_DATA
 static noinline bool
-nft_sock_get_eval_cgroupv2(u32 *dest, const struct nft_pktinfo *pkt, u32 level)
+nft_sock_get_eval_cgroupv2(u32 *dest, struct sock *sk, const struct nft_pktinfo *pkt, u32 level)
 {
-       struct sock *sk = skb_to_full_sk(pkt->skb);
        struct cgroup *cgrp;
 
-       if (!sk || !sk_fullsock(sk) || !net_eq(nft_net(pkt), sock_net(sk)))
+       if (!sk_fullsock(sk))
                return false;
 
        cgrp = sock_cgroup_ptr(&sk->sk_cgrp_data);
@@ -54,6 +53,32 @@ nft_sock_get_eval_cgroupv2(u32 *dest, const struct nft_pktinfo *pkt, u32 level)
 }
 #endif
 
+static struct sock *nft_socket_do_lookup(const struct nft_pktinfo *pkt)
+{
+       const struct net_device *indev = nft_in(pkt);
+       const struct sk_buff *skb = pkt->skb;
+       struct sock *sk = NULL;
+
+       if (!indev)
+               return NULL;
+
+       switch (nft_pf(pkt)) {
+       case NFPROTO_IPV4:
+               sk = nf_sk_lookup_slow_v4(nft_net(pkt), skb, indev);
+               break;
+#if IS_ENABLED(CONFIG_NF_TABLES_IPV6)
+       case NFPROTO_IPV6:
+               sk = nf_sk_lookup_slow_v6(nft_net(pkt), skb, indev);
+               break;
+#endif
+       default:
+               WARN_ON_ONCE(1);
+               break;
+       }
+
+       return sk;
+}
+
 static void nft_socket_eval(const struct nft_expr *expr,
                            struct nft_regs *regs,
                            const struct nft_pktinfo *pkt)
@@ -67,20 +92,7 @@ static void nft_socket_eval(const struct nft_expr *expr,
                sk = NULL;
 
        if (!sk)
-               switch(nft_pf(pkt)) {
-               case NFPROTO_IPV4:
-                       sk = nf_sk_lookup_slow_v4(nft_net(pkt), skb, nft_in(pkt));
-                       break;
-#if IS_ENABLED(CONFIG_NF_TABLES_IPV6)
-               case NFPROTO_IPV6:
-                       sk = nf_sk_lookup_slow_v6(nft_net(pkt), skb, nft_in(pkt));
-                       break;
-#endif
-               default:
-                       WARN_ON_ONCE(1);
-                       regs->verdict.code = NFT_BREAK;
-                       return;
-               }
+               sk = nft_socket_do_lookup(pkt);
 
        if (!sk) {
                regs->verdict.code = NFT_BREAK;
@@ -108,7 +120,7 @@ static void nft_socket_eval(const struct nft_expr *expr,
                break;
 #ifdef CONFIG_SOCK_CGROUP_DATA
        case NFT_SOCKET_CGROUPV2:
-               if (!nft_sock_get_eval_cgroupv2(dest, pkt, priv->level)) {
+               if (!nft_sock_get_eval_cgroupv2(dest, sk, pkt, priv->level)) {
                        regs->verdict.code = NFT_BREAK;
                        return;
                }
@@ -198,6 +210,16 @@ static int nft_socket_dump(struct sk_buff *skb,
        return 0;
 }
 
+static int nft_socket_validate(const struct nft_ctx *ctx,
+                              const struct nft_expr *expr,
+                              const struct nft_data **data)
+{
+       return nft_chain_validate_hooks(ctx->chain,
+                                       (1 << NF_INET_PRE_ROUTING) |
+                                       (1 << NF_INET_LOCAL_IN) |
+                                       (1 << NF_INET_LOCAL_OUT));
+}
+
 static struct nft_expr_type nft_socket_type;
 static const struct nft_expr_ops nft_socket_ops = {
        .type           = &nft_socket_type,
@@ -205,6 +227,7 @@ static const struct nft_expr_ops nft_socket_ops = {
        .eval           = nft_socket_eval,
        .init           = nft_socket_init,
        .dump           = nft_socket_dump,
+       .validate       = nft_socket_validate,
 };
 
 static struct nft_expr_type nft_socket_type __read_mostly = {