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: 92ad6325cb
("netfilter: nf_tables: add hardware offload support")
Signed-off-by: wenxu <wenxu@ucloud.cn>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
parent
085461c897
commit
a69a85da45
|
@ -161,13 +161,21 @@ static int nft_payload_offload_ll(struct nft_offload_ctx *ctx,
|
||||||
|
|
||||||
switch (priv->offset) {
|
switch (priv->offset) {
|
||||||
case offsetof(struct ethhdr, h_source):
|
case offsetof(struct ethhdr, h_source):
|
||||||
|
if (priv->len != ETH_ALEN)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_ETH_ADDRS, eth_addrs,
|
NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_ETH_ADDRS, eth_addrs,
|
||||||
src, ETH_ALEN, reg);
|
src, ETH_ALEN, reg);
|
||||||
break;
|
break;
|
||||||
case offsetof(struct ethhdr, h_dest):
|
case offsetof(struct ethhdr, h_dest):
|
||||||
|
if (priv->len != ETH_ALEN)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_ETH_ADDRS, eth_addrs,
|
NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_ETH_ADDRS, eth_addrs,
|
||||||
dst, ETH_ALEN, reg);
|
dst, ETH_ALEN, reg);
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -181,14 +189,23 @@ static int nft_payload_offload_ip(struct nft_offload_ctx *ctx,
|
||||||
|
|
||||||
switch (priv->offset) {
|
switch (priv->offset) {
|
||||||
case offsetof(struct iphdr, saddr):
|
case offsetof(struct iphdr, saddr):
|
||||||
|
if (priv->len != sizeof(struct in_addr))
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV4_ADDRS, ipv4, src,
|
NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV4_ADDRS, ipv4, src,
|
||||||
sizeof(struct in_addr), reg);
|
sizeof(struct in_addr), reg);
|
||||||
break;
|
break;
|
||||||
case offsetof(struct iphdr, daddr):
|
case offsetof(struct iphdr, daddr):
|
||||||
|
if (priv->len != sizeof(struct in_addr))
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV4_ADDRS, ipv4, dst,
|
NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV4_ADDRS, ipv4, dst,
|
||||||
sizeof(struct in_addr), reg);
|
sizeof(struct in_addr), reg);
|
||||||
break;
|
break;
|
||||||
case offsetof(struct iphdr, protocol):
|
case offsetof(struct iphdr, protocol):
|
||||||
|
if (priv->len != sizeof(__u8))
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_BASIC, basic, ip_proto,
|
NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_BASIC, basic, ip_proto,
|
||||||
sizeof(__u8), reg);
|
sizeof(__u8), reg);
|
||||||
nft_offload_set_dependency(ctx, NFT_OFFLOAD_DEP_TRANSPORT);
|
nft_offload_set_dependency(ctx, NFT_OFFLOAD_DEP_TRANSPORT);
|
||||||
|
@ -208,14 +225,23 @@ static int nft_payload_offload_ip6(struct nft_offload_ctx *ctx,
|
||||||
|
|
||||||
switch (priv->offset) {
|
switch (priv->offset) {
|
||||||
case offsetof(struct ipv6hdr, saddr):
|
case offsetof(struct ipv6hdr, saddr):
|
||||||
|
if (priv->len != sizeof(struct in6_addr))
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV6_ADDRS, ipv6, src,
|
NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV6_ADDRS, ipv6, src,
|
||||||
sizeof(struct in6_addr), reg);
|
sizeof(struct in6_addr), reg);
|
||||||
break;
|
break;
|
||||||
case offsetof(struct ipv6hdr, daddr):
|
case offsetof(struct ipv6hdr, daddr):
|
||||||
|
if (priv->len != sizeof(struct in6_addr))
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV6_ADDRS, ipv6, dst,
|
NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV6_ADDRS, ipv6, dst,
|
||||||
sizeof(struct in6_addr), reg);
|
sizeof(struct in6_addr), reg);
|
||||||
break;
|
break;
|
||||||
case offsetof(struct ipv6hdr, nexthdr):
|
case offsetof(struct ipv6hdr, nexthdr):
|
||||||
|
if (priv->len != sizeof(__u8))
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_BASIC, basic, ip_proto,
|
NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_BASIC, basic, ip_proto,
|
||||||
sizeof(__u8), reg);
|
sizeof(__u8), reg);
|
||||||
nft_offload_set_dependency(ctx, NFT_OFFLOAD_DEP_TRANSPORT);
|
nft_offload_set_dependency(ctx, NFT_OFFLOAD_DEP_TRANSPORT);
|
||||||
|
@ -255,10 +281,16 @@ static int nft_payload_offload_tcp(struct nft_offload_ctx *ctx,
|
||||||
|
|
||||||
switch (priv->offset) {
|
switch (priv->offset) {
|
||||||
case offsetof(struct tcphdr, source):
|
case offsetof(struct tcphdr, source):
|
||||||
|
if (priv->len != sizeof(__be16))
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, src,
|
NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, src,
|
||||||
sizeof(__be16), reg);
|
sizeof(__be16), reg);
|
||||||
break;
|
break;
|
||||||
case offsetof(struct tcphdr, dest):
|
case offsetof(struct tcphdr, dest):
|
||||||
|
if (priv->len != sizeof(__be16))
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, dst,
|
NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, dst,
|
||||||
sizeof(__be16), reg);
|
sizeof(__be16), reg);
|
||||||
break;
|
break;
|
||||||
|
@ -277,10 +309,16 @@ static int nft_payload_offload_udp(struct nft_offload_ctx *ctx,
|
||||||
|
|
||||||
switch (priv->offset) {
|
switch (priv->offset) {
|
||||||
case offsetof(struct udphdr, source):
|
case offsetof(struct udphdr, source):
|
||||||
|
if (priv->len != sizeof(__be16))
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, src,
|
NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, src,
|
||||||
sizeof(__be16), reg);
|
sizeof(__be16), reg);
|
||||||
break;
|
break;
|
||||||
case offsetof(struct udphdr, dest):
|
case offsetof(struct udphdr, dest):
|
||||||
|
if (priv->len != sizeof(__be16))
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, dst,
|
NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, dst,
|
||||||
sizeof(__be16), reg);
|
sizeof(__be16), reg);
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in New Issue