diff options
Diffstat (limited to 'net/sctp/socket.c')
-rw-r--r-- | net/sctp/socket.c | 19 |
1 files changed, 18 insertions, 1 deletions
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 65cc354c520f..aeecdd620c45 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -8166,8 +8166,25 @@ static void sctp_wfree(struct sk_buff *skb) sk->sk_wmem_queued -= skb->truesize; sk_mem_uncharge(sk, skb->truesize); - if (chunk->shkey) + if (chunk->shkey) { + struct sctp_shared_key *shkey = chunk->shkey; + + /* refcnt == 2 and !list_empty mean after this release, it's + * not being used anywhere, and it's time to notify userland + * that this shkey can be freed if it's been deactivated. + */ + if (shkey->deactivated && !list_empty(&shkey->key_list) && + refcount_read(&shkey->refcnt) == 2) { + struct sctp_ulpevent *ev; + + ev = sctp_ulpevent_make_authkey(asoc, shkey->key_id, + SCTP_AUTH_FREE_KEY, + GFP_KERNEL); + if (ev) + asoc->stream.si->enqueue_event(&asoc->ulpq, ev); + } sctp_auth_shkey_release(chunk->shkey); + } sock_wfree(skb); sctp_wake_up_waiters(sk, asoc); |