|
@@ -2136,7 +2136,7 @@ static int netlink_dump(struct sock *sk)
|
|
|
struct sk_buff *skb = NULL;
|
|
|
struct nlmsghdr *nlh;
|
|
|
struct module *module;
|
|
|
- int len, err = -ENOBUFS;
|
|
|
+ int err = -ENOBUFS;
|
|
|
int alloc_min_size;
|
|
|
int alloc_size;
|
|
|
|
|
@@ -2183,9 +2183,11 @@ static int netlink_dump(struct sock *sk)
|
|
|
skb_reserve(skb, skb_tailroom(skb) - alloc_size);
|
|
|
netlink_skb_set_owner_r(skb, sk);
|
|
|
|
|
|
- len = cb->dump(skb, cb);
|
|
|
+ if (nlk->dump_done_errno > 0)
|
|
|
+ nlk->dump_done_errno = cb->dump(skb, cb);
|
|
|
|
|
|
- if (len > 0) {
|
|
|
+ if (nlk->dump_done_errno > 0 ||
|
|
|
+ skb_tailroom(skb) < nlmsg_total_size(sizeof(nlk->dump_done_errno))) {
|
|
|
mutex_unlock(nlk->cb_mutex);
|
|
|
|
|
|
if (sk_filter(sk, skb))
|
|
@@ -2195,13 +2197,15 @@ static int netlink_dump(struct sock *sk)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
- nlh = nlmsg_put_answer(skb, cb, NLMSG_DONE, sizeof(len), NLM_F_MULTI);
|
|
|
- if (!nlh)
|
|
|
+ nlh = nlmsg_put_answer(skb, cb, NLMSG_DONE,
|
|
|
+ sizeof(nlk->dump_done_errno), NLM_F_MULTI);
|
|
|
+ if (WARN_ON(!nlh))
|
|
|
goto errout_skb;
|
|
|
|
|
|
nl_dump_check_consistent(cb, nlh);
|
|
|
|
|
|
- memcpy(nlmsg_data(nlh), &len, sizeof(len));
|
|
|
+ memcpy(nlmsg_data(nlh), &nlk->dump_done_errno,
|
|
|
+ sizeof(nlk->dump_done_errno));
|
|
|
|
|
|
if (sk_filter(sk, skb))
|
|
|
kfree_skb(skb);
|
|
@@ -2273,6 +2277,7 @@ int __netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
|
|
|
}
|
|
|
|
|
|
nlk->cb_running = true;
|
|
|
+ nlk->dump_done_errno = INT_MAX;
|
|
|
|
|
|
mutex_unlock(nlk->cb_mutex);
|
|
|
|