From: Alexey Kodanev Date: Wed, 19 Jul 2017 05:06:26 +0000 (+0900) Subject: MacSec: fix backporting error in patches for CVE-2017-7477 X-Git-Tag: v4.1.12-107.0.20170801_2000~8 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=06621abd6a951bf91370cd5c005d982576a1dc66;p=users%2Fjedix%2Flinux-maple.git MacSec: fix backporting error in patches for CVE-2017-7477 Orabug: 26443893 - macsec: dynamically allocate space for sglist (Jason A. Donenfeld) [Orabug: 26368162] {CVE-2017-7477} - macsec: avoid heap overflow in skb_to_sgvec (Jason A. Donenfeld) [Orabug: 26368162] {CVE-2017-7477} The backporting of above patches introduded a heap overrun error shown as bug 26443893. ------------[ cut here ]------------ WARNING: CPU: 28 PID: 0 at kernel/time/timer.c:1177 call_timer_fn+0x142/0x150() timer: mld_ifc_timer_expire+0x0/0x2d0 preempt leak: 00000100 -> 00000101 Modules linked in: gcm macsec fuse btrfs xor raid6_pq vfat msdos fat ext4 jbd2 ext2 mbcache2 ip6table_filter ip6_tables BUG: workqueue leaked lock or atomic: kworker/15:2/0x00000001/689 last function: addrconf_dad_work CPU: 15 PID: 689 Comm: kworker/15:2 Not tainted 4.1.12-103.2.6.el7uek.x86_64 Hardware name: Oracle Corporation SUN SERVER X4-2 /ASSY,MOTHERBOARD,1U , BIOS 25010603 01/16/2014 Workqueue: ipv6_addrconf addrconf_dad_work Call Trace: [] dump_stack+0x63/0x81 [] process_one_work+0x3a8/0x460 [] worker_thread+0x112/0x520 [] ? rescuer_thread+0x3e0/0x3e0 [] kthread+0xd8/0xf0 [] ? kthread_create_on_node+0x1b0/0x1b0 [] ret_from_fork+0x42/0x70 [] ? kthread_create_on_node+0x1b0/0x1b0 BUG: scheduling while atomic: kworker/15:2/689/0x00000001 1. newly introduced variable "num_frags" not used in 'sg_ad', assumes 'MAX_SKB_FRAGS + 1' 2. Initialization of sglist assumes 'MAX_SKB_FRAGS + 1' length, though it was changed to the number of scatterlist elements being returned from "skb_cow_data()" 3. It seems that "sg_init_table(sg, MAX_SKB_FRAGS + 1);" is redundant, it was already done a few lines before. This patch may solve the above issues. Signed-off-by: Alexey Kodanev Signed-off-by: Ethan Zhao --- diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c index b1b1ff0121885..37079a4058edf 100644 --- a/drivers/net/macsec.c +++ b/drivers/net/macsec.c @@ -625,7 +625,7 @@ static struct aead_request *macsec_alloc_req(struct crypto_aead *tfm, size = ALIGN(size, __alignof__(struct scatterlist)); sg_ad_offset = size; - size += sizeof(struct scatterlist) * (MAX_SKB_FRAGS + 1); + size += sizeof(struct scatterlist) * num_frags; tmp = kmalloc(size, GFP_ATOMIC); if (!tmp) @@ -742,9 +742,8 @@ static struct sk_buff *macsec_encrypt(struct sk_buff *skb, int assoc_len = macsec_hdr_len(tx_sc->send_sci); int data_len = skb->len - secy->icv_len - assoc_len; - sg_init_table(sg_ad, MAX_SKB_FRAGS + 1); + sg_init_table(sg_ad, ret); skb_to_sgvec(skb, sg_ad, 0, assoc_len); - sg_init_table(sg, MAX_SKB_FRAGS + 1); skb_to_sgvec(skb, sg, assoc_len, data_len + secy->icv_len); aead_request_set_crypt(req, sg, sg, data_len, iv); @@ -753,9 +752,8 @@ static struct sk_buff *macsec_encrypt(struct sk_buff *skb, int assoc_len = skb->len - secy->icv_len; int data_len = secy->icv_len; - sg_init_table(sg_ad, MAX_SKB_FRAGS + 1); + sg_init_table(sg_ad, ret); skb_to_sgvec(skb, sg_ad, 0, assoc_len); - sg_init_table(sg, MAX_SKB_FRAGS + 1); skb_to_sgvec(skb, sg, assoc_len, data_len); aead_request_set_crypt(req, sg, sg, 0, iv); @@ -968,9 +966,8 @@ static struct sk_buff *macsec_decrypt(struct sk_buff *skb, int assoc_len = macsec_hdr_len(macsec_skb_cb(skb)->has_sci); int data_len = skb->len - assoc_len; - sg_init_table(sg_ad, MAX_SKB_FRAGS + 1); + sg_init_table(sg_ad, ret); skb_to_sgvec(skb, sg_ad, 0, assoc_len); - sg_init_table(sg, MAX_SKB_FRAGS + 1); skb_to_sgvec(skb, sg, assoc_len, data_len); aead_request_set_crypt(req, sg, sg, data_len, iv); @@ -986,9 +983,8 @@ static struct sk_buff *macsec_decrypt(struct sk_buff *skb, int assoc_len = skb->len - icv_len; int data_len = icv_len; - sg_init_table(sg_ad, MAX_SKB_FRAGS + 1); + sg_init_table(sg_ad, ret); skb_to_sgvec(skb, sg_ad, 0, assoc_len); - sg_init_table(sg, MAX_SKB_FRAGS + 1); skb_to_sgvec(skb, sg, assoc_len, data_len); aead_request_set_crypt(req, sg, sg, data_len, iv);