]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
MacSec: fix backporting error in patches for CVE-2017-7477
authorAlexey Kodanev <alexey.kodanev@oracle.com>
Wed, 19 Jul 2017 05:06:26 +0000 (14:06 +0900)
committerChuck Anderson <chuck.anderson@oracle.com>
Wed, 2 Aug 2017 03:09:27 +0000 (20:09 -0700)
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:
[<ffffffff81735938>] dump_stack+0x63/0x81
[<ffffffff810a0fd8>] process_one_work+0x3a8/0x460
[<ffffffff810a1582>] worker_thread+0x112/0x520
[<ffffffff810a1470>] ? rescuer_thread+0x3e0/0x3e0
[<ffffffff810a7348>] kthread+0xd8/0xf0
[<ffffffff810a7270>] ? kthread_create_on_node+0x1b0/0x1b0
[<ffffffff8173d9a2>] ret_from_fork+0x42/0x70
[<ffffffff810a7270>] ? 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 <alexey.kodanev@oracle.com>
Signed-off-by: Ethan Zhao <ethan.zhao@oracle.com>
drivers/net/macsec.c

index b1b1ff0121885989a8f9bd3144aa5ae0cdbbee6d..37079a4058edfddde03bf6b0db3e3c154c032ecc 100644 (file)
@@ -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);