Commit c3b7d0bd authored by Sabrina Dubroca's avatar Sabrina Dubroca Committed by David S. Miller

macsec: fix rx_sa refcounting with decrypt callback

The decrypt callback macsec_decrypt_done needs a reference on the rx_sa
and releases it before returning, but macsec_handle_frame already
put that reference after macsec_decrypt returned NULL.

Set rx_sa to NULL when the decrypt callback runs so that
macsec_handle_frame knows it must not release the reference.

Fixes: c09440f7 ("macsec: introduce IEEE 802.1AE driver")
Signed-off-by: default avatarSabrina Dubroca <sd@queasysnail.net>
Acked-by: default avatarHannes Frederic Sowa <hannes@stressinduktion.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 497f358a
...@@ -880,12 +880,12 @@ static struct sk_buff *macsec_decrypt(struct sk_buff *skb, ...@@ -880,12 +880,12 @@ static struct sk_buff *macsec_decrypt(struct sk_buff *skb,
macsec_skb_cb(skb)->valid = false; macsec_skb_cb(skb)->valid = false;
skb = skb_share_check(skb, GFP_ATOMIC); skb = skb_share_check(skb, GFP_ATOMIC);
if (!skb) if (!skb)
return NULL; return ERR_PTR(-ENOMEM);
req = aead_request_alloc(rx_sa->key.tfm, GFP_ATOMIC); req = aead_request_alloc(rx_sa->key.tfm, GFP_ATOMIC);
if (!req) { if (!req) {
kfree_skb(skb); kfree_skb(skb);
return NULL; return ERR_PTR(-ENOMEM);
} }
hdr = (struct macsec_eth_header *)skb->data; hdr = (struct macsec_eth_header *)skb->data;
...@@ -905,7 +905,7 @@ static struct sk_buff *macsec_decrypt(struct sk_buff *skb, ...@@ -905,7 +905,7 @@ static struct sk_buff *macsec_decrypt(struct sk_buff *skb,
skb = skb_unshare(skb, GFP_ATOMIC); skb = skb_unshare(skb, GFP_ATOMIC);
if (!skb) { if (!skb) {
aead_request_free(req); aead_request_free(req);
return NULL; return ERR_PTR(-ENOMEM);
} }
} else { } else {
/* integrity only: all headers + data authenticated */ /* integrity only: all headers + data authenticated */
...@@ -921,14 +921,14 @@ static struct sk_buff *macsec_decrypt(struct sk_buff *skb, ...@@ -921,14 +921,14 @@ static struct sk_buff *macsec_decrypt(struct sk_buff *skb,
dev_hold(dev); dev_hold(dev);
ret = crypto_aead_decrypt(req); ret = crypto_aead_decrypt(req);
if (ret == -EINPROGRESS) { if (ret == -EINPROGRESS) {
return NULL; return ERR_PTR(ret);
} else if (ret != 0) { } else if (ret != 0) {
/* decryption/authentication failed /* decryption/authentication failed
* 10.6 if validateFrames is disabled, deliver anyway * 10.6 if validateFrames is disabled, deliver anyway
*/ */
if (ret != -EBADMSG) { if (ret != -EBADMSG) {
kfree_skb(skb); kfree_skb(skb);
skb = NULL; skb = ERR_PTR(ret);
} }
} else { } else {
macsec_skb_cb(skb)->valid = true; macsec_skb_cb(skb)->valid = true;
...@@ -1146,8 +1146,10 @@ static rx_handler_result_t macsec_handle_frame(struct sk_buff **pskb) ...@@ -1146,8 +1146,10 @@ static rx_handler_result_t macsec_handle_frame(struct sk_buff **pskb)
secy->validate_frames != MACSEC_VALIDATE_DISABLED) secy->validate_frames != MACSEC_VALIDATE_DISABLED)
skb = macsec_decrypt(skb, dev, rx_sa, sci, secy); skb = macsec_decrypt(skb, dev, rx_sa, sci, secy);
if (!skb) { if (IS_ERR(skb)) {
macsec_rxsa_put(rx_sa); /* the decrypt callback needs the reference */
if (PTR_ERR(skb) != -EINPROGRESS)
macsec_rxsa_put(rx_sa);
rcu_read_unlock(); rcu_read_unlock();
*pskb = NULL; *pskb = NULL;
return RX_HANDLER_CONSUMED; return RX_HANDLER_CONSUMED;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment