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

netfilter: xtables: provide invoked family value to extensions

By passing in the family through which extensions were invoked, a bit
of data space can be reclaimed. The "family" member will be added to
the parameter structures and the check functions be adjusted.

Signed-off-by: Jan Engelhardt <jengelh@medozas.de>
Signed-off-by: Patrick McHardy <kaber@trash.net>

authored by

Jan Engelhardt and committed by
Patrick McHardy
916a917d a2df1648

+52 -24
+10 -2
include/linux/netfilter/x_tables.h
··· 183 183 * @fragoff: packet is a fragment, this is the data offset 184 184 * @thoff: position of transport header relative to skb->data 185 185 * @hotdrop: drop packet if we had inspection problems 186 + * @family: Actual NFPROTO_* through which the function is invoked 187 + * (helpful when match->family == NFPROTO_UNSPEC) 186 188 */ 187 189 struct xt_match_param { 188 190 const struct net_device *in, *out; ··· 193 191 int fragoff; 194 192 unsigned int thoff; 195 193 bool *hotdrop; 194 + u_int8_t family; 196 195 }; 197 196 198 197 /** ··· 213 210 const struct xt_match *match; 214 211 void *matchinfo; 215 212 unsigned int hook_mask; 213 + u_int8_t family; 216 214 }; 217 215 218 216 /* Match destructor parameters */ 219 217 struct xt_mtdtor_param { 220 218 const struct xt_match *match; 221 219 void *matchinfo; 220 + u_int8_t family; 222 221 }; 223 222 224 223 /** ··· 237 232 unsigned int hooknum; 238 233 const struct xt_target *target; 239 234 const void *targinfo; 235 + u_int8_t family; 240 236 }; 241 237 242 238 /** ··· 255 249 const struct xt_target *target; 256 250 void *targinfo; 257 251 unsigned int hook_mask; 252 + u_int8_t family; 258 253 }; 259 254 260 255 /* Target destructor parameters */ 261 256 struct xt_tgdtor_param { 262 257 const struct xt_target *target; 263 258 void *targinfo; 259 + u_int8_t family; 264 260 }; 265 261 266 262 struct xt_match ··· 401 393 extern int xt_register_matches(struct xt_match *match, unsigned int n); 402 394 extern void xt_unregister_matches(struct xt_match *match, unsigned int n); 403 395 404 - extern int xt_check_match(struct xt_mtchk_param *, u_int8_t family, 396 + extern int xt_check_match(struct xt_mtchk_param *, 405 397 unsigned int size, u_int8_t proto, bool inv_proto); 406 - extern int xt_check_target(struct xt_tgchk_param *, u_int8_t family, 398 + extern int xt_check_target(struct xt_tgchk_param *, 407 399 unsigned int size, u_int8_t proto, bool inv_proto); 408 400 409 401 extern struct xt_table *xt_register_table(struct net *net,
+8 -3
net/bridge/netfilter/ebtables.c
··· 160 160 struct xt_match_param mtpar; 161 161 struct xt_target_param tgpar; 162 162 163 + mtpar.family = tgpar.family = NFPROTO_BRIDGE; 163 164 mtpar.in = tgpar.in = in; 164 165 mtpar.out = tgpar.out = out; 165 166 mtpar.hotdrop = &hotdrop; ··· 352 351 353 352 par->match = match; 354 353 par->matchinfo = m->data; 355 - ret = xt_check_match(par, NFPROTO_BRIDGE, m->match_size, 354 + ret = xt_check_match(par, m->match_size, 356 355 e->ethproto, e->invflags & EBT_IPROTO); 357 356 if (ret < 0) { 358 357 module_put(match->me); ··· 387 386 388 387 par->target = watcher; 389 388 par->targinfo = w->data; 390 - ret = xt_check_target(par, NFPROTO_BRIDGE, w->watcher_size, 389 + ret = xt_check_target(par, w->watcher_size, 391 390 e->ethproto, e->invflags & EBT_IPROTO); 392 391 if (ret < 0) { 393 392 module_put(watcher->me); ··· 573 572 574 573 par.match = m->u.match; 575 574 par.matchinfo = m->data; 575 + par.family = NFPROTO_BRIDGE; 576 576 if (par.match->destroy != NULL) 577 577 par.match->destroy(&par); 578 578 module_put(par.match->me); ··· 590 588 591 589 par.target = w->u.watcher; 592 590 par.targinfo = w->data; 591 + par.family = NFPROTO_BRIDGE; 593 592 if (par.target->destroy != NULL) 594 593 par.target->destroy(&par); 595 594 module_put(par.target->me); ··· 614 611 615 612 par.target = t->u.target; 616 613 par.targinfo = t->data; 614 + par.family = NFPROTO_BRIDGE; 617 615 if (par.target->destroy != NULL) 618 616 par.target->destroy(&par); 619 617 module_put(par.target->me); ··· 677 673 mtpar.table = tgpar.table = name; 678 674 mtpar.entryinfo = tgpar.entryinfo = e; 679 675 mtpar.hook_mask = tgpar.hook_mask = hookmask; 676 + mtpar.family = tgpar.family = NFPROTO_BRIDGE; 680 677 ret = EBT_MATCH_ITERATE(e, ebt_check_match, &mtpar, &i); 681 678 if (ret != 0) 682 679 goto cleanup_matches; ··· 720 715 721 716 tgpar.target = target; 722 717 tgpar.targinfo = t->data; 723 - ret = xt_check_target(&tgpar, NFPROTO_BRIDGE, t->target_size, 718 + ret = xt_check_target(&tgpar, t->target_size, 724 719 e->ethproto, e->invflags & EBT_IPROTO); 725 720 if (ret < 0) { 726 721 module_put(target->me);
+4 -2
net/ipv4/netfilter/arp_tables.c
··· 246 246 tgpar.in = in; 247 247 tgpar.out = out; 248 248 tgpar.hooknum = hook; 249 + tgpar.family = NFPROTO_ARP; 249 250 250 251 arp = arp_hdr(skb); 251 252 do { ··· 466 465 .target = t->u.kernel.target, 467 466 .targinfo = t->data, 468 467 .hook_mask = e->comefrom, 468 + .family = NFPROTO_ARP, 469 469 }; 470 470 471 - ret = xt_check_target(&par, NFPROTO_ARP, 472 - t->u.target_size - sizeof(*t), 0, false); 471 + ret = xt_check_target(&par, t->u.target_size - sizeof(*t), 0, false); 473 472 if (ret < 0) { 474 473 duprintf("arp_tables: check failed for `%s'.\n", 475 474 t->u.kernel.target->name); ··· 567 566 t = arpt_get_target(e); 568 567 par.target = t->u.kernel.target; 569 568 par.targinfo = t->data; 569 + par.family = NFPROTO_ARP; 570 570 if (par.target->destroy != NULL) 571 571 par.target->destroy(&par); 572 572 module_put(par.target->me);
+8 -2
net/ipv4/netfilter/ip_tables.c
··· 348 348 mtpar.hotdrop = &hotdrop; 349 349 mtpar.in = tgpar.in = in; 350 350 mtpar.out = tgpar.out = out; 351 + mtpar.family = tgpar.family = NFPROTO_IPV4; 351 352 tgpar.hooknum = hook; 352 353 353 354 read_lock_bh(&table->lock); ··· 580 579 581 580 par.match = m->u.kernel.match; 582 581 par.matchinfo = m->data; 582 + par.family = NFPROTO_IPV4; 583 583 if (par.match->destroy != NULL) 584 584 par.match->destroy(&par); 585 585 module_put(par.match->me); ··· 618 616 par->match = m->u.kernel.match; 619 617 par->matchinfo = m->data; 620 618 621 - ret = xt_check_match(par, NFPROTO_IPV4, m->u.match_size - sizeof(*m), 619 + ret = xt_check_match(par, m->u.match_size - sizeof(*m), 622 620 ip->proto, ip->invflags & IPT_INV_PROTO); 623 621 if (ret < 0) { 624 622 duprintf("ip_tables: check failed for `%s'.\n", ··· 664 662 .target = t->u.kernel.target, 665 663 .targinfo = t->data, 666 664 .hook_mask = e->comefrom, 665 + .family = NFPROTO_IPV4, 667 666 }; 668 667 int ret; 669 668 670 - ret = xt_check_target(&par, NFPROTO_IPV4, t->u.target_size - sizeof(*t), 669 + ret = xt_check_target(&par, t->u.target_size - sizeof(*t), 671 670 e->ip.proto, e->ip.invflags & IPT_INV_PROTO); 672 671 if (ret < 0) { 673 672 duprintf("ip_tables: check failed for `%s'.\n", ··· 696 693 mtpar.table = name; 697 694 mtpar.entryinfo = &e->ip; 698 695 mtpar.hook_mask = e->comefrom; 696 + mtpar.family = NFPROTO_IPV4; 699 697 ret = IPT_MATCH_ITERATE(e, find_check_match, &mtpar, &j); 700 698 if (ret != 0) 701 699 goto cleanup_matches; ··· 784 780 785 781 par.target = t->u.kernel.target; 786 782 par.targinfo = t->data; 783 + par.family = NFPROTO_IPV4; 787 784 if (par.target->destroy != NULL) 788 785 par.target->destroy(&par); 789 786 module_put(par.target->me); ··· 1664 1659 mtpar.table = name; 1665 1660 mtpar.entryinfo = &e->ip; 1666 1661 mtpar.hook_mask = e->comefrom; 1662 + mtpar.family = NFPROTO_IPV4; 1667 1663 ret = IPT_MATCH_ITERATE(e, check_match, &mtpar, &j); 1668 1664 if (ret) 1669 1665 goto cleanup_matches;
+8 -2
net/ipv6/netfilter/ip6_tables.c
··· 370 370 mtpar.hotdrop = &hotdrop; 371 371 mtpar.in = tgpar.in = in; 372 372 mtpar.out = tgpar.out = out; 373 + mtpar.family = tgpar.family = NFPROTO_IPV6; 373 374 tgpar.hooknum = hook; 374 375 375 376 read_lock_bh(&table->lock); ··· 605 604 606 605 par.match = m->u.kernel.match; 607 606 par.matchinfo = m->data; 607 + par.family = NFPROTO_IPV6; 608 608 if (par.match->destroy != NULL) 609 609 par.match->destroy(&par); 610 610 module_put(par.match->me); ··· 642 640 par->match = m->u.kernel.match; 643 641 par->matchinfo = m->data; 644 642 645 - ret = xt_check_match(par, NFPROTO_IPV6, m->u.match_size - sizeof(*m), 643 + ret = xt_check_match(par, m->u.match_size - sizeof(*m), 646 644 ipv6->proto, ipv6->invflags & IP6T_INV_PROTO); 647 645 if (ret < 0) { 648 646 duprintf("ip_tables: check failed for `%s'.\n", ··· 688 686 .target = t->u.kernel.target, 689 687 .targinfo = t->data, 690 688 .hook_mask = e->comefrom, 689 + .family = NFPROTO_IPV6, 691 690 }; 692 691 int ret; 693 692 694 693 t = ip6t_get_target(e); 695 - ret = xt_check_target(&par, NFPROTO_IPV6, t->u.target_size - sizeof(*t), 694 + ret = xt_check_target(&par, t->u.target_size - sizeof(*t), 696 695 e->ipv6.proto, e->ipv6.invflags & IP6T_INV_PROTO); 697 696 if (ret < 0) { 698 697 duprintf("ip_tables: check failed for `%s'.\n", ··· 721 718 mtpar.table = name; 722 719 mtpar.entryinfo = &e->ipv6; 723 720 mtpar.hook_mask = e->comefrom; 721 + mtpar.family = NFPROTO_IPV6; 724 722 ret = IP6T_MATCH_ITERATE(e, find_check_match, &mtpar, &j); 725 723 if (ret != 0) 726 724 goto cleanup_matches; ··· 809 805 810 806 par.target = t->u.kernel.target; 811 807 par.targinfo = t->data; 808 + par.family = NFPROTO_IPV6; 812 809 if (par.target->destroy != NULL) 813 810 par.target->destroy(&par); 814 811 module_put(par.target->me); ··· 1690 1685 mtpar.table = name; 1691 1686 mtpar.entryinfo = &e->ipv6; 1692 1687 mtpar.hook_mask = e->comefrom; 1688 + mtpar.family = NFPROTO_IPV6; 1693 1689 ret = IP6T_MATCH_ITERATE(e, check_match, &mtpar, &j); 1694 1690 if (ret) 1695 1691 goto cleanup_matches;
+12 -11
net/netfilter/x_tables.c
··· 321 321 } 322 322 EXPORT_SYMBOL_GPL(xt_find_revision); 323 323 324 - int xt_check_match(struct xt_mtchk_param *par, u_int8_t family, 324 + int xt_check_match(struct xt_mtchk_param *par, 325 325 unsigned int size, u_int8_t proto, bool inv_proto) 326 326 { 327 327 if (XT_ALIGN(par->match->matchsize) != size && ··· 331 331 * because it uses a dynamic-size data set. 332 332 */ 333 333 printk("%s_tables: %s match: invalid size %Zu != %u\n", 334 - xt_prefix[family], par->match->name, 334 + xt_prefix[par->family], par->match->name, 335 335 XT_ALIGN(par->match->matchsize), size); 336 336 return -EINVAL; 337 337 } 338 338 if (par->match->table != NULL && 339 339 strcmp(par->match->table, par->table) != 0) { 340 340 printk("%s_tables: %s match: only valid in %s table, not %s\n", 341 - xt_prefix[family], par->match->name, 341 + xt_prefix[par->family], par->match->name, 342 342 par->match->table, par->table); 343 343 return -EINVAL; 344 344 } 345 345 if (par->match->hooks && (par->hook_mask & ~par->match->hooks) != 0) { 346 346 printk("%s_tables: %s match: bad hook_mask %#x/%#x\n", 347 - xt_prefix[family], par->match->name, 347 + xt_prefix[par->family], par->match->name, 348 348 par->hook_mask, par->match->hooks); 349 349 return -EINVAL; 350 350 } 351 351 if (par->match->proto && (par->match->proto != proto || inv_proto)) { 352 352 printk("%s_tables: %s match: only valid for protocol %u\n", 353 - xt_prefix[family], par->match->name, par->match->proto); 353 + xt_prefix[par->family], par->match->name, 354 + par->match->proto); 354 355 return -EINVAL; 355 356 } 356 357 if (par->match->checkentry != NULL && !par->match->checkentry(par)) ··· 472 471 EXPORT_SYMBOL_GPL(xt_compat_match_to_user); 473 472 #endif /* CONFIG_COMPAT */ 474 473 475 - int xt_check_target(struct xt_tgchk_param *par, u_int8_t family, 474 + int xt_check_target(struct xt_tgchk_param *par, 476 475 unsigned int size, u_int8_t proto, bool inv_proto) 477 476 { 478 477 if (XT_ALIGN(par->target->targetsize) != size) { 479 478 printk("%s_tables: %s target: invalid size %Zu != %u\n", 480 - xt_prefix[family], par->target->name, 479 + xt_prefix[par->family], par->target->name, 481 480 XT_ALIGN(par->target->targetsize), size); 482 481 return -EINVAL; 483 482 } 484 483 if (par->target->table != NULL && 485 484 strcmp(par->target->table, par->table) != 0) { 486 485 printk("%s_tables: %s target: only valid in %s table, not %s\n", 487 - xt_prefix[family], par->target->name, 486 + xt_prefix[par->family], par->target->name, 488 487 par->target->table, par->table); 489 488 return -EINVAL; 490 489 } 491 490 if (par->target->hooks && (par->hook_mask & ~par->target->hooks) != 0) { 492 491 printk("%s_tables: %s target: bad hook_mask %#x/%#x\n", 493 - xt_prefix[family], par->target->name, par->hook_mask, 494 - par->target->hooks); 492 + xt_prefix[par->family], par->target->name, 493 + par->hook_mask, par->target->hooks); 495 494 return -EINVAL; 496 495 } 497 496 if (par->target->proto && (par->target->proto != proto || inv_proto)) { 498 497 printk("%s_tables: %s target: only valid for protocol %u\n", 499 - xt_prefix[family], par->target->name, 498 + xt_prefix[par->family], par->target->name, 500 499 par->target->proto); 501 500 return -EINVAL; 502 501 }
+2 -2
net/sched/act_ipt.c
··· 55 55 par.target = target; 56 56 par.targinfo = t->data; 57 57 par.hook_mask = hook; 58 + par.family = NFPROTO_IPV4; 58 59 59 - ret = xt_check_target(&par, NFPROTO_IPV4, 60 - t->u.target_size - sizeof(*t), 0, false); 60 + ret = xt_check_target(&par, t->u.target_size - sizeof(*t), 0, false); 61 61 if (ret < 0) { 62 62 module_put(t->u.kernel.target->me); 63 63 return ret;