mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-11 23:50:25 +00:00
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: c09440f7dcb3 ("macsec: introduce IEEE 802.1AE driver") Signed-off-by: Sabrina Dubroca <sd@queasysnail.net> Acked-by: Hannes Frederic Sowa <hannes@stressinduktion.org> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
497f358aa4
commit
c3b7d0bd7a
@ -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,
|
|||||||
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,
|
|||||||
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)
|
|||||||
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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user