Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v5.3-rc5 620 lines 16 kB view raw
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net> 4 * Copyright (c) 2016 Pablo Neira Ayuso <pablo@netfilter.org> 5 * 6 * Development of this code funded by Astaro AG (http://www.astaro.com/) 7 */ 8 9#include <linux/kernel.h> 10#include <linux/if_vlan.h> 11#include <linux/init.h> 12#include <linux/module.h> 13#include <linux/netlink.h> 14#include <linux/netfilter.h> 15#include <linux/netfilter/nf_tables.h> 16#include <net/netfilter/nf_tables_core.h> 17#include <net/netfilter/nf_tables.h> 18#include <net/netfilter/nf_tables_offload.h> 19/* For layer 4 checksum field offset. */ 20#include <linux/tcp.h> 21#include <linux/udp.h> 22#include <linux/icmpv6.h> 23#include <linux/ip.h> 24#include <linux/ipv6.h> 25 26/* add vlan header into the user buffer for if tag was removed by offloads */ 27static bool 28nft_payload_copy_vlan(u32 *d, const struct sk_buff *skb, u8 offset, u8 len) 29{ 30 int mac_off = skb_mac_header(skb) - skb->data; 31 u8 vlan_len, *vlanh, *dst_u8 = (u8 *) d; 32 struct vlan_ethhdr veth; 33 34 vlanh = (u8 *) &veth; 35 if (offset < ETH_HLEN) { 36 u8 ethlen = min_t(u8, len, ETH_HLEN - offset); 37 38 if (skb_copy_bits(skb, mac_off, &veth, ETH_HLEN)) 39 return false; 40 41 veth.h_vlan_proto = skb->vlan_proto; 42 43 memcpy(dst_u8, vlanh + offset, ethlen); 44 45 len -= ethlen; 46 if (len == 0) 47 return true; 48 49 dst_u8 += ethlen; 50 offset = ETH_HLEN; 51 } else if (offset >= VLAN_ETH_HLEN) { 52 offset -= VLAN_HLEN; 53 goto skip; 54 } 55 56 veth.h_vlan_TCI = htons(skb_vlan_tag_get(skb)); 57 veth.h_vlan_encapsulated_proto = skb->protocol; 58 59 vlanh += offset; 60 61 vlan_len = min_t(u8, len, VLAN_ETH_HLEN - offset); 62 memcpy(dst_u8, vlanh, vlan_len); 63 64 len -= vlan_len; 65 if (!len) 66 return true; 67 68 dst_u8 += vlan_len; 69 skip: 70 return skb_copy_bits(skb, offset + mac_off, dst_u8, len) == 0; 71} 72 73void nft_payload_eval(const struct nft_expr *expr, 74 struct nft_regs *regs, 75 const struct nft_pktinfo *pkt) 76{ 77 const struct nft_payload *priv = nft_expr_priv(expr); 78 const struct sk_buff *skb = pkt->skb; 79 u32 *dest = &regs->data[priv->dreg]; 80 int offset; 81 82 dest[priv->len / NFT_REG32_SIZE] = 0; 83 switch (priv->base) { 84 case NFT_PAYLOAD_LL_HEADER: 85 if (!skb_mac_header_was_set(skb)) 86 goto err; 87 88 if (skb_vlan_tag_present(skb)) { 89 if (!nft_payload_copy_vlan(dest, skb, 90 priv->offset, priv->len)) 91 goto err; 92 return; 93 } 94 offset = skb_mac_header(skb) - skb->data; 95 break; 96 case NFT_PAYLOAD_NETWORK_HEADER: 97 offset = skb_network_offset(skb); 98 break; 99 case NFT_PAYLOAD_TRANSPORT_HEADER: 100 if (!pkt->tprot_set) 101 goto err; 102 offset = pkt->xt.thoff; 103 break; 104 default: 105 BUG(); 106 } 107 offset += priv->offset; 108 109 if (skb_copy_bits(skb, offset, dest, priv->len) < 0) 110 goto err; 111 return; 112err: 113 regs->verdict.code = NFT_BREAK; 114} 115 116static const struct nla_policy nft_payload_policy[NFTA_PAYLOAD_MAX + 1] = { 117 [NFTA_PAYLOAD_SREG] = { .type = NLA_U32 }, 118 [NFTA_PAYLOAD_DREG] = { .type = NLA_U32 }, 119 [NFTA_PAYLOAD_BASE] = { .type = NLA_U32 }, 120 [NFTA_PAYLOAD_OFFSET] = { .type = NLA_U32 }, 121 [NFTA_PAYLOAD_LEN] = { .type = NLA_U32 }, 122 [NFTA_PAYLOAD_CSUM_TYPE] = { .type = NLA_U32 }, 123 [NFTA_PAYLOAD_CSUM_OFFSET] = { .type = NLA_U32 }, 124}; 125 126static int nft_payload_init(const struct nft_ctx *ctx, 127 const struct nft_expr *expr, 128 const struct nlattr * const tb[]) 129{ 130 struct nft_payload *priv = nft_expr_priv(expr); 131 132 priv->base = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_BASE])); 133 priv->offset = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_OFFSET])); 134 priv->len = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_LEN])); 135 priv->dreg = nft_parse_register(tb[NFTA_PAYLOAD_DREG]); 136 137 return nft_validate_register_store(ctx, priv->dreg, NULL, 138 NFT_DATA_VALUE, priv->len); 139} 140 141static int nft_payload_dump(struct sk_buff *skb, const struct nft_expr *expr) 142{ 143 const struct nft_payload *priv = nft_expr_priv(expr); 144 145 if (nft_dump_register(skb, NFTA_PAYLOAD_DREG, priv->dreg) || 146 nla_put_be32(skb, NFTA_PAYLOAD_BASE, htonl(priv->base)) || 147 nla_put_be32(skb, NFTA_PAYLOAD_OFFSET, htonl(priv->offset)) || 148 nla_put_be32(skb, NFTA_PAYLOAD_LEN, htonl(priv->len))) 149 goto nla_put_failure; 150 return 0; 151 152nla_put_failure: 153 return -1; 154} 155 156static int nft_payload_offload_ll(struct nft_offload_ctx *ctx, 157 struct nft_flow_rule *flow, 158 const struct nft_payload *priv) 159{ 160 struct nft_offload_reg *reg = &ctx->regs[priv->dreg]; 161 162 switch (priv->offset) { 163 case offsetof(struct ethhdr, h_source): 164 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_ETH_ADDRS, eth_addrs, 165 src, ETH_ALEN, reg); 166 break; 167 case offsetof(struct ethhdr, h_dest): 168 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_ETH_ADDRS, eth_addrs, 169 dst, ETH_ALEN, reg); 170 break; 171 } 172 173 return 0; 174} 175 176static int nft_payload_offload_ip(struct nft_offload_ctx *ctx, 177 struct nft_flow_rule *flow, 178 const struct nft_payload *priv) 179{ 180 struct nft_offload_reg *reg = &ctx->regs[priv->dreg]; 181 182 switch (priv->offset) { 183 case offsetof(struct iphdr, saddr): 184 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV4_ADDRS, ipv4, src, 185 sizeof(struct in_addr), reg); 186 break; 187 case offsetof(struct iphdr, daddr): 188 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV4_ADDRS, ipv4, dst, 189 sizeof(struct in_addr), reg); 190 break; 191 case offsetof(struct iphdr, protocol): 192 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_BASIC, basic, ip_proto, 193 sizeof(__u8), reg); 194 nft_offload_set_dependency(ctx, NFT_OFFLOAD_DEP_TRANSPORT); 195 break; 196 default: 197 return -EOPNOTSUPP; 198 } 199 200 return 0; 201} 202 203static int nft_payload_offload_ip6(struct nft_offload_ctx *ctx, 204 struct nft_flow_rule *flow, 205 const struct nft_payload *priv) 206{ 207 struct nft_offload_reg *reg = &ctx->regs[priv->dreg]; 208 209 switch (priv->offset) { 210 case offsetof(struct ipv6hdr, saddr): 211 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV6_ADDRS, ipv6, src, 212 sizeof(struct in6_addr), reg); 213 break; 214 case offsetof(struct ipv6hdr, daddr): 215 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV6_ADDRS, ipv6, dst, 216 sizeof(struct in6_addr), reg); 217 break; 218 case offsetof(struct ipv6hdr, nexthdr): 219 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_BASIC, basic, ip_proto, 220 sizeof(__u8), reg); 221 nft_offload_set_dependency(ctx, NFT_OFFLOAD_DEP_TRANSPORT); 222 break; 223 default: 224 return -EOPNOTSUPP; 225 } 226 227 return 0; 228} 229 230static int nft_payload_offload_nh(struct nft_offload_ctx *ctx, 231 struct nft_flow_rule *flow, 232 const struct nft_payload *priv) 233{ 234 int err; 235 236 switch (ctx->dep.l3num) { 237 case htons(ETH_P_IP): 238 err = nft_payload_offload_ip(ctx, flow, priv); 239 break; 240 case htons(ETH_P_IPV6): 241 err = nft_payload_offload_ip6(ctx, flow, priv); 242 break; 243 default: 244 return -EOPNOTSUPP; 245 } 246 247 return err; 248} 249 250static int nft_payload_offload_tcp(struct nft_offload_ctx *ctx, 251 struct nft_flow_rule *flow, 252 const struct nft_payload *priv) 253{ 254 struct nft_offload_reg *reg = &ctx->regs[priv->dreg]; 255 256 switch (priv->offset) { 257 case offsetof(struct tcphdr, source): 258 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, src, 259 sizeof(__be16), reg); 260 break; 261 case offsetof(struct tcphdr, dest): 262 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, dst, 263 sizeof(__be16), reg); 264 break; 265 default: 266 return -EOPNOTSUPP; 267 } 268 269 return 0; 270} 271 272static int nft_payload_offload_udp(struct nft_offload_ctx *ctx, 273 struct nft_flow_rule *flow, 274 const struct nft_payload *priv) 275{ 276 struct nft_offload_reg *reg = &ctx->regs[priv->dreg]; 277 278 switch (priv->offset) { 279 case offsetof(struct udphdr, source): 280 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, src, 281 sizeof(__be16), reg); 282 break; 283 case offsetof(struct udphdr, dest): 284 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, dst, 285 sizeof(__be16), reg); 286 break; 287 default: 288 return -EOPNOTSUPP; 289 } 290 291 return 0; 292} 293 294static int nft_payload_offload_th(struct nft_offload_ctx *ctx, 295 struct nft_flow_rule *flow, 296 const struct nft_payload *priv) 297{ 298 int err; 299 300 switch (ctx->dep.protonum) { 301 case IPPROTO_TCP: 302 err = nft_payload_offload_tcp(ctx, flow, priv); 303 break; 304 case IPPROTO_UDP: 305 err = nft_payload_offload_udp(ctx, flow, priv); 306 break; 307 default: 308 return -EOPNOTSUPP; 309 } 310 311 return err; 312} 313 314static int nft_payload_offload(struct nft_offload_ctx *ctx, 315 struct nft_flow_rule *flow, 316 const struct nft_expr *expr) 317{ 318 const struct nft_payload *priv = nft_expr_priv(expr); 319 int err; 320 321 switch (priv->base) { 322 case NFT_PAYLOAD_LL_HEADER: 323 err = nft_payload_offload_ll(ctx, flow, priv); 324 break; 325 case NFT_PAYLOAD_NETWORK_HEADER: 326 err = nft_payload_offload_nh(ctx, flow, priv); 327 break; 328 case NFT_PAYLOAD_TRANSPORT_HEADER: 329 err = nft_payload_offload_th(ctx, flow, priv); 330 break; 331 default: 332 err = -EOPNOTSUPP; 333 break; 334 } 335 return err; 336} 337 338static const struct nft_expr_ops nft_payload_ops = { 339 .type = &nft_payload_type, 340 .size = NFT_EXPR_SIZE(sizeof(struct nft_payload)), 341 .eval = nft_payload_eval, 342 .init = nft_payload_init, 343 .dump = nft_payload_dump, 344 .offload = nft_payload_offload, 345}; 346 347const struct nft_expr_ops nft_payload_fast_ops = { 348 .type = &nft_payload_type, 349 .size = NFT_EXPR_SIZE(sizeof(struct nft_payload)), 350 .eval = nft_payload_eval, 351 .init = nft_payload_init, 352 .dump = nft_payload_dump, 353 .offload = nft_payload_offload, 354}; 355 356static inline void nft_csum_replace(__sum16 *sum, __wsum fsum, __wsum tsum) 357{ 358 *sum = csum_fold(csum_add(csum_sub(~csum_unfold(*sum), fsum), tsum)); 359 if (*sum == 0) 360 *sum = CSUM_MANGLED_0; 361} 362 363static bool nft_payload_udp_checksum(struct sk_buff *skb, unsigned int thoff) 364{ 365 struct udphdr *uh, _uh; 366 367 uh = skb_header_pointer(skb, thoff, sizeof(_uh), &_uh); 368 if (!uh) 369 return false; 370 371 return (__force bool)uh->check; 372} 373 374static int nft_payload_l4csum_offset(const struct nft_pktinfo *pkt, 375 struct sk_buff *skb, 376 unsigned int *l4csum_offset) 377{ 378 switch (pkt->tprot) { 379 case IPPROTO_TCP: 380 *l4csum_offset = offsetof(struct tcphdr, check); 381 break; 382 case IPPROTO_UDP: 383 if (!nft_payload_udp_checksum(skb, pkt->xt.thoff)) 384 return -1; 385 /* Fall through. */ 386 case IPPROTO_UDPLITE: 387 *l4csum_offset = offsetof(struct udphdr, check); 388 break; 389 case IPPROTO_ICMPV6: 390 *l4csum_offset = offsetof(struct icmp6hdr, icmp6_cksum); 391 break; 392 default: 393 return -1; 394 } 395 396 *l4csum_offset += pkt->xt.thoff; 397 return 0; 398} 399 400static int nft_payload_l4csum_update(const struct nft_pktinfo *pkt, 401 struct sk_buff *skb, 402 __wsum fsum, __wsum tsum) 403{ 404 int l4csum_offset; 405 __sum16 sum; 406 407 /* If we cannot determine layer 4 checksum offset or this packet doesn't 408 * require layer 4 checksum recalculation, skip this packet. 409 */ 410 if (nft_payload_l4csum_offset(pkt, skb, &l4csum_offset) < 0) 411 return 0; 412 413 if (skb_copy_bits(skb, l4csum_offset, &sum, sizeof(sum)) < 0) 414 return -1; 415 416 /* Checksum mangling for an arbitrary amount of bytes, based on 417 * inet_proto_csum_replace*() functions. 418 */ 419 if (skb->ip_summed != CHECKSUM_PARTIAL) { 420 nft_csum_replace(&sum, fsum, tsum); 421 if (skb->ip_summed == CHECKSUM_COMPLETE) { 422 skb->csum = ~csum_add(csum_sub(~(skb->csum), fsum), 423 tsum); 424 } 425 } else { 426 sum = ~csum_fold(csum_add(csum_sub(csum_unfold(sum), fsum), 427 tsum)); 428 } 429 430 if (skb_ensure_writable(skb, l4csum_offset + sizeof(sum)) || 431 skb_store_bits(skb, l4csum_offset, &sum, sizeof(sum)) < 0) 432 return -1; 433 434 return 0; 435} 436 437static int nft_payload_csum_inet(struct sk_buff *skb, const u32 *src, 438 __wsum fsum, __wsum tsum, int csum_offset) 439{ 440 __sum16 sum; 441 442 if (skb_copy_bits(skb, csum_offset, &sum, sizeof(sum)) < 0) 443 return -1; 444 445 nft_csum_replace(&sum, fsum, tsum); 446 if (skb_ensure_writable(skb, csum_offset + sizeof(sum)) || 447 skb_store_bits(skb, csum_offset, &sum, sizeof(sum)) < 0) 448 return -1; 449 450 return 0; 451} 452 453static void nft_payload_set_eval(const struct nft_expr *expr, 454 struct nft_regs *regs, 455 const struct nft_pktinfo *pkt) 456{ 457 const struct nft_payload_set *priv = nft_expr_priv(expr); 458 struct sk_buff *skb = pkt->skb; 459 const u32 *src = &regs->data[priv->sreg]; 460 int offset, csum_offset; 461 __wsum fsum, tsum; 462 463 switch (priv->base) { 464 case NFT_PAYLOAD_LL_HEADER: 465 if (!skb_mac_header_was_set(skb)) 466 goto err; 467 offset = skb_mac_header(skb) - skb->data; 468 break; 469 case NFT_PAYLOAD_NETWORK_HEADER: 470 offset = skb_network_offset(skb); 471 break; 472 case NFT_PAYLOAD_TRANSPORT_HEADER: 473 if (!pkt->tprot_set) 474 goto err; 475 offset = pkt->xt.thoff; 476 break; 477 default: 478 BUG(); 479 } 480 481 csum_offset = offset + priv->csum_offset; 482 offset += priv->offset; 483 484 if ((priv->csum_type == NFT_PAYLOAD_CSUM_INET || priv->csum_flags) && 485 (priv->base != NFT_PAYLOAD_TRANSPORT_HEADER || 486 skb->ip_summed != CHECKSUM_PARTIAL)) { 487 fsum = skb_checksum(skb, offset, priv->len, 0); 488 tsum = csum_partial(src, priv->len, 0); 489 490 if (priv->csum_type == NFT_PAYLOAD_CSUM_INET && 491 nft_payload_csum_inet(skb, src, fsum, tsum, csum_offset)) 492 goto err; 493 494 if (priv->csum_flags && 495 nft_payload_l4csum_update(pkt, skb, fsum, tsum) < 0) 496 goto err; 497 } 498 499 if (skb_ensure_writable(skb, max(offset + priv->len, 0)) || 500 skb_store_bits(skb, offset, src, priv->len) < 0) 501 goto err; 502 503 return; 504err: 505 regs->verdict.code = NFT_BREAK; 506} 507 508static int nft_payload_set_init(const struct nft_ctx *ctx, 509 const struct nft_expr *expr, 510 const struct nlattr * const tb[]) 511{ 512 struct nft_payload_set *priv = nft_expr_priv(expr); 513 514 priv->base = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_BASE])); 515 priv->offset = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_OFFSET])); 516 priv->len = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_LEN])); 517 priv->sreg = nft_parse_register(tb[NFTA_PAYLOAD_SREG]); 518 519 if (tb[NFTA_PAYLOAD_CSUM_TYPE]) 520 priv->csum_type = 521 ntohl(nla_get_be32(tb[NFTA_PAYLOAD_CSUM_TYPE])); 522 if (tb[NFTA_PAYLOAD_CSUM_OFFSET]) 523 priv->csum_offset = 524 ntohl(nla_get_be32(tb[NFTA_PAYLOAD_CSUM_OFFSET])); 525 if (tb[NFTA_PAYLOAD_CSUM_FLAGS]) { 526 u32 flags; 527 528 flags = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_CSUM_FLAGS])); 529 if (flags & ~NFT_PAYLOAD_L4CSUM_PSEUDOHDR) 530 return -EINVAL; 531 532 priv->csum_flags = flags; 533 } 534 535 switch (priv->csum_type) { 536 case NFT_PAYLOAD_CSUM_NONE: 537 case NFT_PAYLOAD_CSUM_INET: 538 break; 539 default: 540 return -EOPNOTSUPP; 541 } 542 543 return nft_validate_register_load(priv->sreg, priv->len); 544} 545 546static int nft_payload_set_dump(struct sk_buff *skb, const struct nft_expr *expr) 547{ 548 const struct nft_payload_set *priv = nft_expr_priv(expr); 549 550 if (nft_dump_register(skb, NFTA_PAYLOAD_SREG, priv->sreg) || 551 nla_put_be32(skb, NFTA_PAYLOAD_BASE, htonl(priv->base)) || 552 nla_put_be32(skb, NFTA_PAYLOAD_OFFSET, htonl(priv->offset)) || 553 nla_put_be32(skb, NFTA_PAYLOAD_LEN, htonl(priv->len)) || 554 nla_put_be32(skb, NFTA_PAYLOAD_CSUM_TYPE, htonl(priv->csum_type)) || 555 nla_put_be32(skb, NFTA_PAYLOAD_CSUM_OFFSET, 556 htonl(priv->csum_offset)) || 557 nla_put_be32(skb, NFTA_PAYLOAD_CSUM_FLAGS, htonl(priv->csum_flags))) 558 goto nla_put_failure; 559 return 0; 560 561nla_put_failure: 562 return -1; 563} 564 565static const struct nft_expr_ops nft_payload_set_ops = { 566 .type = &nft_payload_type, 567 .size = NFT_EXPR_SIZE(sizeof(struct nft_payload_set)), 568 .eval = nft_payload_set_eval, 569 .init = nft_payload_set_init, 570 .dump = nft_payload_set_dump, 571}; 572 573static const struct nft_expr_ops * 574nft_payload_select_ops(const struct nft_ctx *ctx, 575 const struct nlattr * const tb[]) 576{ 577 enum nft_payload_bases base; 578 unsigned int offset, len; 579 580 if (tb[NFTA_PAYLOAD_BASE] == NULL || 581 tb[NFTA_PAYLOAD_OFFSET] == NULL || 582 tb[NFTA_PAYLOAD_LEN] == NULL) 583 return ERR_PTR(-EINVAL); 584 585 base = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_BASE])); 586 switch (base) { 587 case NFT_PAYLOAD_LL_HEADER: 588 case NFT_PAYLOAD_NETWORK_HEADER: 589 case NFT_PAYLOAD_TRANSPORT_HEADER: 590 break; 591 default: 592 return ERR_PTR(-EOPNOTSUPP); 593 } 594 595 if (tb[NFTA_PAYLOAD_SREG] != NULL) { 596 if (tb[NFTA_PAYLOAD_DREG] != NULL) 597 return ERR_PTR(-EINVAL); 598 return &nft_payload_set_ops; 599 } 600 601 if (tb[NFTA_PAYLOAD_DREG] == NULL) 602 return ERR_PTR(-EINVAL); 603 604 offset = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_OFFSET])); 605 len = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_LEN])); 606 607 if (len <= 4 && is_power_of_2(len) && IS_ALIGNED(offset, len) && 608 base != NFT_PAYLOAD_LL_HEADER) 609 return &nft_payload_fast_ops; 610 else 611 return &nft_payload_ops; 612} 613 614struct nft_expr_type nft_payload_type __read_mostly = { 615 .name = "payload", 616 .select_ops = nft_payload_select_ops, 617 .policy = nft_payload_policy, 618 .maxattr = NFTA_PAYLOAD_MAX, 619 .owner = THIS_MODULE, 620};