Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

netfilter: flowtable: strictly check for maximum number of actions

The maximum number of flowtable hardware offload actions in IPv6 is:

* ethernet mangling (4 payload actions, 2 for each ethernet address)
* SNAT (4 payload actions)
* DNAT (4 payload actions)
* Double VLAN (4 vlan actions, 2 for popping vlan, and 2 for pushing)
for QinQ.
* Redirect (1 action)

Which makes 17, while the maximum is 16. But act_ct supports for tunnels
actions too. Note that payload action operates at 32-bit word level, so
mangling an IPv6 address takes 4 payload actions.

Update flow_action_entry_next() calls to check for the maximum number of
supported actions.

While at it, rise the maximum number of actions per flow from 16 to 24
so this works fine with IPv6 setups.

Fixes: c29f74e0df7a ("netfilter: nf_flow_table: hardware offload support")
Reported-by: Hyunwoo Kim <imv4bel@gmail.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

+130 -66
+130 -66
net/netfilter/nf_flow_table_offload.c
··· 14 14 #include <net/netfilter/nf_conntrack_core.h> 15 15 #include <net/netfilter/nf_conntrack_tuple.h> 16 16 17 + #define NF_FLOW_RULE_ACTION_MAX 24 18 + 17 19 static struct workqueue_struct *nf_flow_offload_add_wq; 18 20 static struct workqueue_struct *nf_flow_offload_del_wq; 19 21 static struct workqueue_struct *nf_flow_offload_stats_wq; ··· 218 216 static inline struct flow_action_entry * 219 217 flow_action_entry_next(struct nf_flow_rule *flow_rule) 220 218 { 221 - int i = flow_rule->rule->action.num_entries++; 219 + int i; 220 + 221 + if (unlikely(flow_rule->rule->action.num_entries >= NF_FLOW_RULE_ACTION_MAX)) 222 + return NULL; 223 + 224 + i = flow_rule->rule->action.num_entries++; 222 225 223 226 return &flow_rule->rule->action.entries[i]; 224 227 } ··· 240 233 const unsigned char *addr; 241 234 u32 mask, val; 242 235 u16 val16; 236 + 237 + if (!entry0 || !entry1) 238 + return -E2BIG; 243 239 244 240 this_tuple = &flow->tuplehash[dir].tuple; 245 241 ··· 294 284 u8 nud_state; 295 285 u16 val16; 296 286 287 + if (!entry0 || !entry1) 288 + return -E2BIG; 289 + 297 290 this_tuple = &flow->tuplehash[dir].tuple; 298 291 299 292 switch (this_tuple->xmit_type) { ··· 338 325 return 0; 339 326 } 340 327 341 - static void flow_offload_ipv4_snat(struct net *net, 342 - const struct flow_offload *flow, 343 - enum flow_offload_tuple_dir dir, 344 - struct nf_flow_rule *flow_rule) 328 + static int flow_offload_ipv4_snat(struct net *net, 329 + const struct flow_offload *flow, 330 + enum flow_offload_tuple_dir dir, 331 + struct nf_flow_rule *flow_rule) 345 332 { 346 333 struct flow_action_entry *entry = flow_action_entry_next(flow_rule); 347 334 u32 mask = ~htonl(0xffffffff); 348 335 __be32 addr; 349 336 u32 offset; 337 + 338 + if (!entry) 339 + return -E2BIG; 350 340 351 341 switch (dir) { 352 342 case FLOW_OFFLOAD_DIR_ORIGINAL: ··· 361 345 offset = offsetof(struct iphdr, daddr); 362 346 break; 363 347 default: 364 - return; 348 + return -EOPNOTSUPP; 365 349 } 366 350 367 351 flow_offload_mangle(entry, FLOW_ACT_MANGLE_HDR_TYPE_IP4, offset, 368 352 &addr, &mask); 353 + return 0; 369 354 } 370 355 371 - static void flow_offload_ipv4_dnat(struct net *net, 372 - const struct flow_offload *flow, 373 - enum flow_offload_tuple_dir dir, 374 - struct nf_flow_rule *flow_rule) 356 + static int flow_offload_ipv4_dnat(struct net *net, 357 + const struct flow_offload *flow, 358 + enum flow_offload_tuple_dir dir, 359 + struct nf_flow_rule *flow_rule) 375 360 { 376 361 struct flow_action_entry *entry = flow_action_entry_next(flow_rule); 377 362 u32 mask = ~htonl(0xffffffff); 378 363 __be32 addr; 379 364 u32 offset; 365 + 366 + if (!entry) 367 + return -E2BIG; 380 368 381 369 switch (dir) { 382 370 case FLOW_OFFLOAD_DIR_ORIGINAL: ··· 392 372 offset = offsetof(struct iphdr, saddr); 393 373 break; 394 374 default: 395 - return; 375 + return -EOPNOTSUPP; 396 376 } 397 377 398 378 flow_offload_mangle(entry, FLOW_ACT_MANGLE_HDR_TYPE_IP4, offset, 399 379 &addr, &mask); 380 + return 0; 400 381 } 401 382 402 - static void flow_offload_ipv6_mangle(struct nf_flow_rule *flow_rule, 383 + static int flow_offload_ipv6_mangle(struct nf_flow_rule *flow_rule, 403 384 unsigned int offset, 404 385 const __be32 *addr, const __be32 *mask) 405 386 { ··· 409 388 410 389 for (i = 0; i < sizeof(struct in6_addr) / sizeof(u32); i++) { 411 390 entry = flow_action_entry_next(flow_rule); 391 + if (!entry) 392 + return -E2BIG; 393 + 412 394 flow_offload_mangle(entry, FLOW_ACT_MANGLE_HDR_TYPE_IP6, 413 395 offset + i * sizeof(u32), &addr[i], mask); 414 396 } 397 + 398 + return 0; 415 399 } 416 400 417 - static void flow_offload_ipv6_snat(struct net *net, 418 - const struct flow_offload *flow, 419 - enum flow_offload_tuple_dir dir, 420 - struct nf_flow_rule *flow_rule) 401 + static int flow_offload_ipv6_snat(struct net *net, 402 + const struct flow_offload *flow, 403 + enum flow_offload_tuple_dir dir, 404 + struct nf_flow_rule *flow_rule) 421 405 { 422 406 u32 mask = ~htonl(0xffffffff); 423 407 const __be32 *addr; ··· 438 412 offset = offsetof(struct ipv6hdr, daddr); 439 413 break; 440 414 default: 441 - return; 415 + return -EOPNOTSUPP; 442 416 } 443 417 444 - flow_offload_ipv6_mangle(flow_rule, offset, addr, &mask); 418 + return flow_offload_ipv6_mangle(flow_rule, offset, addr, &mask); 445 419 } 446 420 447 - static void flow_offload_ipv6_dnat(struct net *net, 448 - const struct flow_offload *flow, 449 - enum flow_offload_tuple_dir dir, 450 - struct nf_flow_rule *flow_rule) 421 + static int flow_offload_ipv6_dnat(struct net *net, 422 + const struct flow_offload *flow, 423 + enum flow_offload_tuple_dir dir, 424 + struct nf_flow_rule *flow_rule) 451 425 { 452 426 u32 mask = ~htonl(0xffffffff); 453 427 const __be32 *addr; ··· 463 437 offset = offsetof(struct ipv6hdr, saddr); 464 438 break; 465 439 default: 466 - return; 440 + return -EOPNOTSUPP; 467 441 } 468 442 469 - flow_offload_ipv6_mangle(flow_rule, offset, addr, &mask); 443 + return flow_offload_ipv6_mangle(flow_rule, offset, addr, &mask); 470 444 } 471 445 472 446 static int flow_offload_l4proto(const struct flow_offload *flow) ··· 488 462 return type; 489 463 } 490 464 491 - static void flow_offload_port_snat(struct net *net, 492 - const struct flow_offload *flow, 493 - enum flow_offload_tuple_dir dir, 494 - struct nf_flow_rule *flow_rule) 465 + static int flow_offload_port_snat(struct net *net, 466 + const struct flow_offload *flow, 467 + enum flow_offload_tuple_dir dir, 468 + struct nf_flow_rule *flow_rule) 495 469 { 496 470 struct flow_action_entry *entry = flow_action_entry_next(flow_rule); 497 471 u32 mask, port; 498 472 u32 offset; 473 + 474 + if (!entry) 475 + return -E2BIG; 499 476 500 477 switch (dir) { 501 478 case FLOW_OFFLOAD_DIR_ORIGINAL: ··· 514 485 mask = ~htonl(0xffff); 515 486 break; 516 487 default: 517 - return; 488 + return -EOPNOTSUPP; 518 489 } 519 490 520 491 flow_offload_mangle(entry, flow_offload_l4proto(flow), offset, 521 492 &port, &mask); 493 + return 0; 522 494 } 523 495 524 - static void flow_offload_port_dnat(struct net *net, 525 - const struct flow_offload *flow, 526 - enum flow_offload_tuple_dir dir, 527 - struct nf_flow_rule *flow_rule) 496 + static int flow_offload_port_dnat(struct net *net, 497 + const struct flow_offload *flow, 498 + enum flow_offload_tuple_dir dir, 499 + struct nf_flow_rule *flow_rule) 528 500 { 529 501 struct flow_action_entry *entry = flow_action_entry_next(flow_rule); 530 502 u32 mask, port; 531 503 u32 offset; 504 + 505 + if (!entry) 506 + return -E2BIG; 532 507 533 508 switch (dir) { 534 509 case FLOW_OFFLOAD_DIR_ORIGINAL: ··· 548 515 mask = ~htonl(0xffff0000); 549 516 break; 550 517 default: 551 - return; 518 + return -EOPNOTSUPP; 552 519 } 553 520 554 521 flow_offload_mangle(entry, flow_offload_l4proto(flow), offset, 555 522 &port, &mask); 523 + return 0; 556 524 } 557 525 558 - static void flow_offload_ipv4_checksum(struct net *net, 559 - const struct flow_offload *flow, 560 - struct nf_flow_rule *flow_rule) 526 + static int flow_offload_ipv4_checksum(struct net *net, 527 + const struct flow_offload *flow, 528 + struct nf_flow_rule *flow_rule) 561 529 { 562 530 u8 protonum = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.l4proto; 563 531 struct flow_action_entry *entry = flow_action_entry_next(flow_rule); 532 + 533 + if (!entry) 534 + return -E2BIG; 564 535 565 536 entry->id = FLOW_ACTION_CSUM; 566 537 entry->csum_flags = TCA_CSUM_UPDATE_FLAG_IPV4HDR; ··· 577 540 entry->csum_flags |= TCA_CSUM_UPDATE_FLAG_UDP; 578 541 break; 579 542 } 543 + 544 + return 0; 580 545 } 581 546 582 - static void flow_offload_redirect(struct net *net, 583 - const struct flow_offload *flow, 584 - enum flow_offload_tuple_dir dir, 585 - struct nf_flow_rule *flow_rule) 547 + static int flow_offload_redirect(struct net *net, 548 + const struct flow_offload *flow, 549 + enum flow_offload_tuple_dir dir, 550 + struct nf_flow_rule *flow_rule) 586 551 { 587 552 const struct flow_offload_tuple *this_tuple, *other_tuple; 588 553 struct flow_action_entry *entry; ··· 602 563 ifindex = other_tuple->iifidx; 603 564 break; 604 565 default: 605 - return; 566 + return -EOPNOTSUPP; 606 567 } 607 568 608 569 dev = dev_get_by_index(net, ifindex); 609 570 if (!dev) 610 - return; 571 + return -ENODEV; 611 572 612 573 entry = flow_action_entry_next(flow_rule); 574 + if (!entry) { 575 + dev_put(dev); 576 + return -E2BIG; 577 + } 578 + 613 579 entry->id = FLOW_ACTION_REDIRECT; 614 580 entry->dev = dev; 581 + 582 + return 0; 615 583 } 616 584 617 - static void flow_offload_encap_tunnel(const struct flow_offload *flow, 618 - enum flow_offload_tuple_dir dir, 619 - struct nf_flow_rule *flow_rule) 585 + static int flow_offload_encap_tunnel(const struct flow_offload *flow, 586 + enum flow_offload_tuple_dir dir, 587 + struct nf_flow_rule *flow_rule) 620 588 { 621 589 const struct flow_offload_tuple *this_tuple; 622 590 struct flow_action_entry *entry; ··· 631 585 632 586 this_tuple = &flow->tuplehash[dir].tuple; 633 587 if (this_tuple->xmit_type == FLOW_OFFLOAD_XMIT_DIRECT) 634 - return; 588 + return 0; 635 589 636 590 dst = this_tuple->dst_cache; 637 591 if (dst && dst->lwtstate) { ··· 640 594 tun_info = lwt_tun_info(dst->lwtstate); 641 595 if (tun_info && (tun_info->mode & IP_TUNNEL_INFO_TX)) { 642 596 entry = flow_action_entry_next(flow_rule); 597 + if (!entry) 598 + return -E2BIG; 643 599 entry->id = FLOW_ACTION_TUNNEL_ENCAP; 644 600 entry->tunnel = tun_info; 645 601 } 646 602 } 603 + 604 + return 0; 647 605 } 648 606 649 - static void flow_offload_decap_tunnel(const struct flow_offload *flow, 650 - enum flow_offload_tuple_dir dir, 651 - struct nf_flow_rule *flow_rule) 607 + static int flow_offload_decap_tunnel(const struct flow_offload *flow, 608 + enum flow_offload_tuple_dir dir, 609 + struct nf_flow_rule *flow_rule) 652 610 { 653 611 const struct flow_offload_tuple *other_tuple; 654 612 struct flow_action_entry *entry; ··· 660 610 661 611 other_tuple = &flow->tuplehash[!dir].tuple; 662 612 if (other_tuple->xmit_type == FLOW_OFFLOAD_XMIT_DIRECT) 663 - return; 613 + return 0; 664 614 665 615 dst = other_tuple->dst_cache; 666 616 if (dst && dst->lwtstate) { ··· 669 619 tun_info = lwt_tun_info(dst->lwtstate); 670 620 if (tun_info && (tun_info->mode & IP_TUNNEL_INFO_TX)) { 671 621 entry = flow_action_entry_next(flow_rule); 622 + if (!entry) 623 + return -E2BIG; 672 624 entry->id = FLOW_ACTION_TUNNEL_DECAP; 673 625 } 674 626 } 627 + 628 + return 0; 675 629 } 676 630 677 631 static int ··· 687 633 const struct flow_offload_tuple *tuple; 688 634 int i; 689 635 690 - flow_offload_decap_tunnel(flow, dir, flow_rule); 691 - flow_offload_encap_tunnel(flow, dir, flow_rule); 636 + if (flow_offload_decap_tunnel(flow, dir, flow_rule) < 0 || 637 + flow_offload_encap_tunnel(flow, dir, flow_rule) < 0) 638 + return -1; 692 639 693 640 if (flow_offload_eth_src(net, flow, dir, flow_rule) < 0 || 694 641 flow_offload_eth_dst(net, flow, dir, flow_rule) < 0) ··· 705 650 706 651 if (tuple->encap[i].proto == htons(ETH_P_8021Q)) { 707 652 entry = flow_action_entry_next(flow_rule); 653 + if (!entry) 654 + return -1; 708 655 entry->id = FLOW_ACTION_VLAN_POP; 709 656 } 710 657 } ··· 720 663 continue; 721 664 722 665 entry = flow_action_entry_next(flow_rule); 666 + if (!entry) 667 + return -1; 723 668 724 669 switch (other_tuple->encap[i].proto) { 725 670 case htons(ETH_P_PPP_SES): ··· 747 688 return -1; 748 689 749 690 if (test_bit(NF_FLOW_SNAT, &flow->flags)) { 750 - flow_offload_ipv4_snat(net, flow, dir, flow_rule); 751 - flow_offload_port_snat(net, flow, dir, flow_rule); 691 + if (flow_offload_ipv4_snat(net, flow, dir, flow_rule) < 0 || 692 + flow_offload_port_snat(net, flow, dir, flow_rule) < 0) 693 + return -1; 752 694 } 753 695 if (test_bit(NF_FLOW_DNAT, &flow->flags)) { 754 - flow_offload_ipv4_dnat(net, flow, dir, flow_rule); 755 - flow_offload_port_dnat(net, flow, dir, flow_rule); 696 + if (flow_offload_ipv4_dnat(net, flow, dir, flow_rule) < 0 || 697 + flow_offload_port_dnat(net, flow, dir, flow_rule) < 0) 698 + return -1; 756 699 } 757 700 if (test_bit(NF_FLOW_SNAT, &flow->flags) || 758 701 test_bit(NF_FLOW_DNAT, &flow->flags)) 759 - flow_offload_ipv4_checksum(net, flow, flow_rule); 702 + if (flow_offload_ipv4_checksum(net, flow, flow_rule) < 0) 703 + return -1; 760 704 761 - flow_offload_redirect(net, flow, dir, flow_rule); 705 + if (flow_offload_redirect(net, flow, dir, flow_rule) < 0) 706 + return -1; 762 707 763 708 return 0; 764 709 } ··· 776 713 return -1; 777 714 778 715 if (test_bit(NF_FLOW_SNAT, &flow->flags)) { 779 - flow_offload_ipv6_snat(net, flow, dir, flow_rule); 780 - flow_offload_port_snat(net, flow, dir, flow_rule); 716 + if (flow_offload_ipv6_snat(net, flow, dir, flow_rule) < 0 || 717 + flow_offload_port_snat(net, flow, dir, flow_rule) < 0) 718 + return -1; 781 719 } 782 720 if (test_bit(NF_FLOW_DNAT, &flow->flags)) { 783 - flow_offload_ipv6_dnat(net, flow, dir, flow_rule); 784 - flow_offload_port_dnat(net, flow, dir, flow_rule); 721 + if (flow_offload_ipv6_dnat(net, flow, dir, flow_rule) < 0 || 722 + flow_offload_port_dnat(net, flow, dir, flow_rule) < 0) 723 + return -1; 785 724 } 786 725 787 - flow_offload_redirect(net, flow, dir, flow_rule); 726 + if (flow_offload_redirect(net, flow, dir, flow_rule) < 0) 727 + return -1; 788 728 789 729 return 0; 790 730 } 791 731 EXPORT_SYMBOL_GPL(nf_flow_rule_route_ipv6); 792 - 793 - #define NF_FLOW_RULE_ACTION_MAX 16 794 732 795 733 static struct nf_flow_rule * 796 734 nf_flow_offload_rule_alloc(struct net *net,