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

Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf

Pablo Neira Ayuso says:

====================
Netfilter fixes for net

The following patchset contains Netfilter fixes for net:

1) Fix suspicious RCU usage in ipset, from Jozsef Kadlecsik.

2) Use kvcalloc, from Joe Perches.

3) Flush flowtable hardware workqueue after garbage collection run,
from Paul Blakey.

4) Missing flowtable hardware workqueue flush from nf_flow_table_free(),
also from Paul.

5) Restore NF_FLOW_HW_DEAD in flow_offload_work_del(), from Paul.

6) Flowtable documentation fixes, from Matteo Croce.
====================

Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+28 -26
+1 -1
Documentation/networking/nf_flowtable.txt
··· 76 76 77 77 table inet x { 78 78 flowtable f { 79 - hook ingress priority 0 devices = { eth0, eth1 }; 79 + hook ingress priority 0; devices = { eth0, eth1 }; 80 80 } 81 81 chain y { 82 82 type filter hook forward priority 0; policy accept;
+21 -20
net/netfilter/ipset/ip_set_core.c
··· 1483 1483 }; 1484 1484 1485 1485 static int 1486 - dump_init(struct netlink_callback *cb, struct ip_set_net *inst) 1486 + ip_set_dump_start(struct netlink_callback *cb) 1487 1487 { 1488 1488 struct nlmsghdr *nlh = nlmsg_hdr(cb->skb); 1489 1489 int min_len = nlmsg_total_size(sizeof(struct nfgenmsg)); 1490 1490 struct nlattr *cda[IPSET_ATTR_CMD_MAX + 1]; 1491 1491 struct nlattr *attr = (void *)nlh + min_len; 1492 + struct sk_buff *skb = cb->skb; 1493 + struct ip_set_net *inst = ip_set_pernet(sock_net(skb->sk)); 1492 1494 u32 dump_type; 1493 - ip_set_id_t index; 1494 1495 int ret; 1495 1496 1496 1497 ret = nla_parse(cda, IPSET_ATTR_CMD_MAX, attr, 1497 1498 nlh->nlmsg_len - min_len, 1498 1499 ip_set_dump_policy, NULL); 1499 1500 if (ret) 1500 - return ret; 1501 + goto error; 1501 1502 1502 1503 cb->args[IPSET_CB_PROTO] = nla_get_u8(cda[IPSET_ATTR_PROTOCOL]); 1503 1504 if (cda[IPSET_ATTR_SETNAME]) { 1505 + ip_set_id_t index; 1504 1506 struct ip_set *set; 1505 1507 1506 1508 set = find_set_and_id(inst, nla_data(cda[IPSET_ATTR_SETNAME]), 1507 1509 &index); 1508 - if (!set) 1509 - return -ENOENT; 1510 - 1510 + if (!set) { 1511 + ret = -ENOENT; 1512 + goto error; 1513 + } 1511 1514 dump_type = DUMP_ONE; 1512 1515 cb->args[IPSET_CB_INDEX] = index; 1513 1516 } else { ··· 1526 1523 cb->args[IPSET_CB_DUMP] = dump_type; 1527 1524 1528 1525 return 0; 1526 + 1527 + error: 1528 + /* We have to create and send the error message manually :-( */ 1529 + if (nlh->nlmsg_flags & NLM_F_ACK) { 1530 + netlink_ack(cb->skb, nlh, ret, NULL); 1531 + } 1532 + return ret; 1529 1533 } 1530 1534 1531 1535 static int 1532 - ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb) 1536 + ip_set_dump_do(struct sk_buff *skb, struct netlink_callback *cb) 1533 1537 { 1534 1538 ip_set_id_t index = IPSET_INVALID_ID, max; 1535 1539 struct ip_set *set = NULL; ··· 1547 1537 bool is_destroyed; 1548 1538 int ret = 0; 1549 1539 1550 - if (!cb->args[IPSET_CB_DUMP]) { 1551 - ret = dump_init(cb, inst); 1552 - if (ret < 0) { 1553 - nlh = nlmsg_hdr(cb->skb); 1554 - /* We have to create and send the error message 1555 - * manually :-( 1556 - */ 1557 - if (nlh->nlmsg_flags & NLM_F_ACK) 1558 - netlink_ack(cb->skb, nlh, ret, NULL); 1559 - return ret; 1560 - } 1561 - } 1540 + if (!cb->args[IPSET_CB_DUMP]) 1541 + return -EINVAL; 1562 1542 1563 1543 if (cb->args[IPSET_CB_INDEX] >= inst->ip_set_max) 1564 1544 goto out; ··· 1684 1684 1685 1685 { 1686 1686 struct netlink_dump_control c = { 1687 - .dump = ip_set_dump_start, 1687 + .start = ip_set_dump_start, 1688 + .dump = ip_set_dump_do, 1688 1689 .done = ip_set_dump_done, 1689 1690 }; 1690 1691 return netlink_dump_start(ctnl, skb, nlh, &c);
+1 -2
net/netfilter/nf_conntrack_core.c
··· 2248 2248 BUILD_BUG_ON(sizeof(struct hlist_nulls_head) != sizeof(struct hlist_head)); 2249 2249 nr_slots = *sizep = roundup(*sizep, PAGE_SIZE / sizeof(struct hlist_nulls_head)); 2250 2250 2251 - hash = kvmalloc_array(nr_slots, sizeof(struct hlist_nulls_head), 2252 - GFP_KERNEL | __GFP_ZERO); 2251 + hash = kvcalloc(nr_slots, sizeof(struct hlist_nulls_head), GFP_KERNEL); 2253 2252 2254 2253 if (hash && nulls) 2255 2254 for (i = 0; i < nr_slots; i++)
+2 -1
net/netfilter/nf_flow_table_core.c
··· 529 529 static void nf_flow_table_iterate_cleanup(struct nf_flowtable *flowtable, 530 530 struct net_device *dev) 531 531 { 532 - nf_flow_table_offload_flush(flowtable); 533 532 nf_flow_table_iterate(flowtable, nf_flow_table_do_cleanup, dev); 534 533 flush_delayed_work(&flowtable->gc_work); 534 + nf_flow_table_offload_flush(flowtable); 535 535 } 536 536 537 537 void nf_flow_table_cleanup(struct net_device *dev) ··· 553 553 cancel_delayed_work_sync(&flow_table->gc_work); 554 554 nf_flow_table_iterate(flow_table, nf_flow_table_do_cleanup, NULL); 555 555 nf_flow_table_iterate(flow_table, nf_flow_offload_gc_step, flow_table); 556 + nf_flow_table_offload_flush(flow_table); 556 557 rhashtable_destroy(&flow_table->rhashtable); 557 558 } 558 559 EXPORT_SYMBOL_GPL(nf_flow_table_free);
+1
net/netfilter/nf_flow_table_offload.c
··· 675 675 { 676 676 flow_offload_tuple_del(offload, FLOW_OFFLOAD_DIR_ORIGINAL); 677 677 flow_offload_tuple_del(offload, FLOW_OFFLOAD_DIR_REPLY); 678 + set_bit(NF_FLOW_HW_DEAD, &offload->flow->flags); 678 679 } 679 680 680 681 static void flow_offload_tuple_stats(struct flow_offload_work *offload,
+2 -2
net/netfilter/x_tables.c
··· 939 939 * 940 940 * @size: number of entries 941 941 * 942 - * Return: NULL or kmalloc'd or vmalloc'd array 942 + * Return: NULL or zeroed kmalloc'd or vmalloc'd array 943 943 */ 944 944 unsigned int *xt_alloc_entry_offsets(unsigned int size) 945 945 { 946 946 if (size > XT_MAX_TABLE_SIZE / sizeof(unsigned int)) 947 947 return NULL; 948 948 949 - return kvmalloc_array(size, sizeof(unsigned int), GFP_KERNEL | __GFP_ZERO); 949 + return kvcalloc(size, sizeof(unsigned int), GFP_KERNEL); 950 950 951 951 } 952 952 EXPORT_SYMBOL(xt_alloc_entry_offsets);