99
1010struct nft_socket {
1111 enum nft_socket_keys key :8 ;
12+ u8 level ;
1213 union {
1314 u8 dreg ;
1415 };
@@ -33,6 +34,26 @@ static void nft_socket_wildcard(const struct nft_pktinfo *pkt,
3334 }
3435}
3536
37+ #ifdef CONFIG_CGROUPS
38+ static noinline bool
39+ nft_sock_get_eval_cgroupv2 (u32 * dest , const struct nft_pktinfo * pkt , u32 level )
40+ {
41+ struct sock * sk = skb_to_full_sk (pkt -> skb );
42+ struct cgroup * cgrp ;
43+
44+ if (!sk || !sk_fullsock (sk ) || !net_eq (nft_net (pkt ), sock_net (sk )))
45+ return false;
46+
47+ cgrp = sock_cgroup_ptr (& sk -> sk_cgrp_data );
48+ if (level > cgrp -> level )
49+ return false;
50+
51+ memcpy (dest , & cgrp -> ancestor_ids [level ], sizeof (u64 ));
52+
53+ return true;
54+ }
55+ #endif
56+
3657static void nft_socket_eval (const struct nft_expr * expr ,
3758 struct nft_regs * regs ,
3859 const struct nft_pktinfo * pkt )
@@ -85,6 +106,14 @@ static void nft_socket_eval(const struct nft_expr *expr,
85106 }
86107 nft_socket_wildcard (pkt , regs , sk , dest );
87108 break ;
109+ #ifdef CONFIG_CGROUPS
110+ case NFT_SOCKET_CGROUPV2 :
111+ if (!nft_sock_get_eval_cgroupv2 (dest , pkt , priv -> level )) {
112+ regs -> verdict .code = NFT_BREAK ;
113+ return ;
114+ }
115+ break ;
116+ #endif
88117 default :
89118 WARN_ON (1 );
90119 regs -> verdict .code = NFT_BREAK ;
@@ -97,14 +126,15 @@ static void nft_socket_eval(const struct nft_expr *expr,
97126static const struct nla_policy nft_socket_policy [NFTA_SOCKET_MAX + 1 ] = {
98127 [NFTA_SOCKET_KEY ] = { .type = NLA_U32 },
99128 [NFTA_SOCKET_DREG ] = { .type = NLA_U32 },
129+ [NFTA_SOCKET_LEVEL ] = { .type = NLA_U32 },
100130};
101131
102132static int nft_socket_init (const struct nft_ctx * ctx ,
103133 const struct nft_expr * expr ,
104134 const struct nlattr * const tb [])
105135{
106136 struct nft_socket * priv = nft_expr_priv (expr );
107- unsigned int len ;
137+ unsigned int len , level ;
108138
109139 if (!tb [NFTA_SOCKET_DREG ] || !tb [NFTA_SOCKET_KEY ])
110140 return - EINVAL ;
@@ -129,6 +159,19 @@ static int nft_socket_init(const struct nft_ctx *ctx,
129159 case NFT_SOCKET_MARK :
130160 len = sizeof (u32 );
131161 break ;
162+ #ifdef CONFIG_CGROUPS
163+ case NFT_SOCKET_CGROUPV2 :
164+ if (!tb [NFTA_SOCKET_LEVEL ])
165+ return - EINVAL ;
166+
167+ level = ntohl (nla_get_u32 (tb [NFTA_SOCKET_LEVEL ]));
168+ if (level > 255 )
169+ return - EOPNOTSUPP ;
170+
171+ priv -> level = level ;
172+ len = sizeof (u64 );
173+ break ;
174+ #endif
132175 default :
133176 return - EOPNOTSUPP ;
134177 }
@@ -146,6 +189,9 @@ static int nft_socket_dump(struct sk_buff *skb,
146189 return -1 ;
147190 if (nft_dump_register (skb , NFTA_SOCKET_DREG , priv -> dreg ))
148191 return -1 ;
192+ if (priv -> key == NFT_SOCKET_CGROUPV2 &&
193+ nla_put_u32 (skb , NFTA_SOCKET_LEVEL , htonl (priv -> level )))
194+ return -1 ;
149195 return 0 ;
150196}
151197
0 commit comments