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]: ip_tables: ipt and ipt_compat checks unification

Matches and targets verification is duplicated in normal and compat processing
ways. This patch refactors code in order to remove this.

Signed-off-by: Dmitry Mishin <dim@openvz.org>
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Dmitry Mishin and committed by
David S. Miller
a96be246 11078c37

+79 -97
+79 -97
net/ipv4/netfilter/ip_tables.c
··· 484 484 } 485 485 486 486 static inline int 487 - check_match(struct ipt_entry_match *m, 487 + check_entry(struct ipt_entry *e, const char *name) 488 + { 489 + struct ipt_entry_target *t; 490 + 491 + if (!ip_checkentry(&e->ip)) { 492 + duprintf("ip_tables: ip check failed %p %s.\n", e, name); 493 + return -EINVAL; 494 + } 495 + 496 + if (e->target_offset + sizeof(struct ipt_entry_target) > e->next_offset) 497 + return -EINVAL; 498 + 499 + t = ipt_get_target(e); 500 + if (e->target_offset + t->u.target_size > e->next_offset) 501 + return -EINVAL; 502 + 503 + return 0; 504 + } 505 + 506 + static inline int check_match(struct ipt_entry_match *m, const char *name, 507 + const struct ipt_ip *ip, unsigned int hookmask) 508 + { 509 + struct ipt_match *match; 510 + int ret; 511 + 512 + match = m->u.kernel.match; 513 + ret = xt_check_match(match, AF_INET, m->u.match_size - sizeof(*m), 514 + name, hookmask, ip->proto, 515 + ip->invflags & IPT_INV_PROTO); 516 + if (!ret && m->u.kernel.match->checkentry 517 + && !m->u.kernel.match->checkentry(name, ip, match, m->data, 518 + hookmask)) { 519 + duprintf("ip_tables: check failed for `%s'.\n", 520 + m->u.kernel.match->name); 521 + ret = -EINVAL; 522 + } 523 + return ret; 524 + } 525 + 526 + static inline int 527 + find_check_match(struct ipt_entry_match *m, 488 528 const char *name, 489 529 const struct ipt_ip *ip, 490 530 unsigned int hookmask, ··· 537 497 m->u.user.revision), 538 498 "ipt_%s", m->u.user.name); 539 499 if (IS_ERR(match) || !match) { 540 - duprintf("check_match: `%s' not found\n", m->u.user.name); 500 + duprintf("find_check_match: `%s' not found\n", m->u.user.name); 541 501 return match ? PTR_ERR(match) : -ENOENT; 542 502 } 543 503 m->u.kernel.match = match; 544 504 545 - ret = xt_check_match(match, AF_INET, m->u.match_size - sizeof(*m), 546 - name, hookmask, ip->proto, 547 - ip->invflags & IPT_INV_PROTO); 505 + ret = check_match(m, name, ip, hookmask); 548 506 if (ret) 549 507 goto err; 550 - 551 - if (m->u.kernel.match->checkentry 552 - && !m->u.kernel.match->checkentry(name, ip, match, m->data, 553 - hookmask)) { 554 - duprintf("ip_tables: check failed for `%s'.\n", 555 - m->u.kernel.match->name); 556 - ret = -EINVAL; 557 - goto err; 558 - } 559 508 560 509 (*i)++; 561 510 return 0; ··· 553 524 return ret; 554 525 } 555 526 556 - static struct ipt_target ipt_standard_target; 527 + static inline int check_target(struct ipt_entry *e, const char *name) 528 + { 529 + struct ipt_entry_target *t; 530 + struct ipt_target *target; 531 + int ret; 532 + 533 + t = ipt_get_target(e); 534 + target = t->u.kernel.target; 535 + ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t), 536 + name, e->comefrom, e->ip.proto, 537 + e->ip.invflags & IPT_INV_PROTO); 538 + if (!ret && t->u.kernel.target->checkentry 539 + && !t->u.kernel.target->checkentry(name, e, target, 540 + t->data, e->comefrom)) { 541 + duprintf("ip_tables: check failed for `%s'.\n", 542 + t->u.kernel.target->name); 543 + ret = -EINVAL; 544 + } 545 + return ret; 546 + } 557 547 558 548 static inline int 559 - check_entry(struct ipt_entry *e, const char *name, unsigned int size, 549 + find_check_entry(struct ipt_entry *e, const char *name, unsigned int size, 560 550 unsigned int *i) 561 551 { 562 552 struct ipt_entry_target *t; ··· 583 535 int ret; 584 536 unsigned int j; 585 537 586 - if (!ip_checkentry(&e->ip)) { 587 - duprintf("ip_tables: ip check failed %p %s.\n", e, name); 588 - return -EINVAL; 589 - } 590 - 591 - if (e->target_offset + sizeof(struct ipt_entry_target) > e->next_offset) 592 - return -EINVAL; 538 + ret = check_entry(e, name); 539 + if (ret) 540 + return ret; 593 541 594 542 j = 0; 595 - ret = IPT_MATCH_ITERATE(e, check_match, name, &e->ip, e->comefrom, &j); 543 + ret = IPT_MATCH_ITERATE(e, find_check_match, name, &e->ip, 544 + e->comefrom, &j); 596 545 if (ret != 0) 597 546 goto cleanup_matches; 598 547 599 548 t = ipt_get_target(e); 600 - ret = -EINVAL; 601 - if (e->target_offset + t->u.target_size > e->next_offset) 602 - goto cleanup_matches; 603 549 target = try_then_request_module(xt_find_target(AF_INET, 604 550 t->u.user.name, 605 551 t->u.user.revision), 606 552 "ipt_%s", t->u.user.name); 607 553 if (IS_ERR(target) || !target) { 608 - duprintf("check_entry: `%s' not found\n", t->u.user.name); 554 + duprintf("find_check_entry: `%s' not found\n", t->u.user.name); 609 555 ret = target ? PTR_ERR(target) : -ENOENT; 610 556 goto cleanup_matches; 611 557 } 612 558 t->u.kernel.target = target; 613 559 614 - ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t), 615 - name, e->comefrom, e->ip.proto, 616 - e->ip.invflags & IPT_INV_PROTO); 560 + ret = check_target(e, name); 617 561 if (ret) 618 562 goto err; 619 - 620 - if (t->u.kernel.target->checkentry 621 - && !t->u.kernel.target->checkentry(name, e, target, t->data, 622 - e->comefrom)) { 623 - duprintf("ip_tables: check failed for `%s'.\n", 624 - t->u.kernel.target->name); 625 - ret = -EINVAL; 626 - goto err; 627 - } 628 563 629 564 (*i)++; 630 565 return 0; ··· 743 712 /* Finally, each sanity check must pass */ 744 713 i = 0; 745 714 ret = IPT_ENTRY_ITERATE(entry0, newinfo->size, 746 - check_entry, name, size, &i); 715 + find_check_entry, name, size, &i); 747 716 748 717 if (ret != 0) { 749 718 IPT_ENTRY_ITERATE(entry0, newinfo->size, ··· 1483 1452 return -EINVAL; 1484 1453 } 1485 1454 1486 - if (!ip_checkentry(&e->ip)) { 1487 - duprintf("ip_tables: ip check failed %p %s.\n", e, name); 1488 - return -EINVAL; 1489 - } 1490 - 1491 - if (e->target_offset + sizeof(struct compat_xt_entry_target) > 1492 - e->next_offset) 1493 - return -EINVAL; 1455 + ret = check_entry(e, name); 1456 + if (ret) 1457 + return ret; 1494 1458 1495 1459 off = 0; 1496 1460 entry_offset = (void *)e - (void *)base; ··· 1496 1470 goto cleanup_matches; 1497 1471 1498 1472 t = ipt_get_target(e); 1499 - ret = -EINVAL; 1500 - if (e->target_offset + t->u.target_size > e->next_offset) 1501 - goto cleanup_matches; 1502 1473 target = try_then_request_module(xt_find_target(AF_INET, 1503 1474 t->u.user.name, 1504 1475 t->u.user.revision), 1505 1476 "ipt_%s", t->u.user.name); 1506 1477 if (IS_ERR(target) || !target) { 1507 - duprintf("check_entry: `%s' not found\n", t->u.user.name); 1478 + duprintf("check_compat_entry_size_and_hooks: `%s' not found\n", 1479 + t->u.user.name); 1508 1480 ret = target ? PTR_ERR(target) : -ENOENT; 1509 1481 goto cleanup_matches; 1510 1482 } ··· 1579 1555 return ret; 1580 1556 } 1581 1557 1582 - static inline int compat_check_match(struct ipt_entry_match *m, const char *name, 1583 - const struct ipt_ip *ip, unsigned int hookmask) 1584 - { 1585 - struct ipt_match *match; 1586 - int ret; 1587 - 1588 - match = m->u.kernel.match; 1589 - ret = xt_check_match(match, AF_INET, m->u.match_size - sizeof(*m), 1590 - name, hookmask, ip->proto, 1591 - ip->invflags & IPT_INV_PROTO); 1592 - if (!ret && m->u.kernel.match->checkentry 1593 - && !m->u.kernel.match->checkentry(name, ip, match, m->data, 1594 - hookmask)) { 1595 - duprintf("ip_tables: compat: check failed for `%s'.\n", 1596 - m->u.kernel.match->name); 1597 - ret = -EINVAL; 1598 - } 1599 - return ret; 1600 - } 1601 - 1602 - static inline int compat_check_target(struct ipt_entry *e, const char *name) 1603 - { 1604 - struct ipt_entry_target *t; 1605 - struct ipt_target *target; 1606 - int ret; 1607 - 1608 - t = ipt_get_target(e); 1609 - target = t->u.kernel.target; 1610 - ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t), 1611 - name, e->comefrom, e->ip.proto, 1612 - e->ip.invflags & IPT_INV_PROTO); 1613 - if (!ret && t->u.kernel.target->checkentry 1614 - && !t->u.kernel.target->checkentry(name, e, target, 1615 - t->data, e->comefrom)) { 1616 - duprintf("ip_tables: compat: check failed for `%s'.\n", 1617 - t->u.kernel.target->name); 1618 - ret = -EINVAL; 1619 - } 1620 - return ret; 1621 - } 1622 - 1623 1558 static inline int compat_check_entry(struct ipt_entry *e, const char *name) 1624 1559 { 1625 1560 int ret; 1626 1561 1627 - ret = IPT_MATCH_ITERATE(e, compat_check_match, name, &e->ip, 1628 - e->comefrom); 1562 + ret = IPT_MATCH_ITERATE(e, check_match, name, &e->ip, e->comefrom); 1629 1563 if (ret) 1630 1564 return ret; 1631 1565 1632 - return compat_check_target(e, name); 1566 + return check_target(e, name); 1633 1567 } 1634 1568 1635 1569 static int