Skip to content

Commit e0bb96d

Browse files
committed
netfilter: nft_socket: add support for cgroupsv2
Allow to match on the cgroupsv2 id from ancestor level. Signed-off-by: Pablo Neira Ayuso <[email protected]>
1 parent 885e8c6 commit e0bb96d

File tree

2 files changed

+51
-1
lines changed

2 files changed

+51
-1
lines changed

include/uapi/linux/netfilter/nf_tables.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1014,11 +1014,13 @@ enum nft_rt_attributes {
10141014
*
10151015
* @NFTA_SOCKET_KEY: socket key to match
10161016
* @NFTA_SOCKET_DREG: destination register
1017+
* @NFTA_SOCKET_LEVEL: cgroups2 ancestor level (only for cgroupsv2)
10171018
*/
10181019
enum nft_socket_attributes {
10191020
NFTA_SOCKET_UNSPEC,
10201021
NFTA_SOCKET_KEY,
10211022
NFTA_SOCKET_DREG,
1023+
NFTA_SOCKET_LEVEL,
10221024
__NFTA_SOCKET_MAX
10231025
};
10241026
#define NFTA_SOCKET_MAX (__NFTA_SOCKET_MAX - 1)
@@ -1029,11 +1031,13 @@ enum nft_socket_attributes {
10291031
* @NFT_SOCKET_TRANSPARENT: Value of the IP(V6)_TRANSPARENT socket option
10301032
* @NFT_SOCKET_MARK: Value of the socket mark
10311033
* @NFT_SOCKET_WILDCARD: Whether the socket is zero-bound (e.g. 0.0.0.0 or ::0)
1034+
* @NFT_SOCKET_CGROUPV2: Match on cgroups version 2
10321035
*/
10331036
enum nft_socket_keys {
10341037
NFT_SOCKET_TRANSPARENT,
10351038
NFT_SOCKET_MARK,
10361039
NFT_SOCKET_WILDCARD,
1040+
NFT_SOCKET_CGROUPV2,
10371041
__NFT_SOCKET_MAX
10381042
};
10391043
#define NFT_SOCKET_MAX (__NFT_SOCKET_MAX - 1)

net/netfilter/nft_socket.c

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
struct 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+
3657
static 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,
97126
static 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

102132
static 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

Comments
 (0)