From: Greg Kroah-Hartman Date: Sat, 31 Jul 2021 07:00:01 +0000 (+0200) Subject: 4.14-stable patches X-Git-Tag: v4.4.278~52 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=4ffdf1c7172b59b652f24cdf16b9e42f6b62ec92;p=thirdparty%2Fkernel%2Fstable-queue.git 4.14-stable patches added patches: can-ems_usb-fix-memory-leak.patch can-esd_usb2-fix-memory-leak.patch can-mcba_usb_start-add-missing-urb-transfer_dma-initialization.patch can-raw-raw_setsockopt-fix-raw_rcv-panic-for-sock-uaf.patch can-usb_8dev-fix-memory-leak.patch nfc-nfcsim-fix-use-after-free-during-module-unload.patch niu-fix-incorrect-error-return-missed-in-previous-revert.patch ocfs2-fix-zero-out-valid-data.patch ocfs2-issue-zeroout-to-eof-blocks.patch x86-kvm-fix-vcpu-id-indexed-array-sizes.patch --- diff --git a/queue-4.14/can-ems_usb-fix-memory-leak.patch b/queue-4.14/can-ems_usb-fix-memory-leak.patch new file mode 100644 index 00000000000..99856892c6d --- /dev/null +++ b/queue-4.14/can-ems_usb-fix-memory-leak.patch @@ -0,0 +1,93 @@ +From 9969e3c5f40c166e3396acc36c34f9de502929f6 Mon Sep 17 00:00:00 2001 +From: Pavel Skripkin +Date: Tue, 27 Jul 2021 20:00:33 +0300 +Subject: can: ems_usb: fix memory leak + +From: Pavel Skripkin + +commit 9969e3c5f40c166e3396acc36c34f9de502929f6 upstream. + +In ems_usb_start() MAX_RX_URBS coherent buffers are allocated and +there is nothing, that frees them: + +1) In callback function the urb is resubmitted and that's all +2) In disconnect function urbs are simply killed, but URB_FREE_BUFFER + is not set (see ems_usb_start) and this flag cannot be used with + coherent buffers. + +So, all allocated buffers should be freed with usb_free_coherent() +explicitly. + +Side note: This code looks like a copy-paste of other can drivers. The +same patch was applied to mcba_usb driver and it works nice with real +hardware. There is no change in functionality, only clean-up code for +coherent buffers. + +Fixes: 702171adeed3 ("ems_usb: Added support for EMS CPC-USB/ARM7 CAN/USB interface") +Link: https://lore.kernel.org/r/59aa9fbc9a8cbf9af2bbd2f61a659c480b415800.1627404470.git.paskripkin@gmail.com +Cc: linux-stable +Signed-off-by: Pavel Skripkin +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/can/usb/ems_usb.c | 14 +++++++++++++- + 1 file changed, 13 insertions(+), 1 deletion(-) + +--- a/drivers/net/can/usb/ems_usb.c ++++ b/drivers/net/can/usb/ems_usb.c +@@ -267,6 +267,8 @@ struct ems_usb { + unsigned int free_slots; /* remember number of available slots */ + + struct ems_cpc_msg active_params; /* active controller parameters */ ++ void *rxbuf[MAX_RX_URBS]; ++ dma_addr_t rxbuf_dma[MAX_RX_URBS]; + }; + + static void ems_usb_read_interrupt_callback(struct urb *urb) +@@ -598,6 +600,7 @@ static int ems_usb_start(struct ems_usb + for (i = 0; i < MAX_RX_URBS; i++) { + struct urb *urb = NULL; + u8 *buf = NULL; ++ dma_addr_t buf_dma; + + /* create a URB, and a buffer for it */ + urb = usb_alloc_urb(0, GFP_KERNEL); +@@ -607,7 +610,7 @@ static int ems_usb_start(struct ems_usb + } + + buf = usb_alloc_coherent(dev->udev, RX_BUFFER_SIZE, GFP_KERNEL, +- &urb->transfer_dma); ++ &buf_dma); + if (!buf) { + netdev_err(netdev, "No memory left for USB buffer\n"); + usb_free_urb(urb); +@@ -615,6 +618,8 @@ static int ems_usb_start(struct ems_usb + break; + } + ++ urb->transfer_dma = buf_dma; ++ + usb_fill_bulk_urb(urb, dev->udev, usb_rcvbulkpipe(dev->udev, 2), + buf, RX_BUFFER_SIZE, + ems_usb_read_bulk_callback, dev); +@@ -630,6 +635,9 @@ static int ems_usb_start(struct ems_usb + break; + } + ++ dev->rxbuf[i] = buf; ++ dev->rxbuf_dma[i] = buf_dma; ++ + /* Drop reference, USB core will take care of freeing it */ + usb_free_urb(urb); + } +@@ -695,6 +703,10 @@ static void unlink_all_urbs(struct ems_u + + usb_kill_anchored_urbs(&dev->rx_submitted); + ++ for (i = 0; i < MAX_RX_URBS; ++i) ++ usb_free_coherent(dev->udev, RX_BUFFER_SIZE, ++ dev->rxbuf[i], dev->rxbuf_dma[i]); ++ + usb_kill_anchored_urbs(&dev->tx_submitted); + atomic_set(&dev->active_tx_urbs, 0); + diff --git a/queue-4.14/can-esd_usb2-fix-memory-leak.patch b/queue-4.14/can-esd_usb2-fix-memory-leak.patch new file mode 100644 index 00000000000..c9e4e0daab5 --- /dev/null +++ b/queue-4.14/can-esd_usb2-fix-memory-leak.patch @@ -0,0 +1,97 @@ +From 928150fad41ba16df7fcc9f7f945747d0f56cbb6 Mon Sep 17 00:00:00 2001 +From: Pavel Skripkin +Date: Tue, 27 Jul 2021 20:00:46 +0300 +Subject: can: esd_usb2: fix memory leak + +From: Pavel Skripkin + +commit 928150fad41ba16df7fcc9f7f945747d0f56cbb6 upstream. + +In esd_usb2_setup_rx_urbs() MAX_RX_URBS coherent buffers are allocated +and there is nothing, that frees them: + +1) In callback function the urb is resubmitted and that's all +2) In disconnect function urbs are simply killed, but URB_FREE_BUFFER + is not set (see esd_usb2_setup_rx_urbs) and this flag cannot be used + with coherent buffers. + +So, all allocated buffers should be freed with usb_free_coherent() +explicitly. + +Side note: This code looks like a copy-paste of other can drivers. The +same patch was applied to mcba_usb driver and it works nice with real +hardware. There is no change in functionality, only clean-up code for +coherent buffers. + +Fixes: 96d8e90382dc ("can: Add driver for esd CAN-USB/2 device") +Link: https://lore.kernel.org/r/b31b096926dcb35998ad0271aac4b51770ca7cc8.1627404470.git.paskripkin@gmail.com +Cc: linux-stable +Signed-off-by: Pavel Skripkin +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/can/usb/esd_usb2.c | 16 +++++++++++++++- + 1 file changed, 15 insertions(+), 1 deletion(-) + +--- a/drivers/net/can/usb/esd_usb2.c ++++ b/drivers/net/can/usb/esd_usb2.c +@@ -207,6 +207,8 @@ struct esd_usb2 { + int net_count; + u32 version; + int rxinitdone; ++ void *rxbuf[MAX_RX_URBS]; ++ dma_addr_t rxbuf_dma[MAX_RX_URBS]; + }; + + struct esd_usb2_net_priv { +@@ -556,6 +558,7 @@ static int esd_usb2_setup_rx_urbs(struct + for (i = 0; i < MAX_RX_URBS; i++) { + struct urb *urb = NULL; + u8 *buf = NULL; ++ dma_addr_t buf_dma; + + /* create a URB, and a buffer for it */ + urb = usb_alloc_urb(0, GFP_KERNEL); +@@ -565,7 +568,7 @@ static int esd_usb2_setup_rx_urbs(struct + } + + buf = usb_alloc_coherent(dev->udev, RX_BUFFER_SIZE, GFP_KERNEL, +- &urb->transfer_dma); ++ &buf_dma); + if (!buf) { + dev_warn(dev->udev->dev.parent, + "No memory left for USB buffer\n"); +@@ -573,6 +576,8 @@ static int esd_usb2_setup_rx_urbs(struct + goto freeurb; + } + ++ urb->transfer_dma = buf_dma; ++ + usb_fill_bulk_urb(urb, dev->udev, + usb_rcvbulkpipe(dev->udev, 1), + buf, RX_BUFFER_SIZE, +@@ -585,8 +590,12 @@ static int esd_usb2_setup_rx_urbs(struct + usb_unanchor_urb(urb); + usb_free_coherent(dev->udev, RX_BUFFER_SIZE, buf, + urb->transfer_dma); ++ goto freeurb; + } + ++ dev->rxbuf[i] = buf; ++ dev->rxbuf_dma[i] = buf_dma; ++ + freeurb: + /* Drop reference, USB core will take care of freeing it */ + usb_free_urb(urb); +@@ -674,6 +683,11 @@ static void unlink_all_urbs(struct esd_u + int i, j; + + usb_kill_anchored_urbs(&dev->rx_submitted); ++ ++ for (i = 0; i < MAX_RX_URBS; ++i) ++ usb_free_coherent(dev->udev, RX_BUFFER_SIZE, ++ dev->rxbuf[i], dev->rxbuf_dma[i]); ++ + for (i = 0; i < dev->net_count; i++) { + priv = dev->nets[i]; + if (priv) { diff --git a/queue-4.14/can-mcba_usb_start-add-missing-urb-transfer_dma-initialization.patch b/queue-4.14/can-mcba_usb_start-add-missing-urb-transfer_dma-initialization.patch new file mode 100644 index 00000000000..968b732bcde --- /dev/null +++ b/queue-4.14/can-mcba_usb_start-add-missing-urb-transfer_dma-initialization.patch @@ -0,0 +1,52 @@ +From fc43fb69a7af92839551f99c1a96a37b77b3ae7a Mon Sep 17 00:00:00 2001 +From: Pavel Skripkin +Date: Sun, 25 Jul 2021 13:36:30 +0300 +Subject: can: mcba_usb_start(): add missing urb->transfer_dma initialization + +From: Pavel Skripkin + +commit fc43fb69a7af92839551f99c1a96a37b77b3ae7a upstream. + +Yasushi reported, that his Microchip CAN Analyzer stopped working +since commit 91c02557174b ("can: mcba_usb: fix memory leak in +mcba_usb"). The problem was in missing urb->transfer_dma +initialization. + +In my previous patch to this driver I refactored mcba_usb_start() code +to avoid leaking usb coherent buffers. To archive it, I passed local +stack variable to usb_alloc_coherent() and then saved it to private +array to correctly free all coherent buffers on ->close() call. But I +forgot to initialize urb->transfer_dma with variable passed to +usb_alloc_coherent(). + +All of this was causing device to not work, since dma addr 0 is not +valid and following log can be found on bug report page, which points +exactly to problem described above. + +| DMAR: [DMA Write] Request device [00:14.0] PASID ffffffff fault addr 0 [fault reason 05] PTE Write access is not set + +Fixes: 91c02557174b ("can: mcba_usb: fix memory leak in mcba_usb") +Link: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=990850 +Link: https://lore.kernel.org/r/20210725103630.23864-1-paskripkin@gmail.com +Cc: linux-stable +Reported-by: Yasushi SHOJI +Signed-off-by: Pavel Skripkin +Tested-by: Yasushi SHOJI +[mkl: fixed typos in commit message - thanks Yasushi SHOJI] +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/can/usb/mcba_usb.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/net/can/usb/mcba_usb.c ++++ b/drivers/net/can/usb/mcba_usb.c +@@ -664,6 +664,8 @@ static int mcba_usb_start(struct mcba_pr + break; + } + ++ urb->transfer_dma = buf_dma; ++ + usb_fill_bulk_urb(urb, priv->udev, + usb_rcvbulkpipe(priv->udev, MCBA_USB_EP_IN), + buf, MCBA_USB_RX_BUFF_SIZE, diff --git a/queue-4.14/can-raw-raw_setsockopt-fix-raw_rcv-panic-for-sock-uaf.patch b/queue-4.14/can-raw-raw_setsockopt-fix-raw_rcv-panic-for-sock-uaf.patch new file mode 100644 index 00000000000..f8964452ac2 --- /dev/null +++ b/queue-4.14/can-raw-raw_setsockopt-fix-raw_rcv-panic-for-sock-uaf.patch @@ -0,0 +1,163 @@ +From 54f93336d000229f72c26d8a3f69dd256b744528 Mon Sep 17 00:00:00 2001 +From: Ziyang Xuan +Date: Thu, 22 Jul 2021 15:08:19 +0800 +Subject: can: raw: raw_setsockopt(): fix raw_rcv panic for sock UAF + +From: Ziyang Xuan + +commit 54f93336d000229f72c26d8a3f69dd256b744528 upstream. + +We get a bug during ltp can_filter test as following. + +=========================================== +[60919.264984] BUG: unable to handle kernel NULL pointer dereference at 0000000000000010 +[60919.265223] PGD 8000003dda726067 P4D 8000003dda726067 PUD 3dda727067 PMD 0 +[60919.265443] Oops: 0000 [#1] SMP PTI +[60919.265550] CPU: 30 PID: 3638365 Comm: can_filter Kdump: loaded Tainted: G W 4.19.90+ #1 +[60919.266068] RIP: 0010:selinux_socket_sock_rcv_skb+0x3e/0x200 +[60919.293289] RSP: 0018:ffff8d53bfc03cf8 EFLAGS: 00010246 +[60919.307140] RAX: 0000000000000000 RBX: 000000000000001d RCX: 0000000000000007 +[60919.320756] RDX: 0000000000000001 RSI: ffff8d5104a8ed00 RDI: ffff8d53bfc03d30 +[60919.334319] RBP: ffff8d9338056800 R08: ffff8d53bfc29d80 R09: 0000000000000001 +[60919.347969] R10: ffff8d53bfc03ec0 R11: ffffb8526ef47c98 R12: ffff8d53bfc03d30 +[60919.350320] perf: interrupt took too long (3063 > 2500), lowering kernel.perf_event_max_sample_rate to 65000 +[60919.361148] R13: 0000000000000001 R14: ffff8d53bcf90000 R15: 0000000000000000 +[60919.361151] FS: 00007fb78b6b3600(0000) GS:ffff8d53bfc00000(0000) knlGS:0000000000000000 +[60919.400812] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[60919.413730] CR2: 0000000000000010 CR3: 0000003e3f784006 CR4: 00000000007606e0 +[60919.426479] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +[60919.439339] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 +[60919.451608] PKRU: 55555554 +[60919.463622] Call Trace: +[60919.475617] +[60919.487122] ? update_load_avg+0x89/0x5d0 +[60919.498478] ? update_load_avg+0x89/0x5d0 +[60919.509822] ? account_entity_enqueue+0xc5/0xf0 +[60919.520709] security_sock_rcv_skb+0x2a/0x40 +[60919.531413] sk_filter_trim_cap+0x47/0x1b0 +[60919.542178] ? kmem_cache_alloc+0x38/0x1b0 +[60919.552444] sock_queue_rcv_skb+0x17/0x30 +[60919.562477] raw_rcv+0x110/0x190 [can_raw] +[60919.572539] can_rcv_filter+0xbc/0x1b0 [can] +[60919.582173] can_receive+0x6b/0xb0 [can] +[60919.591595] can_rcv+0x31/0x70 [can] +[60919.600783] __netif_receive_skb_one_core+0x5a/0x80 +[60919.609864] process_backlog+0x9b/0x150 +[60919.618691] net_rx_action+0x156/0x400 +[60919.627310] ? sched_clock_cpu+0xc/0xa0 +[60919.635714] __do_softirq+0xe8/0x2e9 +[60919.644161] do_softirq_own_stack+0x2a/0x40 +[60919.652154] +[60919.659899] do_softirq.part.17+0x4f/0x60 +[60919.667475] __local_bh_enable_ip+0x60/0x70 +[60919.675089] __dev_queue_xmit+0x539/0x920 +[60919.682267] ? finish_wait+0x80/0x80 +[60919.689218] ? finish_wait+0x80/0x80 +[60919.695886] ? sock_alloc_send_pskb+0x211/0x230 +[60919.702395] ? can_send+0xe5/0x1f0 [can] +[60919.708882] can_send+0xe5/0x1f0 [can] +[60919.715037] raw_sendmsg+0x16d/0x268 [can_raw] + +It's because raw_setsockopt() concurrently with +unregister_netdevice_many(). Concurrent scenario as following. + + cpu0 cpu1 +raw_bind +raw_setsockopt unregister_netdevice_many + unlist_netdevice +dev_get_by_index raw_notifier +raw_enable_filters ...... +can_rx_register +can_rcv_list_find(..., net->can.rx_alldev_list) + +...... + +sock_close +raw_release(sock_a) + +...... + +can_receive +can_rcv_filter(net->can.rx_alldev_list, ...) +raw_rcv(skb, sock_a) +BUG + +After unlist_netdevice(), dev_get_by_index() return NULL in +raw_setsockopt(). Function raw_enable_filters() will add sock +and can_filter to net->can.rx_alldev_list. Then the sock is closed. +Followed by, we sock_sendmsg() to a new vcan device use the same +can_filter. Protocol stack match the old receiver whose sock has +been released on net->can.rx_alldev_list in can_rcv_filter(). +Function raw_rcv() uses the freed sock. UAF BUG is triggered. + +We can find that the key issue is that net_device has not been +protected in raw_setsockopt(). Use rtnl_lock to protect net_device +in raw_setsockopt(). + +Fixes: c18ce101f2e4 ("[CAN]: Add raw protocol") +Link: https://lore.kernel.org/r/20210722070819.1048263-1-william.xuanziyang@huawei.com +Cc: linux-stable +Signed-off-by: Ziyang Xuan +Acked-by: Oliver Hartkopp +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Greg Kroah-Hartman +--- + net/can/raw.c | 20 ++++++++++++++++++-- + 1 file changed, 18 insertions(+), 2 deletions(-) + +--- a/net/can/raw.c ++++ b/net/can/raw.c +@@ -549,10 +549,18 @@ static int raw_setsockopt(struct socket + return -EFAULT; + } + ++ rtnl_lock(); + lock_sock(sk); + +- if (ro->bound && ro->ifindex) ++ if (ro->bound && ro->ifindex) { + dev = dev_get_by_index(sock_net(sk), ro->ifindex); ++ if (!dev) { ++ if (count > 1) ++ kfree(filter); ++ err = -ENODEV; ++ goto out_fil; ++ } ++ } + + if (ro->bound) { + /* (try to) register the new filters */ +@@ -591,6 +599,7 @@ static int raw_setsockopt(struct socket + dev_put(dev); + + release_sock(sk); ++ rtnl_unlock(); + + break; + +@@ -603,10 +612,16 @@ static int raw_setsockopt(struct socket + + err_mask &= CAN_ERR_MASK; + ++ rtnl_lock(); + lock_sock(sk); + +- if (ro->bound && ro->ifindex) ++ if (ro->bound && ro->ifindex) { + dev = dev_get_by_index(sock_net(sk), ro->ifindex); ++ if (!dev) { ++ err = -ENODEV; ++ goto out_err; ++ } ++ } + + /* remove current error mask */ + if (ro->bound) { +@@ -630,6 +645,7 @@ static int raw_setsockopt(struct socket + dev_put(dev); + + release_sock(sk); ++ rtnl_unlock(); + + break; + diff --git a/queue-4.14/can-usb_8dev-fix-memory-leak.patch b/queue-4.14/can-usb_8dev-fix-memory-leak.patch new file mode 100644 index 00000000000..a9b97ce1ee3 --- /dev/null +++ b/queue-4.14/can-usb_8dev-fix-memory-leak.patch @@ -0,0 +1,94 @@ +From 0e865f0c31928d6a313269ef624907eec55287c4 Mon Sep 17 00:00:00 2001 +From: Pavel Skripkin +Date: Tue, 27 Jul 2021 19:59:57 +0300 +Subject: can: usb_8dev: fix memory leak + +From: Pavel Skripkin + +commit 0e865f0c31928d6a313269ef624907eec55287c4 upstream. + +In usb_8dev_start() MAX_RX_URBS coherent buffers are allocated and +there is nothing, that frees them: + +1) In callback function the urb is resubmitted and that's all +2) In disconnect function urbs are simply killed, but URB_FREE_BUFFER + is not set (see usb_8dev_start) and this flag cannot be used with + coherent buffers. + +So, all allocated buffers should be freed with usb_free_coherent() +explicitly. + +Side note: This code looks like a copy-paste of other can drivers. The +same patch was applied to mcba_usb driver and it works nice with real +hardware. There is no change in functionality, only clean-up code for +coherent buffers. + +Fixes: 0024d8ad1639 ("can: usb_8dev: Add support for USB2CAN interface from 8 devices") +Link: https://lore.kernel.org/r/d39b458cd425a1cf7f512f340224e6e9563b07bd.1627404470.git.paskripkin@gmail.com +Cc: linux-stable +Signed-off-by: Pavel Skripkin +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/can/usb/usb_8dev.c | 15 +++++++++++++-- + 1 file changed, 13 insertions(+), 2 deletions(-) + +--- a/drivers/net/can/usb/usb_8dev.c ++++ b/drivers/net/can/usb/usb_8dev.c +@@ -148,7 +148,8 @@ struct usb_8dev_priv { + u8 *cmd_msg_buffer; + + struct mutex usb_8dev_cmd_lock; +- ++ void *rxbuf[MAX_RX_URBS]; ++ dma_addr_t rxbuf_dma[MAX_RX_URBS]; + }; + + /* tx frame */ +@@ -744,6 +745,7 @@ static int usb_8dev_start(struct usb_8de + for (i = 0; i < MAX_RX_URBS; i++) { + struct urb *urb = NULL; + u8 *buf; ++ dma_addr_t buf_dma; + + /* create a URB, and a buffer for it */ + urb = usb_alloc_urb(0, GFP_KERNEL); +@@ -753,7 +755,7 @@ static int usb_8dev_start(struct usb_8de + } + + buf = usb_alloc_coherent(priv->udev, RX_BUFFER_SIZE, GFP_KERNEL, +- &urb->transfer_dma); ++ &buf_dma); + if (!buf) { + netdev_err(netdev, "No memory left for USB buffer\n"); + usb_free_urb(urb); +@@ -761,6 +763,8 @@ static int usb_8dev_start(struct usb_8de + break; + } + ++ urb->transfer_dma = buf_dma; ++ + usb_fill_bulk_urb(urb, priv->udev, + usb_rcvbulkpipe(priv->udev, + USB_8DEV_ENDP_DATA_RX), +@@ -778,6 +782,9 @@ static int usb_8dev_start(struct usb_8de + break; + } + ++ priv->rxbuf[i] = buf; ++ priv->rxbuf_dma[i] = buf_dma; ++ + /* Drop reference, USB core will take care of freeing it */ + usb_free_urb(urb); + } +@@ -847,6 +854,10 @@ static void unlink_all_urbs(struct usb_8 + + usb_kill_anchored_urbs(&priv->rx_submitted); + ++ for (i = 0; i < MAX_RX_URBS; ++i) ++ usb_free_coherent(priv->udev, RX_BUFFER_SIZE, ++ priv->rxbuf[i], priv->rxbuf_dma[i]); ++ + usb_kill_anchored_urbs(&priv->tx_submitted); + atomic_set(&priv->active_tx_urbs, 0); + diff --git a/queue-4.14/nfc-nfcsim-fix-use-after-free-during-module-unload.patch b/queue-4.14/nfc-nfcsim-fix-use-after-free-during-module-unload.patch new file mode 100644 index 00000000000..a8915561782 --- /dev/null +++ b/queue-4.14/nfc-nfcsim-fix-use-after-free-during-module-unload.patch @@ -0,0 +1,93 @@ +From 5e7b30d24a5b8cb691c173b45b50e3ca0191be19 Mon Sep 17 00:00:00 2001 +From: Krzysztof Kozlowski +Date: Wed, 28 Jul 2021 08:49:09 +0200 +Subject: nfc: nfcsim: fix use after free during module unload +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Krzysztof Kozlowski + +commit 5e7b30d24a5b8cb691c173b45b50e3ca0191be19 upstream. + +There is a use after free memory corruption during module exit: + - nfcsim_exit() + - nfcsim_device_free(dev0) + - nfc_digital_unregister_device() + This iterates over command queue and frees all commands, + - dev->up = false + - nfcsim_link_shutdown() + - nfcsim_link_recv_wake() + This wakes the sleeping thread nfcsim_link_recv_skb(). + + - nfcsim_link_recv_skb() + Wake from wait_event_interruptible_timeout(), + call directly the deb->cb callback even though (dev->up == false), + - digital_send_cmd_complete() + Dereference of "struct digital_cmd" cmd which was freed earlier by + nfc_digital_unregister_device(). + +This causes memory corruption shortly after (with unrelated stack +trace): + + nfc nfc0: NFC: nfcsim_recv_wq: Device is down + llcp: nfc_llcp_recv: err -19 + nfc nfc1: NFC: nfcsim_recv_wq: Device is down + BUG: unable to handle page fault for address: ffffffffffffffed + Call Trace: + fsnotify+0x54b/0x5c0 + __fsnotify_parent+0x1fe/0x300 + ? vfs_write+0x27c/0x390 + vfs_write+0x27c/0x390 + ksys_write+0x63/0xe0 + do_syscall_64+0x3b/0x90 + entry_SYSCALL_64_after_hwframe+0x44/0xae + +KASAN report: + + BUG: KASAN: use-after-free in digital_send_cmd_complete+0x16/0x50 + Write of size 8 at addr ffff88800a05f720 by task kworker/0:2/71 + Workqueue: events nfcsim_recv_wq [nfcsim] + Call Trace: +  dump_stack_lvl+0x45/0x59 +  print_address_description.constprop.0+0x21/0x140 +  ? digital_send_cmd_complete+0x16/0x50 +  ? digital_send_cmd_complete+0x16/0x50 +  kasan_report.cold+0x7f/0x11b +  ? digital_send_cmd_complete+0x16/0x50 +  ? digital_dep_link_down+0x60/0x60 +  digital_send_cmd_complete+0x16/0x50 +  nfcsim_recv_wq+0x38f/0x3d5 [nfcsim] +  ? nfcsim_in_send_cmd+0x4a/0x4a [nfcsim] +  ? lock_is_held_type+0x98/0x110 +  ? finish_wait+0x110/0x110 +  ? rcu_read_lock_sched_held+0x9c/0xd0 +  ? rcu_read_lock_bh_held+0xb0/0xb0 +  ? lockdep_hardirqs_on_prepare+0x12e/0x1f0 + +This flow of calling digital_send_cmd_complete() callback on driver exit +is specific to nfcsim which implements reading and sending work queues. +Since the NFC digital device was unregistered, the callback should not +be called. + +Fixes: 204bddcb508f ("NFC: nfcsim: Make use of the Digital layer") +Cc: +Signed-off-by: Krzysztof Kozlowski +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nfc/nfcsim.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/drivers/nfc/nfcsim.c ++++ b/drivers/nfc/nfcsim.c +@@ -201,8 +201,7 @@ static void nfcsim_recv_wq(struct work_s + + if (!IS_ERR(skb)) + dev_kfree_skb(skb); +- +- skb = ERR_PTR(-ENODEV); ++ return; + } + + dev->cb(dev->nfc_digital_dev, dev->arg, skb); diff --git a/queue-4.14/niu-fix-incorrect-error-return-missed-in-previous-revert.patch b/queue-4.14/niu-fix-incorrect-error-return-missed-in-previous-revert.patch new file mode 100644 index 00000000000..0cfa456617e --- /dev/null +++ b/queue-4.14/niu-fix-incorrect-error-return-missed-in-previous-revert.patch @@ -0,0 +1,42 @@ +From 15bbf8bb4d4ab87108ecf5f4155ec8ffa3c141d6 Mon Sep 17 00:00:00 2001 +From: Paul Jakma +Date: Fri, 23 Jul 2021 16:13:04 +0100 +Subject: NIU: fix incorrect error return, missed in previous revert + +From: Paul Jakma + +commit 15bbf8bb4d4ab87108ecf5f4155ec8ffa3c141d6 upstream. + +Commit 7930742d6, reverting 26fd962, missed out on reverting an incorrect +change to a return value. The niu_pci_vpd_scan_props(..) == 1 case appears +to be a normal path - treating it as an error and return -EINVAL was +breaking VPD_SCAN and causing the driver to fail to load. + +Fix, so my Neptune card works again. + +Cc: Kangjie Lu +Cc: Shannon Nelson +Cc: David S. Miller +Cc: Greg Kroah-Hartman +Cc: stable +Fixes: 7930742d ('Revert "niu: fix missing checks of niu_pci_eeprom_read"') +Signed-off-by: Paul Jakma +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/sun/niu.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/net/ethernet/sun/niu.c ++++ b/drivers/net/ethernet/sun/niu.c +@@ -8211,8 +8211,9 @@ static int niu_pci_vpd_fetch(struct niu + err = niu_pci_vpd_scan_props(np, here, end); + if (err < 0) + return err; ++ /* ret == 1 is not an error */ + if (err == 1) +- return -EINVAL; ++ return 0; + } + return 0; + } diff --git a/queue-4.14/ocfs2-fix-zero-out-valid-data.patch b/queue-4.14/ocfs2-fix-zero-out-valid-data.patch new file mode 100644 index 00000000000..fea5c7bcc2d --- /dev/null +++ b/queue-4.14/ocfs2-fix-zero-out-valid-data.patch @@ -0,0 +1,60 @@ +From f267aeb6dea5e468793e5b8eb6a9c72c0020d418 Mon Sep 17 00:00:00 2001 +From: Junxiao Bi +Date: Thu, 29 Jul 2021 14:53:38 -0700 +Subject: ocfs2: fix zero out valid data + +From: Junxiao Bi + +commit f267aeb6dea5e468793e5b8eb6a9c72c0020d418 upstream. + +If append-dio feature is enabled, direct-io write and fallocate could +run in parallel to extend file size, fallocate used "orig_isize" to +record i_size before taking "ip_alloc_sem", when +ocfs2_zeroout_partial_cluster() zeroout EOF blocks, i_size maybe already +extended by ocfs2_dio_end_io_write(), that will cause valid data zeroed +out. + +Link: https://lkml.kernel.org/r/20210722054923.24389-1-junxiao.bi@oracle.com +Fixes: 6bba4471f0cc ("ocfs2: fix data corruption by fallocate") +Signed-off-by: Junxiao Bi +Reviewed-by: Joseph Qi +Cc: Changwei Ge +Cc: Gang He +Cc: Joel Becker +Cc: Jun Piao +Cc: Mark Fasheh +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman +--- + fs/ocfs2/file.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/fs/ocfs2/file.c ++++ b/fs/ocfs2/file.c +@@ -1941,7 +1941,6 @@ static int __ocfs2_change_file_space(str + goto out_inode_unlock; + } + +- orig_isize = i_size_read(inode); + switch (sr->l_whence) { + case 0: /*SEEK_SET*/ + break; +@@ -1949,7 +1948,7 @@ static int __ocfs2_change_file_space(str + sr->l_start += f_pos; + break; + case 2: /*SEEK_END*/ +- sr->l_start += orig_isize; ++ sr->l_start += i_size_read(inode); + break; + default: + ret = -EINVAL; +@@ -2004,6 +2003,7 @@ static int __ocfs2_change_file_space(str + ret = -EINVAL; + } + ++ orig_isize = i_size_read(inode); + /* zeroout eof blocks in the cluster. */ + if (!ret && change_size && orig_isize < size) { + ret = ocfs2_zeroout_partial_cluster(inode, orig_isize, diff --git a/queue-4.14/ocfs2-issue-zeroout-to-eof-blocks.patch b/queue-4.14/ocfs2-issue-zeroout-to-eof-blocks.patch new file mode 100644 index 00000000000..ca115937bbc --- /dev/null +++ b/queue-4.14/ocfs2-issue-zeroout-to-eof-blocks.patch @@ -0,0 +1,186 @@ +From 9449ad33be8480f538b11a593e2dda2fb33ca06d Mon Sep 17 00:00:00 2001 +From: Junxiao Bi +Date: Thu, 29 Jul 2021 14:53:41 -0700 +Subject: ocfs2: issue zeroout to EOF blocks + +From: Junxiao Bi + +commit 9449ad33be8480f538b11a593e2dda2fb33ca06d upstream. + +For punch holes in EOF blocks, fallocate used buffer write to zero the +EOF blocks in last cluster. But since ->writepage will ignore EOF +pages, those zeros will not be flushed. + +This "looks" ok as commit 6bba4471f0cc ("ocfs2: fix data corruption by +fallocate") will zero the EOF blocks when extend the file size, but it +isn't. The problem happened on those EOF pages, before writeback, those +pages had DIRTY flag set and all buffer_head in them also had DIRTY flag +set, when writeback run by write_cache_pages(), DIRTY flag on the page +was cleared, but DIRTY flag on the buffer_head not. + +When next write happened to those EOF pages, since buffer_head already +had DIRTY flag set, it would not mark page DIRTY again. That made +writeback ignore them forever. That will cause data corruption. Even +directio write can't work because it will fail when trying to drop pages +caches before direct io, as it found the buffer_head for those pages +still had DIRTY flag set, then it will fall back to buffer io mode. + +To make a summary of the issue, as writeback ingores EOF pages, once any +EOF page is generated, any write to it will only go to the page cache, +it will never be flushed to disk even file size extends and that page is +not EOF page any more. The fix is to avoid zero EOF blocks with buffer +write. + +The following code snippet from qemu-img could trigger the corruption. + + 656 open("6b3711ae-3306-4bdd-823c-cf1c0060a095.conv.2", O_RDWR|O_DIRECT|O_CLOEXEC) = 11 + ... + 660 fallocate(11, FALLOC_FL_KEEP_SIZE|FALLOC_FL_PUNCH_HOLE, 2275868672, 327680 + 660 fallocate(11, 0, 2275868672, 327680) = 0 + 658 pwrite64(11, " + +Link: https://lkml.kernel.org/r/20210722054923.24389-2-junxiao.bi@oracle.com +Signed-off-by: Junxiao Bi +Reviewed-by: Joseph Qi +Cc: Mark Fasheh +Cc: Joel Becker +Cc: Changwei Ge +Cc: Gang He +Cc: Jun Piao +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman +--- + fs/ocfs2/file.c | 99 +++++++++++++++++++++++++++++++++----------------------- + 1 file changed, 60 insertions(+), 39 deletions(-) + +--- a/fs/ocfs2/file.c ++++ b/fs/ocfs2/file.c +@@ -1535,6 +1535,45 @@ static void ocfs2_truncate_cluster_pages + } + } + ++/* ++ * zero out partial blocks of one cluster. ++ * ++ * start: file offset where zero starts, will be made upper block aligned. ++ * len: it will be trimmed to the end of current cluster if "start + len" ++ * is bigger than it. ++ */ ++static int ocfs2_zeroout_partial_cluster(struct inode *inode, ++ u64 start, u64 len) ++{ ++ int ret; ++ u64 start_block, end_block, nr_blocks; ++ u64 p_block, offset; ++ u32 cluster, p_cluster, nr_clusters; ++ struct super_block *sb = inode->i_sb; ++ u64 end = ocfs2_align_bytes_to_clusters(sb, start); ++ ++ if (start + len < end) ++ end = start + len; ++ ++ start_block = ocfs2_blocks_for_bytes(sb, start); ++ end_block = ocfs2_blocks_for_bytes(sb, end); ++ nr_blocks = end_block - start_block; ++ if (!nr_blocks) ++ return 0; ++ ++ cluster = ocfs2_bytes_to_clusters(sb, start); ++ ret = ocfs2_get_clusters(inode, cluster, &p_cluster, ++ &nr_clusters, NULL); ++ if (ret) ++ return ret; ++ if (!p_cluster) ++ return 0; ++ ++ offset = start_block - ocfs2_clusters_to_blocks(sb, cluster); ++ p_block = ocfs2_clusters_to_blocks(sb, p_cluster) + offset; ++ return sb_issue_zeroout(sb, p_block, nr_blocks, GFP_NOFS); ++} ++ + static int ocfs2_zero_partial_clusters(struct inode *inode, + u64 start, u64 len) + { +@@ -1544,6 +1583,7 @@ static int ocfs2_zero_partial_clusters(s + struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); + unsigned int csize = osb->s_clustersize; + handle_t *handle; ++ loff_t isize = i_size_read(inode); + + /* + * The "start" and "end" values are NOT necessarily part of +@@ -1564,6 +1604,26 @@ static int ocfs2_zero_partial_clusters(s + if ((start & (csize - 1)) == 0 && (end & (csize - 1)) == 0) + goto out; + ++ /* No page cache for EOF blocks, issue zero out to disk. */ ++ if (end > isize) { ++ /* ++ * zeroout eof blocks in last cluster starting from ++ * "isize" even "start" > "isize" because it is ++ * complicated to zeroout just at "start" as "start" ++ * may be not aligned with block size, buffer write ++ * would be required to do that, but out of eof buffer ++ * write is not supported. ++ */ ++ ret = ocfs2_zeroout_partial_cluster(inode, isize, ++ end - isize); ++ if (ret) { ++ mlog_errno(ret); ++ goto out; ++ } ++ if (start >= isize) ++ goto out; ++ end = isize; ++ } + handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS); + if (IS_ERR(handle)) { + ret = PTR_ERR(handle); +@@ -1862,45 +1922,6 @@ out: + } + + /* +- * zero out partial blocks of one cluster. +- * +- * start: file offset where zero starts, will be made upper block aligned. +- * len: it will be trimmed to the end of current cluster if "start + len" +- * is bigger than it. +- */ +-static int ocfs2_zeroout_partial_cluster(struct inode *inode, +- u64 start, u64 len) +-{ +- int ret; +- u64 start_block, end_block, nr_blocks; +- u64 p_block, offset; +- u32 cluster, p_cluster, nr_clusters; +- struct super_block *sb = inode->i_sb; +- u64 end = ocfs2_align_bytes_to_clusters(sb, start); +- +- if (start + len < end) +- end = start + len; +- +- start_block = ocfs2_blocks_for_bytes(sb, start); +- end_block = ocfs2_blocks_for_bytes(sb, end); +- nr_blocks = end_block - start_block; +- if (!nr_blocks) +- return 0; +- +- cluster = ocfs2_bytes_to_clusters(sb, start); +- ret = ocfs2_get_clusters(inode, cluster, &p_cluster, +- &nr_clusters, NULL); +- if (ret) +- return ret; +- if (!p_cluster) +- return 0; +- +- offset = start_block - ocfs2_clusters_to_blocks(sb, cluster); +- p_block = ocfs2_clusters_to_blocks(sb, p_cluster) + offset; +- return sb_issue_zeroout(sb, p_block, nr_blocks, GFP_NOFS); +-} +- +-/* + * Parts of this function taken from xfs_change_file_space() + */ + static int __ocfs2_change_file_space(struct file *file, struct inode *inode, diff --git a/queue-4.14/series b/queue-4.14/series index 0293a9b7205..f3f2c4acd78 100644 --- a/queue-4.14/series +++ b/queue-4.14/series @@ -13,4 +13,14 @@ hfs-add-lock-nesting-notation-to-hfs_find_init.patch arm-dts-versatile-fix-up-interrupt-controller-node-n.patch virtio_net-do-not-pull-payload-in-skb-head.patch gro-ensure-frag0-meets-ip-header-alignment.patch +x86-kvm-fix-vcpu-id-indexed-array-sizes.patch +ocfs2-fix-zero-out-valid-data.patch +ocfs2-issue-zeroout-to-eof-blocks.patch +can-raw-raw_setsockopt-fix-raw_rcv-panic-for-sock-uaf.patch +can-mcba_usb_start-add-missing-urb-transfer_dma-initialization.patch +can-usb_8dev-fix-memory-leak.patch +can-ems_usb-fix-memory-leak.patch +can-esd_usb2-fix-memory-leak.patch +niu-fix-incorrect-error-return-missed-in-previous-revert.patch +nfc-nfcsim-fix-use-after-free-during-module-unload.patch x86-asm-ensure-asm-proto.h-can-be-included-stand-alo.patch diff --git a/queue-4.14/x86-kvm-fix-vcpu-id-indexed-array-sizes.patch b/queue-4.14/x86-kvm-fix-vcpu-id-indexed-array-sizes.patch new file mode 100644 index 00000000000..e3847db36a0 --- /dev/null +++ b/queue-4.14/x86-kvm-fix-vcpu-id-indexed-array-sizes.patch @@ -0,0 +1,59 @@ +From 76b4f357d0e7d8f6f0013c733e6cba1773c266d3 Mon Sep 17 00:00:00 2001 +From: Juergen Gross +Date: Thu, 1 Jul 2021 17:41:00 +0200 +Subject: x86/kvm: fix vcpu-id indexed array sizes + +From: Juergen Gross + +commit 76b4f357d0e7d8f6f0013c733e6cba1773c266d3 upstream. + +KVM_MAX_VCPU_ID is the maximum vcpu-id of a guest, and not the number +of vcpu-ids. Fix array indexed by vcpu-id to have KVM_MAX_VCPU_ID+1 +elements. + +Note that this is currently no real problem, as KVM_MAX_VCPU_ID is +an odd number, resulting in always enough padding being available at +the end of those arrays. + +Nevertheless this should be fixed in order to avoid rare problems in +case someone is using an even number for KVM_MAX_VCPU_ID. + +Signed-off-by: Juergen Gross +Message-Id: <20210701154105.23215-2-jgross@suse.com> +Cc: stable@vger.kernel.org +Signed-off-by: Paolo Bonzini +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kvm/ioapic.c | 2 +- + arch/x86/kvm/ioapic.h | 4 ++-- + 2 files changed, 3 insertions(+), 3 deletions(-) + +--- a/arch/x86/kvm/ioapic.c ++++ b/arch/x86/kvm/ioapic.c +@@ -96,7 +96,7 @@ static unsigned long ioapic_read_indirec + static void rtc_irq_eoi_tracking_reset(struct kvm_ioapic *ioapic) + { + ioapic->rtc_status.pending_eoi = 0; +- bitmap_zero(ioapic->rtc_status.dest_map.map, KVM_MAX_VCPU_ID); ++ bitmap_zero(ioapic->rtc_status.dest_map.map, KVM_MAX_VCPU_ID + 1); + } + + static void kvm_rtc_eoi_tracking_restore_all(struct kvm_ioapic *ioapic); +--- a/arch/x86/kvm/ioapic.h ++++ b/arch/x86/kvm/ioapic.h +@@ -43,13 +43,13 @@ struct kvm_vcpu; + + struct dest_map { + /* vcpu bitmap where IRQ has been sent */ +- DECLARE_BITMAP(map, KVM_MAX_VCPU_ID); ++ DECLARE_BITMAP(map, KVM_MAX_VCPU_ID + 1); + + /* + * Vector sent to a given vcpu, only valid when + * the vcpu's bit in map is set + */ +- u8 vectors[KVM_MAX_VCPU_ID]; ++ u8 vectors[KVM_MAX_VCPU_ID + 1]; + }; + +