Skip to content

Commit 9a1e5fc

Browse files
committed
netfilter: nf_tables: fully validate NFT_DATA_VALUE on store to data registers
jira LE-3201 cve CVE-2024-42070 Rebuild_History Non-Buildable kernel-rt-4.18.0-553.27.1.rt7.368.el8_10 commit-author Pablo Neira Ayuso <[email protected]> commit 7931d32 Empty-Commit: Cherry-Pick Conflicts during history rebuild. Will be included in final tarball splat. Ref for failed cherry-pick at: ciq/ciq_backports/kernel-rt-4.18.0-553.27.1.rt7.368.el8_10/7931d329.failed register store validation for NFT_DATA_VALUE is conditional, however, the datatype is always either NFT_DATA_VALUE or NFT_DATA_VERDICT. This only requires a new helper function to infer the register type from the set datatype so this conditional check can be removed. Otherwise, pointer to chain object can be leaked through the registers. Fixes: 9651851 ("netfilter: add nftables") Reported-by: Linus Torvalds <[email protected]> Signed-off-by: Pablo Neira Ayuso <[email protected]> (cherry picked from commit 7931d32) Signed-off-by: Jonathan Maple <[email protected]> # Conflicts: # net/netfilter/nf_tables_api.c # net/netfilter/nft_lookup.c
1 parent 60543ca commit 9a1e5fc

File tree

1 file changed

+137
-0
lines changed

1 file changed

+137
-0
lines changed
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
netfilter: nf_tables: fully validate NFT_DATA_VALUE on store to data registers
2+
3+
jira LE-3201
4+
cve CVE-2024-42070
5+
Rebuild_History Non-Buildable kernel-rt-4.18.0-553.27.1.rt7.368.el8_10
6+
commit-author Pablo Neira Ayuso <[email protected]>
7+
commit 7931d32955e09d0a11b1fe0b6aac1bfa061c005c
8+
Empty-Commit: Cherry-Pick Conflicts during history rebuild.
9+
Will be included in final tarball splat. Ref for failed cherry-pick at:
10+
ciq/ciq_backports/kernel-rt-4.18.0-553.27.1.rt7.368.el8_10/7931d329.failed
11+
12+
register store validation for NFT_DATA_VALUE is conditional, however,
13+
the datatype is always either NFT_DATA_VALUE or NFT_DATA_VERDICT. This
14+
only requires a new helper function to infer the register type from the
15+
set datatype so this conditional check can be removed. Otherwise,
16+
pointer to chain object can be leaked through the registers.
17+
18+
Fixes: 96518518cc41 ("netfilter: add nftables")
19+
Reported-by: Linus Torvalds <[email protected]>
20+
Signed-off-by: Pablo Neira Ayuso <[email protected]>
21+
(cherry picked from commit 7931d32955e09d0a11b1fe0b6aac1bfa061c005c)
22+
Signed-off-by: Jonathan Maple <[email protected]>
23+
24+
# Conflicts:
25+
# net/netfilter/nf_tables_api.c
26+
# net/netfilter/nft_lookup.c
27+
diff --cc net/netfilter/nf_tables_api.c
28+
index a8d03cec29c3,e8dcf41d360d..000000000000
29+
--- a/net/netfilter/nf_tables_api.c
30+
+++ b/net/netfilter/nf_tables_api.c
31+
@@@ -9015,23 -11071,42 +9014,28 @@@ int nft_validate_register_store(const s
32+
}
33+
34+
return 0;
35+
++<<<<<<< HEAD
36+
+ case NFT_REG_1...NFT_REG32_15:
37+
++=======
38+
+ default:
39+
+ if (type != NFT_DATA_VALUE)
40+
+ return -EINVAL;
41+
+
42+
++>>>>>>> 7931d32955e0 (netfilter: nf_tables: fully validate NFT_DATA_VALUE on store to data registers)
43+
if (reg < NFT_REG_1 * NFT_REG_SIZE / NFT_REG32_SIZE)
44+
return -EINVAL;
45+
if (len == 0)
46+
return -EINVAL;
47+
if (reg * NFT_REG32_SIZE + len >
48+
- sizeof_field(struct nft_regs, data))
49+
+ FIELD_SIZEOF(struct nft_regs, data))
50+
return -ERANGE;
51+
52+
- if (data != NULL && type != NFT_DATA_VALUE)
53+
- return -EINVAL;
54+
return 0;
55+
+ default:
56+
+ return -ERANGE;
57+
}
58+
}
59+
-
60+
-int nft_parse_register_store(const struct nft_ctx *ctx,
61+
- const struct nlattr *attr, u8 *dreg,
62+
- const struct nft_data *data,
63+
- enum nft_data_types type, unsigned int len)
64+
-{
65+
- int err;
66+
- u32 reg;
67+
-
68+
- err = nft_parse_register(attr, &reg);
69+
- if (err < 0)
70+
- return err;
71+
-
72+
- err = nft_validate_register_store(ctx, reg, data, type, len);
73+
- if (err < 0)
74+
- return err;
75+
-
76+
- *dreg = reg;
77+
- return 0;
78+
-}
79+
-EXPORT_SYMBOL_GPL(nft_parse_register_store);
80+
+EXPORT_SYMBOL_GPL(nft_validate_register_store);
81+
82+
static const struct nla_policy nft_verdict_policy[NFTA_VERDICT_MAX + 1] = {
83+
[NFTA_VERDICT_CODE] = { .type = NLA_U32 },
84+
diff --cc net/netfilter/nft_lookup.c
85+
index 828f87bb9145,f3080fa1b226..000000000000
86+
--- a/net/netfilter/nft_lookup.c
87+
+++ b/net/netfilter/nft_lookup.c
88+
@@@ -103,13 -131,23 +103,20 @@@ static int nft_lookup_init(const struc
89+
if (!(set->flags & NFT_SET_MAP))
90+
return -EINVAL;
91+
92+
++<<<<<<< HEAD
93+
+ priv->dreg = nft_parse_register(tb[NFTA_LOOKUP_DREG]);
94+
+ err = nft_validate_register_store(ctx, priv->dreg, NULL,
95+
+ set->dtype, set->dlen);
96+
++=======
97+
+ err = nft_parse_register_store(ctx, tb[NFTA_LOOKUP_DREG],
98+
+ &priv->dreg, NULL,
99+
+ nft_set_datatype(set),
100+
+ set->dlen);
101+
++>>>>>>> 7931d32955e0 (netfilter: nf_tables: fully validate NFT_DATA_VALUE on store to data registers)
102+
if (err < 0)
103+
return err;
104+
- priv->dreg_set = true;
105+
- } else if (set->flags & NFT_SET_MAP) {
106+
- /* Map given, but user asks for lookup only (i.e. to
107+
- * ignore value assoicated with key).
108+
- *
109+
- * This makes no sense for anonymous maps since they are
110+
- * scoped to the rule, but for named sets this can be useful.
111+
- */
112+
- if (set->flags & NFT_SET_ANONYMOUS)
113+
- return -EINVAL;
114+
- }
115+
+ } else if (set->flags & NFT_SET_MAP)
116+
+ return -EINVAL;
117+
118+
priv->binding.flags = set->flags & NFT_SET_MAP;
119+
120+
diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
121+
index dc1113771aec..e26d3b30a12d 100644
122+
--- a/include/net/netfilter/nf_tables.h
123+
+++ b/include/net/netfilter/nf_tables.h
124+
@@ -518,6 +518,11 @@ static inline void *nft_set_priv(const struct nft_set *set)
125+
return (void *)set->data;
126+
}
127+
128+
+static inline enum nft_data_types nft_set_datatype(const struct nft_set *set)
129+
+{
130+
+ return set->dtype == NFT_DATA_VERDICT ? NFT_DATA_VERDICT : NFT_DATA_VALUE;
131+
+}
132+
+
133+
static inline bool nft_set_gc_is_pending(const struct nft_set *s)
134+
{
135+
return refcount_read(&s->refs) != 1;
136+
* Unmerged path net/netfilter/nf_tables_api.c
137+
* Unmerged path net/netfilter/nft_lookup.c

0 commit comments

Comments
 (0)