Skip to content

Commit 8700970

Browse files
author
Paolo Abeni
committed
Merge tag 'nf-24-09-12' of git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf
Pablo Neira Ayuso says: ==================== Netfilter fixes for net The following batch contains two fixes from Florian Westphal: Patch #1 fixes a sk refcount leak in nft_socket on mismatch. Patch #2 fixes cgroupsv2 matching from containers due to incorrect level in subtree. netfilter pull request 24-09-12 * tag 'nf-24-09-12' of git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf: netfilter: nft_socket: make cgroupsv2 matching work with namespaces netfilter: nft_socket: fix sk refcount leaks ==================== Link: https://patch.msgid.link/[email protected] Signed-off-by: Paolo Abeni <[email protected]>
2 parents 6513eb3 + 7f3287d commit 8700970

File tree

1 file changed

+42
-6
lines changed

1 file changed

+42
-6
lines changed

net/netfilter/nft_socket.c

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99

1010
struct nft_socket {
1111
enum nft_socket_keys key:8;
12-
u8 level;
12+
u8 level; /* cgroupv2 level to extract */
13+
u8 level_user; /* cgroupv2 level provided by userspace */
1314
u8 len;
1415
union {
1516
u8 dreg;
@@ -53,6 +54,28 @@ nft_sock_get_eval_cgroupv2(u32 *dest, struct sock *sk, const struct nft_pktinfo
5354
memcpy(dest, &cgid, sizeof(u64));
5455
return true;
5556
}
57+
58+
/* process context only, uses current->nsproxy. */
59+
static noinline int nft_socket_cgroup_subtree_level(void)
60+
{
61+
struct cgroup *cgrp = cgroup_get_from_path("/");
62+
int level;
63+
64+
if (!cgrp)
65+
return -ENOENT;
66+
67+
level = cgrp->level;
68+
69+
cgroup_put(cgrp);
70+
71+
if (WARN_ON_ONCE(level > 255))
72+
return -ERANGE;
73+
74+
if (WARN_ON_ONCE(level < 0))
75+
return -EINVAL;
76+
77+
return level;
78+
}
5679
#endif
5780

5881
static struct sock *nft_socket_do_lookup(const struct nft_pktinfo *pkt)
@@ -110,21 +133,21 @@ static void nft_socket_eval(const struct nft_expr *expr,
110133
*dest = READ_ONCE(sk->sk_mark);
111134
} else {
112135
regs->verdict.code = NFT_BREAK;
113-
return;
136+
goto out_put_sk;
114137
}
115138
break;
116139
case NFT_SOCKET_WILDCARD:
117140
if (!sk_fullsock(sk)) {
118141
regs->verdict.code = NFT_BREAK;
119-
return;
142+
goto out_put_sk;
120143
}
121144
nft_socket_wildcard(pkt, regs, sk, dest);
122145
break;
123146
#ifdef CONFIG_SOCK_CGROUP_DATA
124147
case NFT_SOCKET_CGROUPV2:
125148
if (!nft_sock_get_eval_cgroupv2(dest, sk, pkt, priv->level)) {
126149
regs->verdict.code = NFT_BREAK;
127-
return;
150+
goto out_put_sk;
128151
}
129152
break;
130153
#endif
@@ -133,6 +156,7 @@ static void nft_socket_eval(const struct nft_expr *expr,
133156
regs->verdict.code = NFT_BREAK;
134157
}
135158

159+
out_put_sk:
136160
if (sk != skb->sk)
137161
sock_gen_put(sk);
138162
}
@@ -173,9 +197,10 @@ static int nft_socket_init(const struct nft_ctx *ctx,
173197
case NFT_SOCKET_MARK:
174198
len = sizeof(u32);
175199
break;
176-
#ifdef CONFIG_CGROUPS
200+
#ifdef CONFIG_SOCK_CGROUP_DATA
177201
case NFT_SOCKET_CGROUPV2: {
178202
unsigned int level;
203+
int err;
179204

180205
if (!tb[NFTA_SOCKET_LEVEL])
181206
return -EINVAL;
@@ -184,6 +209,17 @@ static int nft_socket_init(const struct nft_ctx *ctx,
184209
if (level > 255)
185210
return -EOPNOTSUPP;
186211

212+
err = nft_socket_cgroup_subtree_level();
213+
if (err < 0)
214+
return err;
215+
216+
priv->level_user = level;
217+
218+
level += err;
219+
/* Implies a giant cgroup tree */
220+
if (WARN_ON_ONCE(level > 255))
221+
return -EOPNOTSUPP;
222+
187223
priv->level = level;
188224
len = sizeof(u64);
189225
break;
@@ -208,7 +244,7 @@ static int nft_socket_dump(struct sk_buff *skb,
208244
if (nft_dump_register(skb, NFTA_SOCKET_DREG, priv->dreg))
209245
return -1;
210246
if (priv->key == NFT_SOCKET_CGROUPV2 &&
211-
nla_put_be32(skb, NFTA_SOCKET_LEVEL, htonl(priv->level)))
247+
nla_put_be32(skb, NFTA_SOCKET_LEVEL, htonl(priv->level_user)))
212248
return -1;
213249
return 0;
214250
}

0 commit comments

Comments
 (0)