From 89d8eaee98ecd49fefa315e9597598b15c76a028 Mon Sep 17 00:00:00 2001 From: Thomas Lamprecht Date: Wed, 13 Mar 2019 07:25:59 +0100 Subject: [PATCH] rebase patches on top of Ubuntu-4.15.0-47.50 (generated with debian/scripts/import-upstream-tag) Signed-off-by: Thomas Lamprecht --- ...-default-dynamic-halt-polling-growth.patch | 2 +- ...event-overlapping-tx_timeout-recover.patch | 2 +- ...pset-Fix-wraparound-n-hash-net-types.patch | 318 ------------------ ...o-set-sk-to-NULL-when-af_alg_release.patch | 118 ------- ...l_create_device-reference-counting-C.patch | 60 ---- ...tionally-cancel-preemption-timer-in-.patch | 46 --- ...und-leak-of-uninitialized-stack-cont.patch | 50 --- 7 files changed, 2 insertions(+), 594 deletions(-) delete mode 100644 patches/kernel/0010-netfilter-ipset-Fix-wraparound-n-hash-net-types.patch delete mode 100644 patches/kernel/0011-net-crypto-set-sk-to-NULL-when-af_alg_release.patch delete mode 100644 patches/kernel/0012-kvm-fix-kvm_ioctl_create_device-reference-counting-C.patch delete mode 100644 patches/kernel/0013-KVM-nVMX-unconditionally-cancel-preemption-timer-in-.patch delete mode 100644 patches/kernel/0014-KVM-x86-work-around-leak-of-uninitialized-stack-cont.patch diff --git a/patches/kernel/0004-kvm-disable-default-dynamic-halt-polling-growth.patch b/patches/kernel/0004-kvm-disable-default-dynamic-halt-polling-growth.patch index 74fc4fb..93e89fb 100644 --- a/patches/kernel/0004-kvm-disable-default-dynamic-halt-polling-growth.patch +++ b/patches/kernel/0004-kvm-disable-default-dynamic-halt-polling-growth.patch @@ -12,7 +12,7 @@ Signed-off-by: Fabian Grünbichler 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c -index 234d03abcb75..2e7d3aee779d 100644 +index 238ddbc127e1..d7a24fd29144 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -77,7 +77,7 @@ module_param(halt_poll_ns, uint, 0644); diff --git a/patches/kernel/0009-i40e-prevent-overlapping-tx_timeout-recover.patch b/patches/kernel/0009-i40e-prevent-overlapping-tx_timeout-recover.patch index 4e5367d..4841683 100644 --- a/patches/kernel/0009-i40e-prevent-overlapping-tx_timeout-recover.patch +++ b/patches/kernel/0009-i40e-prevent-overlapping-tx_timeout-recover.patch @@ -22,7 +22,7 @@ Signed-off-by: Thomas Lamprecht 2 files changed, 6 insertions(+) diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h -index e019baa905c5..80114d6a910a 100644 +index a68b914776c7..09452e4b4877 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -145,6 +145,7 @@ enum i40e_state_t { diff --git a/patches/kernel/0010-netfilter-ipset-Fix-wraparound-n-hash-net-types.patch b/patches/kernel/0010-netfilter-ipset-Fix-wraparound-n-hash-net-types.patch deleted file mode 100644 index 282e380..0000000 --- a/patches/kernel/0010-netfilter-ipset-Fix-wraparound-n-hash-net-types.patch +++ /dev/null @@ -1,318 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jozsef Kadlecsik -Date: Fri, 12 Jan 2018 11:16:50 +0100 -Subject: [PATCH] netfilter: ipset: Fix wraparound in hash:*net* types - -Fix wraparound bug which could lead to memory exhaustion when adding an -x.x.x.x-255.255.255.255 range to any hash:*net* types. - -Fixes Netfilter's bugzilla id #1212, reported by Thomas Schwark. - -Fixes: 48596a8ddc46 ("netfilter: ipset: Fix adding an IPv4 range containing more than 2^31 addresses") -Signed-off-by: Jozsef Kadlecsik -Signed-off-by: Pablo Neira Ayuso ---- - net/netfilter/ipset/ip_set_hash_ipportnet.c | 26 ++++++++++----------- - net/netfilter/ipset/ip_set_hash_net.c | 9 ++++--- - net/netfilter/ipset/ip_set_hash_netiface.c | 9 ++++--- - net/netfilter/ipset/ip_set_hash_netnet.c | 28 +++++++++++----------- - net/netfilter/ipset/ip_set_hash_netport.c | 19 ++++++++------- - net/netfilter/ipset/ip_set_hash_netportnet.c | 35 ++++++++++++++-------------- - 6 files changed, 63 insertions(+), 63 deletions(-) - -diff --git a/net/netfilter/ipset/ip_set_hash_ipportnet.c b/net/netfilter/ipset/ip_set_hash_ipportnet.c -index 0f164e986bf1..88b83d6d3084 100644 ---- a/net/netfilter/ipset/ip_set_hash_ipportnet.c -+++ b/net/netfilter/ipset/ip_set_hash_ipportnet.c -@@ -168,7 +168,7 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[], - struct hash_ipportnet4_elem e = { .cidr = HOST_MASK - 1 }; - struct ip_set_ext ext = IP_SET_INIT_UEXT(set); - u32 ip = 0, ip_to = 0, p = 0, port, port_to; -- u32 ip2_from = 0, ip2_to = 0, ip2_last, ip2; -+ u32 ip2_from = 0, ip2_to = 0, ip2; - bool with_ports = false; - u8 cidr; - int ret; -@@ -269,22 +269,21 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[], - ip_set_mask_from_to(ip2_from, ip2_to, e.cidr + 1); - } - -- if (retried) -+ if (retried) { - ip = ntohl(h->next.ip); -+ p = ntohs(h->next.port); -+ ip2 = ntohl(h->next.ip2); -+ } else { -+ p = port; -+ ip2 = ip2_from; -+ } - for (; ip <= ip_to; ip++) { - e.ip = htonl(ip); -- p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port) -- : port; - for (; p <= port_to; p++) { - e.port = htons(p); -- ip2 = retried && -- ip == ntohl(h->next.ip) && -- p == ntohs(h->next.port) -- ? ntohl(h->next.ip2) : ip2_from; -- while (ip2 <= ip2_to) { -+ do { - e.ip2 = htonl(ip2); -- ip2_last = ip_set_range_to_cidr(ip2, ip2_to, -- &cidr); -+ ip2 = ip_set_range_to_cidr(ip2, ip2_to, &cidr); - e.cidr = cidr - 1; - ret = adtfn(set, &e, &ext, &ext, flags); - -@@ -292,9 +291,10 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[], - return ret; - - ret = 0; -- ip2 = ip2_last + 1; -- } -+ } while (ip2++ < ip2_to); -+ ip2 = ip2_from; - } -+ p = port; - } - return ret; - } -diff --git a/net/netfilter/ipset/ip_set_hash_net.c b/net/netfilter/ipset/ip_set_hash_net.c -index 1c67a1761e45..5449e23af13a 100644 ---- a/net/netfilter/ipset/ip_set_hash_net.c -+++ b/net/netfilter/ipset/ip_set_hash_net.c -@@ -143,7 +143,7 @@ hash_net4_uadt(struct ip_set *set, struct nlattr *tb[], - ipset_adtfn adtfn = set->variant->adt[adt]; - struct hash_net4_elem e = { .cidr = HOST_MASK }; - struct ip_set_ext ext = IP_SET_INIT_UEXT(set); -- u32 ip = 0, ip_to = 0, last; -+ u32 ip = 0, ip_to = 0; - int ret; - - if (tb[IPSET_ATTR_LINENO]) -@@ -193,16 +193,15 @@ hash_net4_uadt(struct ip_set *set, struct nlattr *tb[], - } - if (retried) - ip = ntohl(h->next.ip); -- while (ip <= ip_to) { -+ do { - e.ip = htonl(ip); -- last = ip_set_range_to_cidr(ip, ip_to, &e.cidr); -+ ip = ip_set_range_to_cidr(ip, ip_to, &e.cidr); - ret = adtfn(set, &e, &ext, &ext, flags); - if (ret && !ip_set_eexist(ret, flags)) - return ret; - - ret = 0; -- ip = last + 1; -- } -+ } while (ip++ < ip_to); - return ret; - } - -diff --git a/net/netfilter/ipset/ip_set_hash_netiface.c b/net/netfilter/ipset/ip_set_hash_netiface.c -index d417074f1c1a..f5164c1efce2 100644 ---- a/net/netfilter/ipset/ip_set_hash_netiface.c -+++ b/net/netfilter/ipset/ip_set_hash_netiface.c -@@ -200,7 +200,7 @@ hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[], - ipset_adtfn adtfn = set->variant->adt[adt]; - struct hash_netiface4_elem e = { .cidr = HOST_MASK, .elem = 1 }; - struct ip_set_ext ext = IP_SET_INIT_UEXT(set); -- u32 ip = 0, ip_to = 0, last; -+ u32 ip = 0, ip_to = 0; - int ret; - - if (tb[IPSET_ATTR_LINENO]) -@@ -255,17 +255,16 @@ hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[], - - if (retried) - ip = ntohl(h->next.ip); -- while (ip <= ip_to) { -+ do { - e.ip = htonl(ip); -- last = ip_set_range_to_cidr(ip, ip_to, &e.cidr); -+ ip = ip_set_range_to_cidr(ip, ip_to, &e.cidr); - ret = adtfn(set, &e, &ext, &ext, flags); - - if (ret && !ip_set_eexist(ret, flags)) - return ret; - - ret = 0; -- ip = last + 1; -- } -+ } while (ip++ < ip_to); - return ret; - } - -diff --git a/net/netfilter/ipset/ip_set_hash_netnet.c b/net/netfilter/ipset/ip_set_hash_netnet.c -index 7f9ae2e9645b..5a2b923bd81f 100644 ---- a/net/netfilter/ipset/ip_set_hash_netnet.c -+++ b/net/netfilter/ipset/ip_set_hash_netnet.c -@@ -169,8 +169,8 @@ hash_netnet4_uadt(struct ip_set *set, struct nlattr *tb[], - ipset_adtfn adtfn = set->variant->adt[adt]; - struct hash_netnet4_elem e = { }; - struct ip_set_ext ext = IP_SET_INIT_UEXT(set); -- u32 ip = 0, ip_to = 0, last; -- u32 ip2 = 0, ip2_from = 0, ip2_to = 0, last2; -+ u32 ip = 0, ip_to = 0; -+ u32 ip2 = 0, ip2_from = 0, ip2_to = 0; - int ret; - - if (tb[IPSET_ATTR_LINENO]) -@@ -247,27 +247,27 @@ hash_netnet4_uadt(struct ip_set *set, struct nlattr *tb[], - ip_set_mask_from_to(ip2_from, ip2_to, e.cidr[1]); - } - -- if (retried) -+ if (retried) { - ip = ntohl(h->next.ip[0]); -+ ip2 = ntohl(h->next.ip[1]); -+ } else { -+ ip2 = ip2_from; -+ } - -- while (ip <= ip_to) { -+ do { - e.ip[0] = htonl(ip); -- last = ip_set_range_to_cidr(ip, ip_to, &e.cidr[0]); -- ip2 = (retried && -- ip == ntohl(h->next.ip[0])) ? ntohl(h->next.ip[1]) -- : ip2_from; -- while (ip2 <= ip2_to) { -+ ip = ip_set_range_to_cidr(ip, ip_to, &e.cidr[0]); -+ do { - e.ip[1] = htonl(ip2); -- last2 = ip_set_range_to_cidr(ip2, ip2_to, &e.cidr[1]); -+ ip2 = ip_set_range_to_cidr(ip2, ip2_to, &e.cidr[1]); - ret = adtfn(set, &e, &ext, &ext, flags); - if (ret && !ip_set_eexist(ret, flags)) - return ret; - - ret = 0; -- ip2 = last2 + 1; -- } -- ip = last + 1; -- } -+ } while (ip2++ < ip2_to); -+ ip2 = ip2_from; -+ } while (ip++ < ip_to); - return ret; - } - -diff --git a/net/netfilter/ipset/ip_set_hash_netport.c b/net/netfilter/ipset/ip_set_hash_netport.c -index e6ef382febe4..1a187be9ebc8 100644 ---- a/net/netfilter/ipset/ip_set_hash_netport.c -+++ b/net/netfilter/ipset/ip_set_hash_netport.c -@@ -161,7 +161,7 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[], - ipset_adtfn adtfn = set->variant->adt[adt]; - struct hash_netport4_elem e = { .cidr = HOST_MASK - 1 }; - struct ip_set_ext ext = IP_SET_INIT_UEXT(set); -- u32 port, port_to, p = 0, ip = 0, ip_to = 0, last; -+ u32 port, port_to, p = 0, ip = 0, ip_to = 0; - bool with_ports = false; - u8 cidr; - int ret; -@@ -239,25 +239,26 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[], - ip_set_mask_from_to(ip, ip_to, e.cidr + 1); - } - -- if (retried) -+ if (retried) { - ip = ntohl(h->next.ip); -- while (ip <= ip_to) { -+ p = ntohs(h->next.port); -+ } else { -+ p = port; -+ } -+ do { - e.ip = htonl(ip); -- last = ip_set_range_to_cidr(ip, ip_to, &cidr); -+ ip = ip_set_range_to_cidr(ip, ip_to, &cidr); - e.cidr = cidr - 1; -- p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port) -- : port; - for (; p <= port_to; p++) { - e.port = htons(p); - ret = adtfn(set, &e, &ext, &ext, flags); -- - if (ret && !ip_set_eexist(ret, flags)) - return ret; - - ret = 0; - } -- ip = last + 1; -- } -+ p = port; -+ } while (ip++ < ip_to); - return ret; - } - -diff --git a/net/netfilter/ipset/ip_set_hash_netportnet.c b/net/netfilter/ipset/ip_set_hash_netportnet.c -index 8602f2595a1a..d391485a6acd 100644 ---- a/net/netfilter/ipset/ip_set_hash_netportnet.c -+++ b/net/netfilter/ipset/ip_set_hash_netportnet.c -@@ -184,8 +184,8 @@ hash_netportnet4_uadt(struct ip_set *set, struct nlattr *tb[], - ipset_adtfn adtfn = set->variant->adt[adt]; - struct hash_netportnet4_elem e = { }; - struct ip_set_ext ext = IP_SET_INIT_UEXT(set); -- u32 ip = 0, ip_to = 0, ip_last, p = 0, port, port_to; -- u32 ip2_from = 0, ip2_to = 0, ip2_last, ip2; -+ u32 ip = 0, ip_to = 0, p = 0, port, port_to; -+ u32 ip2_from = 0, ip2_to = 0, ip2; - bool with_ports = false; - int ret; - -@@ -288,33 +288,34 @@ hash_netportnet4_uadt(struct ip_set *set, struct nlattr *tb[], - ip_set_mask_from_to(ip2_from, ip2_to, e.cidr[1]); - } - -- if (retried) -+ if (retried) { - ip = ntohl(h->next.ip[0]); -+ p = ntohs(h->next.port); -+ ip2 = ntohl(h->next.ip[1]); -+ } else { -+ p = port; -+ ip2 = ip2_from; -+ } - -- while (ip <= ip_to) { -+ do { - e.ip[0] = htonl(ip); -- ip_last = ip_set_range_to_cidr(ip, ip_to, &e.cidr[0]); -- p = retried && ip == ntohl(h->next.ip[0]) ? ntohs(h->next.port) -- : port; -+ ip = ip_set_range_to_cidr(ip, ip_to, &e.cidr[0]); - for (; p <= port_to; p++) { - e.port = htons(p); -- ip2 = (retried && ip == ntohl(h->next.ip[0]) && -- p == ntohs(h->next.port)) ? ntohl(h->next.ip[1]) -- : ip2_from; -- while (ip2 <= ip2_to) { -+ do { - e.ip[1] = htonl(ip2); -- ip2_last = ip_set_range_to_cidr(ip2, ip2_to, -- &e.cidr[1]); -+ ip2 = ip_set_range_to_cidr(ip2, ip2_to, -+ &e.cidr[1]); - ret = adtfn(set, &e, &ext, &ext, flags); - if (ret && !ip_set_eexist(ret, flags)) - return ret; - - ret = 0; -- ip2 = ip2_last + 1; -- } -+ } while (ip2++ < ip2_to); -+ ip2 = ip2_from; - } -- ip = ip_last + 1; -- } -+ p = port; -+ } while (ip++ < ip_to); - return ret; - } - --- -2.11.0 - diff --git a/patches/kernel/0011-net-crypto-set-sk-to-NULL-when-af_alg_release.patch b/patches/kernel/0011-net-crypto-set-sk-to-NULL-when-af_alg_release.patch deleted file mode 100644 index 8450fd2..0000000 --- a/patches/kernel/0011-net-crypto-set-sk-to-NULL-when-af_alg_release.patch +++ /dev/null @@ -1,118 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Mao Wenan -Date: Mon, 18 Feb 2019 10:44:44 +0800 -Subject: [PATCH] net: crypto set sk to NULL when af_alg_release. - -KASAN has found use-after-free in sockfs_setattr. -The existed commit 6d8c50dcb029 ("socket: close race condition between sock_close() -and sockfs_setattr()") is to fix this simillar issue, but it seems to ignore -that crypto module forgets to set the sk to NULL after af_alg_release. - -KASAN report details as below: -BUG: KASAN: use-after-free in sockfs_setattr+0x120/0x150 -Write of size 4 at addr ffff88837b956128 by task syz-executor0/4186 - -CPU: 2 PID: 4186 Comm: syz-executor0 Not tainted xxx + #1 -Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS -1.10.2-1ubuntu1 04/01/2014 -Call Trace: - dump_stack+0xca/0x13e - print_address_description+0x79/0x330 - ? vprintk_func+0x5e/0xf0 - kasan_report+0x18a/0x2e0 - ? sockfs_setattr+0x120/0x150 - sockfs_setattr+0x120/0x150 - ? sock_register+0x2d0/0x2d0 - notify_change+0x90c/0xd40 - ? chown_common+0x2ef/0x510 - chown_common+0x2ef/0x510 - ? chmod_common+0x3b0/0x3b0 - ? __lock_is_held+0xbc/0x160 - ? __sb_start_write+0x13d/0x2b0 - ? __mnt_want_write+0x19a/0x250 - do_fchownat+0x15c/0x190 - ? __ia32_sys_chmod+0x80/0x80 - ? trace_hardirqs_on_thunk+0x1a/0x1c - __x64_sys_fchownat+0xbf/0x160 - ? lockdep_hardirqs_on+0x39a/0x5e0 - do_syscall_64+0xc8/0x580 - entry_SYSCALL_64_after_hwframe+0x49/0xbe -RIP: 0033:0x462589 -Code: f7 d8 64 89 02 b8 ff ff ff ff c3 66 0f 1f 44 00 00 48 89 f8 48 89 -f7 48 89 d6 48 89 -ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 -48 c7 c1 bc ff ff -ff f7 d8 64 89 01 48 -RSP: 002b:00007fb4b2c83c58 EFLAGS: 00000246 ORIG_RAX: 0000000000000104 -RAX: ffffffffffffffda RBX: 000000000072bfa0 RCX: 0000000000462589 -RDX: 0000000000000000 RSI: 00000000200000c0 RDI: 0000000000000007 -RBP: 0000000000000005 R08: 0000000000001000 R09: 0000000000000000 -R10: 0000000000000000 R11: 0000000000000246 R12: 00007fb4b2c846bc -R13: 00000000004bc733 R14: 00000000006f5138 R15: 00000000ffffffff - -Allocated by task 4185: - kasan_kmalloc+0xa0/0xd0 - __kmalloc+0x14a/0x350 - sk_prot_alloc+0xf6/0x290 - sk_alloc+0x3d/0xc00 - af_alg_accept+0x9e/0x670 - hash_accept+0x4a3/0x650 - __sys_accept4+0x306/0x5c0 - __x64_sys_accept4+0x98/0x100 - do_syscall_64+0xc8/0x580 - entry_SYSCALL_64_after_hwframe+0x49/0xbe - -Freed by task 4184: - __kasan_slab_free+0x12e/0x180 - kfree+0xeb/0x2f0 - __sk_destruct+0x4e6/0x6a0 - sk_destruct+0x48/0x70 - __sk_free+0xa9/0x270 - sk_free+0x2a/0x30 - af_alg_release+0x5c/0x70 - __sock_release+0xd3/0x280 - sock_close+0x1a/0x20 - __fput+0x27f/0x7f0 - task_work_run+0x136/0x1b0 - exit_to_usermode_loop+0x1a7/0x1d0 - do_syscall_64+0x461/0x580 - entry_SYSCALL_64_after_hwframe+0x49/0xbe - -Syzkaller reproducer: -r0 = perf_event_open(&(0x7f0000000000)={0x0, 0x70, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, @perf_config_ext}, 0x0, 0x0, -0xffffffffffffffff, 0x0) -r1 = socket$alg(0x26, 0x5, 0x0) -getrusage(0x0, 0x0) -bind(r1, &(0x7f00000001c0)=@alg={0x26, 'hash\x00', 0x0, 0x0, -'sha256-ssse3\x00'}, 0x80) -r2 = accept(r1, 0x0, 0x0) -r3 = accept4$unix(r2, 0x0, 0x0, 0x0) -r4 = dup3(r3, r0, 0x0) -fchownat(r4, &(0x7f00000000c0)='\x00', 0x0, 0x0, 0x1000) - -Fixes: 6d8c50dcb029 ("socket: close race condition between sock_close() and sockfs_setattr()") -Signed-off-by: Mao Wenan -Signed-off-by: Thomas Lamprecht ---- - crypto/af_alg.c | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/crypto/af_alg.c b/crypto/af_alg.c -index 671e42ff21d4..493002afae73 100644 ---- a/crypto/af_alg.c -+++ b/crypto/af_alg.c -@@ -122,8 +122,10 @@ static void alg_do_release(const struct af_alg_type *type, void *private) - - int af_alg_release(struct socket *sock) - { -- if (sock->sk) -+ if (sock->sk) { - sock_put(sock->sk); -+ sock->sk = NULL; -+ } - return 0; - } - EXPORT_SYMBOL_GPL(af_alg_release); diff --git a/patches/kernel/0012-kvm-fix-kvm_ioctl_create_device-reference-counting-C.patch b/patches/kernel/0012-kvm-fix-kvm_ioctl_create_device-reference-counting-C.patch deleted file mode 100644 index 0829c98..0000000 --- a/patches/kernel/0012-kvm-fix-kvm_ioctl_create_device-reference-counting-C.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jann Horn -Date: Mon, 25 Feb 2019 11:48:05 +0000 -Subject: [PATCH] kvm: fix kvm_ioctl_create_device() reference counting - (CVE-2019-6974) - -kvm_ioctl_create_device() does the following: - -1. creates a device that holds a reference to the VM object (with a borrowed - reference, the VM's refcount has not been bumped yet) -2. initializes the device -3. transfers the reference to the device to the caller's file descriptor table -4. calls kvm_get_kvm() to turn the borrowed reference to the VM into a real - reference - -The ownership transfer in step 3 must not happen before the reference to the VM -becomes a proper, non-borrowed reference, which only happens in step 4. -After step 3, an attacker can close the file descriptor and drop the borrowed -reference, which can cause the refcount of the kvm object to drop to zero. - -This means that we need to grab a reference for the device before -anon_inode_getfd(), otherwise the VM can disappear from under us. - -Fixes: 852b6d57dc7f ("kvm: add device control API") -Cc: stable@kernel.org -Signed-off-by: Jann Horn -Signed-off-by: Paolo Bonzini - -CVE-2019-6974 - -(cherry picked from commit cfa39381173d5f969daf43582c95ad679189cbc9) -Signed-off-by: Tyler Hicks -Signed-off-by: Thomas Lamprecht ---- - virt/kvm/kvm_main.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c -index 234d03abcb75..238ddbc127e1 100644 ---- a/virt/kvm/kvm_main.c -+++ b/virt/kvm/kvm_main.c -@@ -2908,8 +2908,10 @@ static int kvm_ioctl_create_device(struct kvm *kvm, - if (ops->init) - ops->init(dev); - -+ kvm_get_kvm(kvm); - ret = anon_inode_getfd(ops->name, &kvm_device_fops, dev, O_RDWR | O_CLOEXEC); - if (ret < 0) { -+ kvm_put_kvm(kvm); - mutex_lock(&kvm->lock); - list_del(&dev->vm_node); - mutex_unlock(&kvm->lock); -@@ -2917,7 +2919,6 @@ static int kvm_ioctl_create_device(struct kvm *kvm, - return ret; - } - -- kvm_get_kvm(kvm); - cd->fd = ret; - return 0; - } diff --git a/patches/kernel/0013-KVM-nVMX-unconditionally-cancel-preemption-timer-in-.patch b/patches/kernel/0013-KVM-nVMX-unconditionally-cancel-preemption-timer-in-.patch deleted file mode 100644 index 6b55182..0000000 --- a/patches/kernel/0013-KVM-nVMX-unconditionally-cancel-preemption-timer-in-.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Peter Shier -Date: Mon, 25 Feb 2019 11:48:06 +0000 -Subject: [PATCH] KVM: nVMX: unconditionally cancel preemption timer in - free_nested (CVE-2019-7221) - -Bugzilla: 1671904 - -There are multiple code paths where an hrtimer may have been started to -emulate an L1 VMX preemption timer that can result in a call to free_nested -without an intervening L2 exit where the hrtimer is normally -cancelled. Unconditionally cancel in free_nested to cover all cases. - -Embargoed until Feb 7th 2019. - -Signed-off-by: Peter Shier -Reported-by: Jim Mattson -Reviewed-by: Jim Mattson -Reported-by: Felix Wilhelm -Cc: stable@kernel.org -Message-Id: <20181011184646.154065-1-pshier@google.com> -Signed-off-by: Paolo Bonzini - -CVE-2019-7221 - -(backported from commit ecec76885bcfe3294685dc363fd1273df0d5d65f) -[tyhicks: Backport to 4.18: - - free_nested() is in arch/x86/kvm/vmx.c] -Signed-off-by: Tyler Hicks -Signed-off-by: Thomas Lamprecht ---- - arch/x86/kvm/vmx.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c -index 7ade6cb125d3..37b095e7f00a 100644 ---- a/arch/x86/kvm/vmx.c -+++ b/arch/x86/kvm/vmx.c -@@ -7681,6 +7681,7 @@ static void free_nested(struct vcpu_vmx *vmx) - if (!vmx->nested.vmxon && !vmx->nested.smm.vmxon) - return; - -+ hrtimer_cancel(&vmx->nested.preemption_timer); - vmx->nested.vmxon = false; - vmx->nested.smm.vmxon = false; - free_vpid(vmx->nested.vpid02); diff --git a/patches/kernel/0014-KVM-x86-work-around-leak-of-uninitialized-stack-cont.patch b/patches/kernel/0014-KVM-x86-work-around-leak-of-uninitialized-stack-cont.patch deleted file mode 100644 index bc12f72..0000000 --- a/patches/kernel/0014-KVM-x86-work-around-leak-of-uninitialized-stack-cont.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Paolo Bonzini -Date: Mon, 25 Feb 2019 11:48:07 +0000 -Subject: [PATCH] KVM: x86: work around leak of uninitialized stack contents - (CVE-2019-7222) - -Bugzilla: 1671930 - -Emulation of certain instructions (VMXON, VMCLEAR, VMPTRLD, VMWRITE with -memory operand, INVEPT, INVVPID) can incorrectly inject a page fault -when passed an operand that points to an MMIO address. The page fault -will use uninitialized kernel stack memory as the CR2 and error code. - -The right behavior would be to abort the VM with a KVM_EXIT_INTERNAL_ERROR -exit to userspace; however, it is not an easy fix, so for now just -ensure that the error code and CR2 are zero. - -Embargoed until Feb 7th 2019. - -Reported-by: Felix Wilhelm -Cc: stable@kernel.org -Signed-off-by: Paolo Bonzini - -CVE-2019-7222 - -(cherry picked from commit 353c0956a618a07ba4bbe7ad00ff29fe70e8412a) -Signed-off-by: Tyler Hicks -Signed-off-by: Thomas Lamprecht ---- - arch/x86/kvm/x86.c | 7 +++++++ - 1 file changed, 7 insertions(+) - -diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c -index b3df576413cd..13804929adce 100644 ---- a/arch/x86/kvm/x86.c -+++ b/arch/x86/kvm/x86.c -@@ -4632,6 +4632,13 @@ int kvm_read_guest_virt(struct kvm_vcpu *vcpu, - { - u32 access = (kvm_x86_ops->get_cpl(vcpu) == 3) ? PFERR_USER_MASK : 0; - -+ /* -+ * FIXME: this should call handle_emulation_failure if X86EMUL_IO_NEEDED -+ * is returned, but our callers are not ready for that and they blindly -+ * call kvm_inject_page_fault. Ensure that they at least do not leak -+ * uninitialized kernel stack memory into cr2 and error code. -+ */ -+ memset(exception, 0, sizeof(*exception)); - return kvm_read_guest_virt_helper(addr, val, bytes, vcpu, access, - exception); - }