diff options
Diffstat (limited to 'net/netlink/af_netlink.c')
-rw-r--r-- | net/netlink/af_netlink.c | 20 |
1 files changed, 13 insertions, 7 deletions
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 6ef64adf7362..0a4db0211da0 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
@@ -1659,13 +1659,10 @@ static int netlink_dump(struct sock *sk) | |||
1659 | { | 1659 | { |
1660 | struct netlink_sock *nlk = nlk_sk(sk); | 1660 | struct netlink_sock *nlk = nlk_sk(sk); |
1661 | struct netlink_callback *cb; | 1661 | struct netlink_callback *cb; |
1662 | struct sk_buff *skb; | 1662 | struct sk_buff *skb = NULL; |
1663 | struct nlmsghdr *nlh; | 1663 | struct nlmsghdr *nlh; |
1664 | int len, err = -ENOBUFS; | 1664 | int len, err = -ENOBUFS; |
1665 | 1665 | int alloc_size; | |
1666 | skb = sock_rmalloc(sk, NLMSG_GOODSIZE, 0, GFP_KERNEL); | ||
1667 | if (!skb) | ||
1668 | goto errout; | ||
1669 | 1666 | ||
1670 | mutex_lock(nlk->cb_mutex); | 1667 | mutex_lock(nlk->cb_mutex); |
1671 | 1668 | ||
@@ -1675,6 +1672,12 @@ static int netlink_dump(struct sock *sk) | |||
1675 | goto errout_skb; | 1672 | goto errout_skb; |
1676 | } | 1673 | } |
1677 | 1674 | ||
1675 | alloc_size = max_t(int, cb->min_dump_alloc, NLMSG_GOODSIZE); | ||
1676 | |||
1677 | skb = sock_rmalloc(sk, alloc_size, 0, GFP_KERNEL); | ||
1678 | if (!skb) | ||
1679 | goto errout_skb; | ||
1680 | |||
1678 | len = cb->dump(skb, cb); | 1681 | len = cb->dump(skb, cb); |
1679 | 1682 | ||
1680 | if (len > 0) { | 1683 | if (len > 0) { |
@@ -1693,6 +1696,8 @@ static int netlink_dump(struct sock *sk) | |||
1693 | if (!nlh) | 1696 | if (!nlh) |
1694 | goto errout_skb; | 1697 | goto errout_skb; |
1695 | 1698 | ||
1699 | nl_dump_check_consistent(cb, nlh); | ||
1700 | |||
1696 | memcpy(nlmsg_data(nlh), &len, sizeof(len)); | 1701 | memcpy(nlmsg_data(nlh), &len, sizeof(len)); |
1697 | 1702 | ||
1698 | if (sk_filter(sk, skb)) | 1703 | if (sk_filter(sk, skb)) |
@@ -1713,7 +1718,6 @@ static int netlink_dump(struct sock *sk) | |||
1713 | errout_skb: | 1718 | errout_skb: |
1714 | mutex_unlock(nlk->cb_mutex); | 1719 | mutex_unlock(nlk->cb_mutex); |
1715 | kfree_skb(skb); | 1720 | kfree_skb(skb); |
1716 | errout: | ||
1717 | return err; | 1721 | return err; |
1718 | } | 1722 | } |
1719 | 1723 | ||
@@ -1721,7 +1725,8 @@ int netlink_dump_start(struct sock *ssk, struct sk_buff *skb, | |||
1721 | const struct nlmsghdr *nlh, | 1725 | const struct nlmsghdr *nlh, |
1722 | int (*dump)(struct sk_buff *skb, | 1726 | int (*dump)(struct sk_buff *skb, |
1723 | struct netlink_callback *), | 1727 | struct netlink_callback *), |
1724 | int (*done)(struct netlink_callback *)) | 1728 | int (*done)(struct netlink_callback *), |
1729 | u16 min_dump_alloc) | ||
1725 | { | 1730 | { |
1726 | struct netlink_callback *cb; | 1731 | struct netlink_callback *cb; |
1727 | struct sock *sk; | 1732 | struct sock *sk; |
@@ -1735,6 +1740,7 @@ int netlink_dump_start(struct sock *ssk, struct sk_buff *skb, | |||
1735 | cb->dump = dump; | 1740 | cb->dump = dump; |
1736 | cb->done = done; | 1741 | cb->done = done; |
1737 | cb->nlh = nlh; | 1742 | cb->nlh = nlh; |
1743 | cb->min_dump_alloc = min_dump_alloc; | ||
1738 | atomic_inc(&skb->users); | 1744 | atomic_inc(&skb->users); |
1739 | cb->skb = skb; | 1745 | cb->skb = skb; |
1740 | 1746 | ||