|
@@ -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);
|