9
9
10
10
struct nft_socket {
11
11
enum nft_socket_keys key :8 ;
12
+ u8 level ;
12
13
union {
13
14
u8 dreg ;
14
15
};
@@ -33,6 +34,26 @@ static void nft_socket_wildcard(const struct nft_pktinfo *pkt,
33
34
}
34
35
}
35
36
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
+
36
57
static void nft_socket_eval (const struct nft_expr * expr ,
37
58
struct nft_regs * regs ,
38
59
const struct nft_pktinfo * pkt )
@@ -85,6 +106,14 @@ static void nft_socket_eval(const struct nft_expr *expr,
85
106
}
86
107
nft_socket_wildcard (pkt , regs , sk , dest );
87
108
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
88
117
default :
89
118
WARN_ON (1 );
90
119
regs -> verdict .code = NFT_BREAK ;
@@ -97,14 +126,15 @@ static void nft_socket_eval(const struct nft_expr *expr,
97
126
static const struct nla_policy nft_socket_policy [NFTA_SOCKET_MAX + 1 ] = {
98
127
[NFTA_SOCKET_KEY ] = { .type = NLA_U32 },
99
128
[NFTA_SOCKET_DREG ] = { .type = NLA_U32 },
129
+ [NFTA_SOCKET_LEVEL ] = { .type = NLA_U32 },
100
130
};
101
131
102
132
static int nft_socket_init (const struct nft_ctx * ctx ,
103
133
const struct nft_expr * expr ,
104
134
const struct nlattr * const tb [])
105
135
{
106
136
struct nft_socket * priv = nft_expr_priv (expr );
107
- unsigned int len ;
137
+ unsigned int len , level ;
108
138
109
139
if (!tb [NFTA_SOCKET_DREG ] || !tb [NFTA_SOCKET_KEY ])
110
140
return - EINVAL ;
@@ -129,6 +159,19 @@ static int nft_socket_init(const struct nft_ctx *ctx,
129
159
case NFT_SOCKET_MARK :
130
160
len = sizeof (u32 );
131
161
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
132
175
default :
133
176
return - EOPNOTSUPP ;
134
177
}
@@ -146,6 +189,9 @@ static int nft_socket_dump(struct sk_buff *skb,
146
189
return -1 ;
147
190
if (nft_dump_register (skb , NFTA_SOCKET_DREG , priv -> dreg ))
148
191
return -1 ;
192
+ if (priv -> key == NFT_SOCKET_CGROUPV2 &&
193
+ nla_put_u32 (skb , NFTA_SOCKET_LEVEL , htonl (priv -> level )))
194
+ return -1 ;
149
195
return 0 ;
150
196
}
151
197
0 commit comments