Skip to content

Commit ed5d778

Browse files
herbertxdavem330
authored andcommitted
netlink: Do not schedule work from sk_destruct
It is wrong to schedule a work from sk_destruct using the socket as the memory reserve because the socket will be freed immediately after the return from sk_destruct. Instead we should do the deferral prior to sk_free. This patch does just that. Fixes: 707693c ("netlink: Call cb->done from a worker thread") Signed-off-by: Herbert Xu <[email protected]> Tested-by: Andrey Konovalov <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent ffe3bb8 commit ed5d778

File tree

1 file changed

+15
-17
lines changed

1 file changed

+15
-17
lines changed

net/netlink/af_netlink.c

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -322,11 +322,13 @@ static void netlink_skb_set_owner_r(struct sk_buff *skb, struct sock *sk)
322322
sk_mem_charge(sk, skb->truesize);
323323
}
324324

325-
static void __netlink_sock_destruct(struct sock *sk)
325+
static void netlink_sock_destruct(struct sock *sk)
326326
{
327327
struct netlink_sock *nlk = nlk_sk(sk);
328328

329329
if (nlk->cb_running) {
330+
if (nlk->cb.done)
331+
nlk->cb.done(&nlk->cb);
330332
module_put(nlk->cb.module);
331333
kfree_skb(nlk->cb.skb);
332334
}
@@ -348,21 +350,7 @@ static void netlink_sock_destruct_work(struct work_struct *work)
348350
struct netlink_sock *nlk = container_of(work, struct netlink_sock,
349351
work);
350352

351-
nlk->cb.done(&nlk->cb);
352-
__netlink_sock_destruct(&nlk->sk);
353-
}
354-
355-
static void netlink_sock_destruct(struct sock *sk)
356-
{
357-
struct netlink_sock *nlk = nlk_sk(sk);
358-
359-
if (nlk->cb_running && nlk->cb.done) {
360-
INIT_WORK(&nlk->work, netlink_sock_destruct_work);
361-
schedule_work(&nlk->work);
362-
return;
363-
}
364-
365-
__netlink_sock_destruct(sk);
353+
sk_free(&nlk->sk);
366354
}
367355

368356
/* This lock without WQ_FLAG_EXCLUSIVE is good on UP and it is _very_ bad on
@@ -667,8 +655,18 @@ static int netlink_create(struct net *net, struct socket *sock, int protocol,
667655
static void deferred_put_nlk_sk(struct rcu_head *head)
668656
{
669657
struct netlink_sock *nlk = container_of(head, struct netlink_sock, rcu);
658+
struct sock *sk = &nlk->sk;
659+
660+
if (!atomic_dec_and_test(&sk->sk_refcnt))
661+
return;
662+
663+
if (nlk->cb_running && nlk->cb.done) {
664+
INIT_WORK(&nlk->work, netlink_sock_destruct_work);
665+
schedule_work(&nlk->work);
666+
return;
667+
}
670668

671-
sock_put(&nlk->sk);
669+
sk_free(sk);
672670
}
673671

674672
static int netlink_release(struct socket *sock)

0 commit comments

Comments
 (0)