Commit 73cd598df46a73d6f02063f2520df115a9b88aa5
Committed by
David S. Miller
1 parent
30c08c41be
Exists in
master
and in
7 other branches
[NETFILTER]: ip_tables: fix compat types
Use compat types and compat iterators when dealing with compat entries for clarity. This doesn't actually make a difference for ip_tables, but is needed for ip6_tables and arp_tables. Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
Showing 2 changed files with 47 additions and 29 deletions Side-by-side Diff
include/linux/netfilter_ipv4/ip_tables.h
... | ... | @@ -236,11 +236,6 @@ |
236 | 236 | #define IPT_ENTRY_ITERATE(entries, size, fn, args...) \ |
237 | 237 | XT_ENTRY_ITERATE(struct ipt_entry, entries, size, fn, ## args) |
238 | 238 | |
239 | -/* fn returns 0 to continue iteration */ | |
240 | -#define IPT_ENTRY_ITERATE_CONTINUE(entries, size, n, fn, args...) \ | |
241 | - XT_ENTRY_ITERATE_CONTINUE(struct ipt_entry, entries, size, n, fn, \ | |
242 | - ## args) | |
243 | - | |
244 | 239 | /* |
245 | 240 | * Main firewall chains definitions and global var's definitions. |
246 | 241 | */ |
247 | 242 | |
... | ... | @@ -316,7 +311,27 @@ |
316 | 311 | unsigned char elems[0]; |
317 | 312 | }; |
318 | 313 | |
314 | +/* Helper functions */ | |
315 | +static inline struct ipt_entry_target * | |
316 | +compat_ipt_get_target(struct compat_ipt_entry *e) | |
317 | +{ | |
318 | + return (void *)e + e->target_offset; | |
319 | +} | |
320 | + | |
319 | 321 | #define COMPAT_IPT_ALIGN(s) COMPAT_XT_ALIGN(s) |
322 | + | |
323 | +/* fn returns 0 to continue iteration */ | |
324 | +#define COMPAT_IPT_MATCH_ITERATE(e, fn, args...) \ | |
325 | + XT_MATCH_ITERATE(struct compat_ipt_entry, e, fn, ## args) | |
326 | + | |
327 | +/* fn returns 0 to continue iteration */ | |
328 | +#define COMPAT_IPT_ENTRY_ITERATE(entries, size, fn, args...) \ | |
329 | + XT_ENTRY_ITERATE(struct compat_ipt_entry, entries, size, fn, ## args) | |
330 | + | |
331 | +/* fn returns 0 to continue iteration */ | |
332 | +#define COMPAT_IPT_ENTRY_ITERATE_CONTINUE(entries, size, n, fn, args...) \ | |
333 | + XT_ENTRY_ITERATE_CONTINUE(struct compat_ipt_entry, entries, size, n, \ | |
334 | + fn, ## args) | |
320 | 335 | |
321 | 336 | #endif /* CONFIG_COMPAT */ |
322 | 337 | #endif /*__KERNEL__*/ |
net/ipv4/netfilter/ip_tables.c
... | ... | @@ -1559,7 +1559,7 @@ |
1559 | 1559 | } |
1560 | 1560 | |
1561 | 1561 | static inline int |
1562 | -compat_release_entry(struct ipt_entry *e, unsigned int *i) | |
1562 | +compat_release_entry(struct compat_ipt_entry *e, unsigned int *i) | |
1563 | 1563 | { |
1564 | 1564 | struct ipt_entry_target *t; |
1565 | 1565 | |
1566 | 1566 | |
... | ... | @@ -1567,14 +1567,14 @@ |
1567 | 1567 | return 1; |
1568 | 1568 | |
1569 | 1569 | /* Cleanup all matches */ |
1570 | - IPT_MATCH_ITERATE(e, compat_release_match, NULL); | |
1571 | - t = ipt_get_target(e); | |
1570 | + COMPAT_IPT_MATCH_ITERATE(e, compat_release_match, NULL); | |
1571 | + t = compat_ipt_get_target(e); | |
1572 | 1572 | module_put(t->u.kernel.target->me); |
1573 | 1573 | return 0; |
1574 | 1574 | } |
1575 | 1575 | |
1576 | 1576 | static inline int |
1577 | -check_compat_entry_size_and_hooks(struct ipt_entry *e, | |
1577 | +check_compat_entry_size_and_hooks(struct compat_ipt_entry *e, | |
1578 | 1578 | struct xt_table_info *newinfo, |
1579 | 1579 | unsigned int *size, |
1580 | 1580 | unsigned char *base, |
1581 | 1581 | |
1582 | 1582 | |
... | ... | @@ -1603,19 +1603,20 @@ |
1603 | 1603 | return -EINVAL; |
1604 | 1604 | } |
1605 | 1605 | |
1606 | - ret = check_entry(e, name); | |
1606 | + /* For purposes of check_entry casting the compat entry is fine */ | |
1607 | + ret = check_entry((struct ipt_entry *)e, name); | |
1607 | 1608 | if (ret) |
1608 | 1609 | return ret; |
1609 | 1610 | |
1610 | 1611 | off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry); |
1611 | 1612 | entry_offset = (void *)e - (void *)base; |
1612 | 1613 | j = 0; |
1613 | - ret = IPT_MATCH_ITERATE(e, compat_find_calc_match, name, &e->ip, | |
1614 | - e->comefrom, &off, &j); | |
1614 | + ret = COMPAT_IPT_MATCH_ITERATE(e, compat_find_calc_match, name, | |
1615 | + &e->ip, e->comefrom, &off, &j); | |
1615 | 1616 | if (ret != 0) |
1616 | 1617 | goto release_matches; |
1617 | 1618 | |
1618 | - t = ipt_get_target(e); | |
1619 | + t = compat_ipt_get_target(e); | |
1619 | 1620 | target = try_then_request_module(xt_find_target(AF_INET, |
1620 | 1621 | t->u.user.name, |
1621 | 1622 | t->u.user.revision), |
... | ... | @@ -1643,7 +1644,7 @@ |
1643 | 1644 | } |
1644 | 1645 | |
1645 | 1646 | /* Clear counters and comefrom */ |
1646 | - e->counters = ((struct ipt_counters) { 0, 0 }); | |
1647 | + memset(&e->counters, 0, sizeof(e->counters)); | |
1647 | 1648 | e->comefrom = 0; |
1648 | 1649 | |
1649 | 1650 | (*i)++; |
... | ... | @@ -1657,7 +1658,7 @@ |
1657 | 1658 | } |
1658 | 1659 | |
1659 | 1660 | static int |
1660 | -compat_copy_entry_from_user(struct ipt_entry *e, void **dstptr, | |
1661 | +compat_copy_entry_from_user(struct compat_ipt_entry *e, void **dstptr, | |
1661 | 1662 | unsigned int *size, const char *name, |
1662 | 1663 | struct xt_table_info *newinfo, unsigned char *base) |
1663 | 1664 | { |
1664 | 1665 | |
1665 | 1666 | |
1666 | 1667 | |
... | ... | @@ -1671,15 +1672,17 @@ |
1671 | 1672 | origsize = *size; |
1672 | 1673 | de = (struct ipt_entry *)*dstptr; |
1673 | 1674 | memcpy(de, e, sizeof(struct ipt_entry)); |
1675 | + memcpy(&de->counters, &e->counters, sizeof(e->counters)); | |
1674 | 1676 | |
1675 | - *dstptr += sizeof(struct compat_ipt_entry); | |
1677 | + *dstptr += sizeof(struct ipt_entry); | |
1676 | 1678 | *size += sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry); |
1677 | 1679 | |
1678 | - ret = IPT_MATCH_ITERATE(e, xt_compat_match_from_user, dstptr, size); | |
1680 | + ret = COMPAT_IPT_MATCH_ITERATE(e, xt_compat_match_from_user, | |
1681 | + dstptr, size); | |
1679 | 1682 | if (ret) |
1680 | 1683 | return ret; |
1681 | 1684 | de->target_offset = e->target_offset - (origsize - *size); |
1682 | - t = ipt_get_target(e); | |
1685 | + t = compat_ipt_get_target(e); | |
1683 | 1686 | target = t->u.kernel.target; |
1684 | 1687 | xt_compat_target_from_user(t, dstptr, size); |
1685 | 1688 | |
... | ... | @@ -1746,11 +1749,11 @@ |
1746 | 1749 | j = 0; |
1747 | 1750 | xt_compat_lock(AF_INET); |
1748 | 1751 | /* Walk through entries, checking offsets. */ |
1749 | - ret = IPT_ENTRY_ITERATE(entry0, total_size, | |
1750 | - check_compat_entry_size_and_hooks, | |
1751 | - info, &size, entry0, | |
1752 | - entry0 + total_size, | |
1753 | - hook_entries, underflows, &j, name); | |
1752 | + ret = COMPAT_IPT_ENTRY_ITERATE(entry0, total_size, | |
1753 | + check_compat_entry_size_and_hooks, | |
1754 | + info, &size, entry0, | |
1755 | + entry0 + total_size, | |
1756 | + hook_entries, underflows, &j, name); | |
1754 | 1757 | if (ret != 0) |
1755 | 1758 | goto out_unlock; |
1756 | 1759 | |
... | ... | @@ -1791,9 +1794,9 @@ |
1791 | 1794 | entry1 = newinfo->entries[raw_smp_processor_id()]; |
1792 | 1795 | pos = entry1; |
1793 | 1796 | size = total_size; |
1794 | - ret = IPT_ENTRY_ITERATE(entry0, total_size, | |
1795 | - compat_copy_entry_from_user, &pos, &size, | |
1796 | - name, newinfo, entry1); | |
1797 | + ret = COMPAT_IPT_ENTRY_ITERATE(entry0, total_size, | |
1798 | + compat_copy_entry_from_user, &pos, &size, | |
1799 | + name, newinfo, entry1); | |
1797 | 1800 | compat_flush_offsets(); |
1798 | 1801 | xt_compat_unlock(AF_INET); |
1799 | 1802 | if (ret) |
... | ... | @@ -1808,8 +1811,8 @@ |
1808 | 1811 | name, &i); |
1809 | 1812 | if (ret) { |
1810 | 1813 | j -= i; |
1811 | - IPT_ENTRY_ITERATE_CONTINUE(entry1, newinfo->size, i, | |
1812 | - compat_release_entry, &j); | |
1814 | + COMPAT_IPT_ENTRY_ITERATE_CONTINUE(entry0, newinfo->size, i, | |
1815 | + compat_release_entry, &j); | |
1813 | 1816 | IPT_ENTRY_ITERATE(entry1, newinfo->size, cleanup_entry, &i); |
1814 | 1817 | xt_free_table_info(newinfo); |
1815 | 1818 | return ret; |
... | ... | @@ -1828,7 +1831,7 @@ |
1828 | 1831 | free_newinfo: |
1829 | 1832 | xt_free_table_info(newinfo); |
1830 | 1833 | out: |
1831 | - IPT_ENTRY_ITERATE(entry0, total_size, compat_release_entry, &j); | |
1834 | + COMPAT_IPT_ENTRY_ITERATE(entry0, total_size, compat_release_entry, &j); | |
1832 | 1835 | return ret; |
1833 | 1836 | out_unlock: |
1834 | 1837 | compat_flush_offsets(); |