Skip to content

Commit ec2e506

Browse files
lxindavem330
authored andcommitted
sctp: add SCTP_AUTH_FREE_KEY type for AUTHENTICATION_EVENT
This patch is to add SCTP_AUTH_FREE_KEY type for AUTHENTICATION_EVENT, as described in section 6.1.8 of RFC6458. SCTP_AUTH_FREE_KEY: This report indicates that the SCTP implementation will no longer use the key identifier specified in auth_keynumber. After deactivating a key, it would never be used again, which means it's refcnt can't be held/increased by new chunks. But there may be some chunks in out queue still using it. So only when refcnt is 1, which means no chunk in outqueue is using/holding this key either, this EVENT would be sent. When users receive this notification, they could do DEL_KEY sockopt to remove this shkey, and also tell the peer that this key won't be used in any chunk thoroughly from now on, then the peer can remove it as well safely. Signed-off-by: Xin Long <lucien.xin@gmail.com> Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 601590e commit ec2e506

File tree

5 files changed

+57
-4
lines changed

5 files changed

+57
-4
lines changed

include/uapi/linux/sctp.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -518,7 +518,11 @@ struct sctp_authkey_event {
518518
sctp_assoc_t auth_assoc_id;
519519
};
520520

521-
enum { SCTP_AUTH_NEWKEY = 0, };
521+
enum {
522+
SCTP_AUTH_NEW_KEY,
523+
#define SCTP_AUTH_NEWKEY SCTP_AUTH_NEW_KEY /* compatible with before */
524+
SCTP_AUTH_FREE_KEY,
525+
};
522526

523527
/*
524528
* 6.1.9. SCTP_SENDER_DRY_EVENT

net/sctp/auth.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -992,6 +992,20 @@ int sctp_auth_deact_key_id(struct sctp_endpoint *ep,
992992
if (!found)
993993
return -EINVAL;
994994

995+
/* refcnt == 1 and !list_empty mean it's not being used anywhere
996+
* and deactivated will be set, so it's time to notify userland
997+
* that this shkey can be freed.
998+
*/
999+
if (asoc && !list_empty(&key->key_list) &&
1000+
refcount_read(&key->refcnt) == 1) {
1001+
struct sctp_ulpevent *ev;
1002+
1003+
ev = sctp_ulpevent_make_authkey(asoc, key->key_id,
1004+
SCTP_AUTH_FREE_KEY, GFP_KERNEL);
1005+
if (ev)
1006+
asoc->stream.si->enqueue_event(&asoc->ulpq, ev);
1007+
}
1008+
9951009
key->deactivated = 1;
9961010

9971011
return 0;

net/sctp/sm_make_chunk.c

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,26 @@ static void sctp_control_release_owner(struct sk_buff *skb)
8989
{
9090
struct sctp_chunk *chunk = skb_shinfo(skb)->destructor_arg;
9191

92-
if (chunk->shkey)
92+
if (chunk->shkey) {
93+
struct sctp_shared_key *shkey = chunk->shkey;
94+
struct sctp_association *asoc = chunk->asoc;
95+
96+
/* refcnt == 2 and !list_empty mean after this release, it's
97+
* not being used anywhere, and it's time to notify userland
98+
* that this shkey can be freed if it's been deactivated.
99+
*/
100+
if (shkey->deactivated && !list_empty(&shkey->key_list) &&
101+
refcount_read(&shkey->refcnt) == 2) {
102+
struct sctp_ulpevent *ev;
103+
104+
ev = sctp_ulpevent_make_authkey(asoc, shkey->key_id,
105+
SCTP_AUTH_FREE_KEY,
106+
GFP_KERNEL);
107+
if (ev)
108+
asoc->stream.si->enqueue_event(&asoc->ulpq, ev);
109+
}
93110
sctp_auth_shkey_release(chunk->shkey);
111+
}
94112
}
95113

96114
static void sctp_control_set_owner_w(struct sctp_chunk *chunk)

net/sctp/sm_statefuns.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4246,7 +4246,7 @@ enum sctp_disposition sctp_sf_eat_auth(struct net *net,
42464246
struct sctp_ulpevent *ev;
42474247

42484248
ev = sctp_ulpevent_make_authkey(asoc, ntohs(auth_hdr->shkey_id),
4249-
SCTP_AUTH_NEWKEY, GFP_ATOMIC);
4249+
SCTP_AUTH_NEW_KEY, GFP_ATOMIC);
42504250

42514251
if (!ev)
42524252
return -ENOMEM;

net/sctp/socket.c

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8166,8 +8166,25 @@ static void sctp_wfree(struct sk_buff *skb)
81668166
sk->sk_wmem_queued -= skb->truesize;
81678167
sk_mem_uncharge(sk, skb->truesize);
81688168

8169-
if (chunk->shkey)
8169+
if (chunk->shkey) {
8170+
struct sctp_shared_key *shkey = chunk->shkey;
8171+
8172+
/* refcnt == 2 and !list_empty mean after this release, it's
8173+
* not being used anywhere, and it's time to notify userland
8174+
* that this shkey can be freed if it's been deactivated.
8175+
*/
8176+
if (shkey->deactivated && !list_empty(&shkey->key_list) &&
8177+
refcount_read(&shkey->refcnt) == 2) {
8178+
struct sctp_ulpevent *ev;
8179+
8180+
ev = sctp_ulpevent_make_authkey(asoc, shkey->key_id,
8181+
SCTP_AUTH_FREE_KEY,
8182+
GFP_KERNEL);
8183+
if (ev)
8184+
asoc->stream.si->enqueue_event(&asoc->ulpq, ev);
8185+
}
81708186
sctp_auth_shkey_release(chunk->shkey);
8187+
}
81718188

81728189
sock_wfree(skb);
81738190
sctp_wake_up_waiters(sk, asoc);

0 commit comments

Comments
 (0)