aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwenxu <wenxu@ucloud.cn>2019-10-24 03:52:45 -0400
committerPablo Neira Ayuso <pablo@netfilter.org>2019-10-24 06:27:29 -0400
commita69a85da458f79088c38a38db034a4d64d9c32c3 (patch)
tree0ce824f5991bbcb5d74c5a8e220395c457f3318c
parent085461c8976e6cb4d5b608a7b7062f394c51a253 (diff)
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: 92ad6325cb89 ("netfilter: nf_tables: add hardware offload support") Signed-off-by: wenxu <wenxu@ucloud.cn> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r--net/netfilter/nft_payload.c38
1 files changed, 38 insertions, 0 deletions
diff --git a/net/netfilter/nft_payload.c b/net/netfilter/nft_payload.c
index 22a80eb60222..5cb2d8908d2a 100644
--- a/net/netfilter/nft_payload.c
+++ b/net/netfilter/nft_payload.c
@@ -161,13 +161,21 @@ static int nft_payload_offload_ll(struct nft_offload_ctx *ctx,
161 161
162 switch (priv->offset) { 162 switch (priv->offset) {
163 case offsetof(struct ethhdr, h_source): 163 case offsetof(struct ethhdr, h_source):
164 if (priv->len != ETH_ALEN)
165 return -EOPNOTSUPP;
166
164 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_ETH_ADDRS, eth_addrs, 167 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_ETH_ADDRS, eth_addrs,
165 src, ETH_ALEN, reg); 168 src, ETH_ALEN, reg);
166 break; 169 break;
167 case offsetof(struct ethhdr, h_dest): 170 case offsetof(struct ethhdr, h_dest):
171 if (priv->len != ETH_ALEN)
172 return -EOPNOTSUPP;
173
168 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_ETH_ADDRS, eth_addrs, 174 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_ETH_ADDRS, eth_addrs,
169 dst, ETH_ALEN, reg); 175 dst, ETH_ALEN, reg);
170 break; 176 break;
177 default:
178 return -EOPNOTSUPP;
171 } 179 }
172 180
173 return 0; 181 return 0;
@@ -181,14 +189,23 @@ static int nft_payload_offload_ip(struct nft_offload_ctx *ctx,
181 189
182 switch (priv->offset) { 190 switch (priv->offset) {
183 case offsetof(struct iphdr, saddr): 191 case offsetof(struct iphdr, saddr):
192 if (priv->len != sizeof(struct in_addr))
193 return -EOPNOTSUPP;
194
184 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV4_ADDRS, ipv4, src, 195 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV4_ADDRS, ipv4, src,
185 sizeof(struct in_addr), reg); 196 sizeof(struct in_addr), reg);
186 break; 197 break;
187 case offsetof(struct iphdr, daddr): 198 case offsetof(struct iphdr, daddr):
199 if (priv->len != sizeof(struct in_addr))
200 return -EOPNOTSUPP;
201
188 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV4_ADDRS, ipv4, dst, 202 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV4_ADDRS, ipv4, dst,
189 sizeof(struct in_addr), reg); 203 sizeof(struct in_addr), reg);
190 break; 204 break;
191 case offsetof(struct iphdr, protocol): 205 case offsetof(struct iphdr, protocol):
206 if (priv->len != sizeof(__u8))
207 return -EOPNOTSUPP;
208
192 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_BASIC, basic, ip_proto, 209 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_BASIC, basic, ip_proto,
193 sizeof(__u8), reg); 210 sizeof(__u8), reg);
194 nft_offload_set_dependency(ctx, NFT_OFFLOAD_DEP_TRANSPORT); 211 nft_offload_set_dependency(ctx, NFT_OFFLOAD_DEP_TRANSPORT);
@@ -208,14 +225,23 @@ static int nft_payload_offload_ip6(struct nft_offload_ctx *ctx,
208 225
209 switch (priv->offset) { 226 switch (priv->offset) {
210 case offsetof(struct ipv6hdr, saddr): 227 case offsetof(struct ipv6hdr, saddr):
228 if (priv->len != sizeof(struct in6_addr))
229 return -EOPNOTSUPP;
230
211 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV6_ADDRS, ipv6, src, 231 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV6_ADDRS, ipv6, src,
212 sizeof(struct in6_addr), reg); 232 sizeof(struct in6_addr), reg);
213 break; 233 break;
214 case offsetof(struct ipv6hdr, daddr): 234 case offsetof(struct ipv6hdr, daddr):
235 if (priv->len != sizeof(struct in6_addr))
236 return -EOPNOTSUPP;
237
215 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV6_ADDRS, ipv6, dst, 238 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV6_ADDRS, ipv6, dst,
216 sizeof(struct in6_addr), reg); 239 sizeof(struct in6_addr), reg);
217 break; 240 break;
218 case offsetof(struct ipv6hdr, nexthdr): 241 case offsetof(struct ipv6hdr, nexthdr):
242 if (priv->len != sizeof(__u8))
243 return -EOPNOTSUPP;
244
219 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_BASIC, basic, ip_proto, 245 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_BASIC, basic, ip_proto,
220 sizeof(__u8), reg); 246 sizeof(__u8), reg);
221 nft_offload_set_dependency(ctx, NFT_OFFLOAD_DEP_TRANSPORT); 247 nft_offload_set_dependency(ctx, NFT_OFFLOAD_DEP_TRANSPORT);
@@ -255,10 +281,16 @@ static int nft_payload_offload_tcp(struct nft_offload_ctx *ctx,
255 281
256 switch (priv->offset) { 282 switch (priv->offset) {
257 case offsetof(struct tcphdr, source): 283 case offsetof(struct tcphdr, source):
284 if (priv->len != sizeof(__be16))
285 return -EOPNOTSUPP;
286
258 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, src, 287 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, src,
259 sizeof(__be16), reg); 288 sizeof(__be16), reg);
260 break; 289 break;
261 case offsetof(struct tcphdr, dest): 290 case offsetof(struct tcphdr, dest):
291 if (priv->len != sizeof(__be16))
292 return -EOPNOTSUPP;
293
262 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, dst, 294 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, dst,
263 sizeof(__be16), reg); 295 sizeof(__be16), reg);
264 break; 296 break;
@@ -277,10 +309,16 @@ static int nft_payload_offload_udp(struct nft_offload_ctx *ctx,
277 309
278 switch (priv->offset) { 310 switch (priv->offset) {
279 case offsetof(struct udphdr, source): 311 case offsetof(struct udphdr, source):
312 if (priv->len != sizeof(__be16))
313 return -EOPNOTSUPP;
314
280 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, src, 315 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, src,
281 sizeof(__be16), reg); 316 sizeof(__be16), reg);
282 break; 317 break;
283 case offsetof(struct udphdr, dest): 318 case offsetof(struct udphdr, dest):
319 if (priv->len != sizeof(__be16))
320 return -EOPNOTSUPP;
321
284 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, dst, 322 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, dst,
285 sizeof(__be16), reg); 323 sizeof(__be16), reg);
286 break; 324 break;