diff options
author | Sabrina Dubroca <sd@queasysnail.net> | 2016-04-22 05:28:04 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-04-24 14:31:58 -0400 |
commit | c3b7d0bd7ac2c501d4806db71ddd383c184968e8 (patch) | |
tree | 8bc0ce1c27261b9857058fe24514c783b8879855 | |
parent | 497f358aa4c0d99b75ec204407389920d5e33ec5 (diff) |
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>
-rw-r--r-- | drivers/net/macsec.c | 16 |
1 files changed, 9 insertions, 7 deletions
diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c index 2a2136b7d324..1fd2b147fda1 100644 --- a/drivers/net/macsec.c +++ b/drivers/net/macsec.c | |||
@@ -880,12 +880,12 @@ static struct sk_buff *macsec_decrypt(struct sk_buff *skb, | |||
880 | macsec_skb_cb(skb)->valid = false; | 880 | macsec_skb_cb(skb)->valid = false; |
881 | skb = skb_share_check(skb, GFP_ATOMIC); | 881 | skb = skb_share_check(skb, GFP_ATOMIC); |
882 | if (!skb) | 882 | if (!skb) |
883 | return NULL; | 883 | return ERR_PTR(-ENOMEM); |
884 | 884 | ||
885 | req = aead_request_alloc(rx_sa->key.tfm, GFP_ATOMIC); | 885 | req = aead_request_alloc(rx_sa->key.tfm, GFP_ATOMIC); |
886 | if (!req) { | 886 | if (!req) { |
887 | kfree_skb(skb); | 887 | kfree_skb(skb); |
888 | return NULL; | 888 | return ERR_PTR(-ENOMEM); |
889 | } | 889 | } |
890 | 890 | ||
891 | hdr = (struct macsec_eth_header *)skb->data; | 891 | hdr = (struct macsec_eth_header *)skb->data; |
@@ -905,7 +905,7 @@ static struct sk_buff *macsec_decrypt(struct sk_buff *skb, | |||
905 | skb = skb_unshare(skb, GFP_ATOMIC); | 905 | skb = skb_unshare(skb, GFP_ATOMIC); |
906 | if (!skb) { | 906 | if (!skb) { |
907 | aead_request_free(req); | 907 | aead_request_free(req); |
908 | return NULL; | 908 | return ERR_PTR(-ENOMEM); |
909 | } | 909 | } |
910 | } else { | 910 | } else { |
911 | /* integrity only: all headers + data authenticated */ | 911 | /* integrity only: all headers + data authenticated */ |
@@ -921,14 +921,14 @@ static struct sk_buff *macsec_decrypt(struct sk_buff *skb, | |||
921 | dev_hold(dev); | 921 | dev_hold(dev); |
922 | ret = crypto_aead_decrypt(req); | 922 | ret = crypto_aead_decrypt(req); |
923 | if (ret == -EINPROGRESS) { | 923 | if (ret == -EINPROGRESS) { |
924 | return NULL; | 924 | return ERR_PTR(ret); |
925 | } else if (ret != 0) { | 925 | } else if (ret != 0) { |
926 | /* decryption/authentication failed | 926 | /* decryption/authentication failed |
927 | * 10.6 if validateFrames is disabled, deliver anyway | 927 | * 10.6 if validateFrames is disabled, deliver anyway |
928 | */ | 928 | */ |
929 | if (ret != -EBADMSG) { | 929 | if (ret != -EBADMSG) { |
930 | kfree_skb(skb); | 930 | kfree_skb(skb); |
931 | skb = NULL; | 931 | skb = ERR_PTR(ret); |
932 | } | 932 | } |
933 | } else { | 933 | } else { |
934 | macsec_skb_cb(skb)->valid = true; | 934 | macsec_skb_cb(skb)->valid = true; |
@@ -1146,8 +1146,10 @@ static rx_handler_result_t macsec_handle_frame(struct sk_buff **pskb) | |||
1146 | secy->validate_frames != MACSEC_VALIDATE_DISABLED) | 1146 | secy->validate_frames != MACSEC_VALIDATE_DISABLED) |
1147 | skb = macsec_decrypt(skb, dev, rx_sa, sci, secy); | 1147 | skb = macsec_decrypt(skb, dev, rx_sa, sci, secy); |
1148 | 1148 | ||
1149 | if (!skb) { | 1149 | if (IS_ERR(skb)) { |
1150 | macsec_rxsa_put(rx_sa); | 1150 | /* the decrypt callback needs the reference */ |
1151 | if (PTR_ERR(skb) != -EINPROGRESS) | ||
1152 | macsec_rxsa_put(rx_sa); | ||
1151 | rcu_read_unlock(); | 1153 | rcu_read_unlock(); |
1152 | *pskb = NULL; | 1154 | *pskb = NULL; |
1153 | return RX_HANDLER_CONSUMED; | 1155 | return RX_HANDLER_CONSUMED; |