aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSabrina Dubroca <sd@queasysnail.net>2016-04-22 05:28:04 -0400
committerDavid S. Miller <davem@davemloft.net>2016-04-24 14:31:58 -0400
commitc3b7d0bd7ac2c501d4806db71ddd383c184968e8 (patch)
tree8bc0ce1c27261b9857058fe24514c783b8879855
parent497f358aa4c0d99b75ec204407389920d5e33ec5 (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.c16
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;