Skip to content

Commit a69a85d

Browse files
wenxuummakynes
authored andcommitted
netfilter: nft_payload: fix missing check for matching length in offloads
Payload offload rule should also check the length of the match. Moreover, check for unsupported link-layer fields: nft --debug=netlink add rule firewall zones vlan id 100 ... [ payload load 2b @ link header + 0 => reg 1 ] this loads 2byte base on ll header and offset 0. This also fixes unsupported raw payload match. Fixes: 92ad632 ("netfilter: nf_tables: add hardware offload support") Signed-off-by: wenxu <[email protected]> Signed-off-by: Pablo Neira Ayuso <[email protected]>
1 parent 085461c commit a69a85d

File tree

1 file changed

+38
-0
lines changed

1 file changed

+38
-0
lines changed

net/netfilter/nft_payload.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,13 +161,21 @@ static int nft_payload_offload_ll(struct nft_offload_ctx *ctx,
161161

162162
switch (priv->offset) {
163163
case offsetof(struct ethhdr, h_source):
164+
if (priv->len != ETH_ALEN)
165+
return -EOPNOTSUPP;
166+
164167
NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_ETH_ADDRS, eth_addrs,
165168
src, ETH_ALEN, reg);
166169
break;
167170
case offsetof(struct ethhdr, h_dest):
171+
if (priv->len != ETH_ALEN)
172+
return -EOPNOTSUPP;
173+
168174
NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_ETH_ADDRS, eth_addrs,
169175
dst, ETH_ALEN, reg);
170176
break;
177+
default:
178+
return -EOPNOTSUPP;
171179
}
172180

173181
return 0;
@@ -181,14 +189,23 @@ static int nft_payload_offload_ip(struct nft_offload_ctx *ctx,
181189

182190
switch (priv->offset) {
183191
case offsetof(struct iphdr, saddr):
192+
if (priv->len != sizeof(struct in_addr))
193+
return -EOPNOTSUPP;
194+
184195
NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV4_ADDRS, ipv4, src,
185196
sizeof(struct in_addr), reg);
186197
break;
187198
case offsetof(struct iphdr, daddr):
199+
if (priv->len != sizeof(struct in_addr))
200+
return -EOPNOTSUPP;
201+
188202
NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV4_ADDRS, ipv4, dst,
189203
sizeof(struct in_addr), reg);
190204
break;
191205
case offsetof(struct iphdr, protocol):
206+
if (priv->len != sizeof(__u8))
207+
return -EOPNOTSUPP;
208+
192209
NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_BASIC, basic, ip_proto,
193210
sizeof(__u8), reg);
194211
nft_offload_set_dependency(ctx, NFT_OFFLOAD_DEP_TRANSPORT);
@@ -208,14 +225,23 @@ static int nft_payload_offload_ip6(struct nft_offload_ctx *ctx,
208225

209226
switch (priv->offset) {
210227
case offsetof(struct ipv6hdr, saddr):
228+
if (priv->len != sizeof(struct in6_addr))
229+
return -EOPNOTSUPP;
230+
211231
NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV6_ADDRS, ipv6, src,
212232
sizeof(struct in6_addr), reg);
213233
break;
214234
case offsetof(struct ipv6hdr, daddr):
235+
if (priv->len != sizeof(struct in6_addr))
236+
return -EOPNOTSUPP;
237+
215238
NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV6_ADDRS, ipv6, dst,
216239
sizeof(struct in6_addr), reg);
217240
break;
218241
case offsetof(struct ipv6hdr, nexthdr):
242+
if (priv->len != sizeof(__u8))
243+
return -EOPNOTSUPP;
244+
219245
NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_BASIC, basic, ip_proto,
220246
sizeof(__u8), reg);
221247
nft_offload_set_dependency(ctx, NFT_OFFLOAD_DEP_TRANSPORT);
@@ -255,10 +281,16 @@ static int nft_payload_offload_tcp(struct nft_offload_ctx *ctx,
255281

256282
switch (priv->offset) {
257283
case offsetof(struct tcphdr, source):
284+
if (priv->len != sizeof(__be16))
285+
return -EOPNOTSUPP;
286+
258287
NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, src,
259288
sizeof(__be16), reg);
260289
break;
261290
case offsetof(struct tcphdr, dest):
291+
if (priv->len != sizeof(__be16))
292+
return -EOPNOTSUPP;
293+
262294
NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, dst,
263295
sizeof(__be16), reg);
264296
break;
@@ -277,10 +309,16 @@ static int nft_payload_offload_udp(struct nft_offload_ctx *ctx,
277309

278310
switch (priv->offset) {
279311
case offsetof(struct udphdr, source):
312+
if (priv->len != sizeof(__be16))
313+
return -EOPNOTSUPP;
314+
280315
NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, src,
281316
sizeof(__be16), reg);
282317
break;
283318
case offsetof(struct udphdr, dest):
319+
if (priv->len != sizeof(__be16))
320+
return -EOPNOTSUPP;
321+
284322
NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, dst,
285323
sizeof(__be16), reg);
286324
break;

0 commit comments

Comments
 (0)