From: Sasha Levin Date: Sun, 15 Aug 2021 12:53:00 +0000 (-0400) Subject: Fixes for 4.4 X-Git-Tag: v5.4.142~46^2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=f5c46942b867d77127a14d22361aed2f65de0cdb;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 4.4 Signed-off-by: Sasha Levin --- diff --git a/queue-4.4/net-fix-memory-leak-in-ieee802154_raw_deliver.patch b/queue-4.4/net-fix-memory-leak-in-ieee802154_raw_deliver.patch new file mode 100644 index 00000000000..98142b54d63 --- /dev/null +++ b/queue-4.4/net-fix-memory-leak-in-ieee802154_raw_deliver.patch @@ -0,0 +1,87 @@ +From 2a0973ae2daa737b7d55eee7b23f98cfd4f01665 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 5 Aug 2021 16:54:14 +0900 +Subject: net: Fix memory leak in ieee802154_raw_deliver + +From: Takeshi Misawa + +[ Upstream commit 1090340f7ee53e824fd4eef66a4855d548110c5b ] + +If IEEE-802.15.4-RAW is closed before receive skb, skb is leaked. +Fix this, by freeing sk_receive_queue in sk->sk_destruct(). + +syzbot report: +BUG: memory leak +unreferenced object 0xffff88810f644600 (size 232): + comm "softirq", pid 0, jiffies 4294967032 (age 81.270s) + hex dump (first 32 bytes): + 10 7d 4b 12 81 88 ff ff 10 7d 4b 12 81 88 ff ff .}K......}K..... + 00 00 00 00 00 00 00 00 40 7c 4b 12 81 88 ff ff ........@|K..... + backtrace: + [] skb_clone+0xaa/0x2b0 net/core/skbuff.c:1496 + [] ieee802154_raw_deliver net/ieee802154/socket.c:369 [inline] + [] ieee802154_rcv+0x100/0x340 net/ieee802154/socket.c:1070 + [] __netif_receive_skb_one_core+0x6a/0xa0 net/core/dev.c:5384 + [] __netif_receive_skb+0x27/0xa0 net/core/dev.c:5498 + [] netif_receive_skb_internal net/core/dev.c:5603 [inline] + [] netif_receive_skb+0x59/0x260 net/core/dev.c:5662 + [] ieee802154_deliver_skb net/mac802154/rx.c:29 [inline] + [] ieee802154_subif_frame net/mac802154/rx.c:102 [inline] + [] __ieee802154_rx_handle_packet net/mac802154/rx.c:212 [inline] + [] ieee802154_rx+0x612/0x620 net/mac802154/rx.c:284 + [] ieee802154_tasklet_handler+0x86/0xa0 net/mac802154/main.c:35 + [] tasklet_action_common.constprop.0+0x5b/0x100 kernel/softirq.c:557 + [] __do_softirq+0xbf/0x2ab kernel/softirq.c:345 + [] do_softirq kernel/softirq.c:248 [inline] + [] do_softirq+0x5c/0x80 kernel/softirq.c:235 + [] __local_bh_enable_ip+0x51/0x60 kernel/softirq.c:198 + [] local_bh_enable include/linux/bottom_half.h:32 [inline] + [] rcu_read_unlock_bh include/linux/rcupdate.h:745 [inline] + [] __dev_queue_xmit+0x7f4/0xf60 net/core/dev.c:4221 + [] raw_sendmsg+0x1f4/0x2b0 net/ieee802154/socket.c:295 + [] sock_sendmsg_nosec net/socket.c:654 [inline] + [] sock_sendmsg+0x56/0x80 net/socket.c:674 + [] __sys_sendto+0x15c/0x200 net/socket.c:1977 + [] __do_sys_sendto net/socket.c:1989 [inline] + [] __se_sys_sendto net/socket.c:1985 [inline] + [] __x64_sys_sendto+0x26/0x30 net/socket.c:1985 + +Fixes: 9ec767160357 ("net: add IEEE 802.15.4 socket family implementation") +Reported-and-tested-by: syzbot+1f68113fa907bf0695a8@syzkaller.appspotmail.com +Signed-off-by: Takeshi Misawa +Acked-by: Alexander Aring +Link: https://lore.kernel.org/r/20210805075414.GA15796@DESKTOP +Signed-off-by: Stefan Schmidt +Signed-off-by: Sasha Levin +--- + net/ieee802154/socket.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/net/ieee802154/socket.c b/net/ieee802154/socket.c +index cb6c0772ea36..42ab1b61b513 100644 +--- a/net/ieee802154/socket.c ++++ b/net/ieee802154/socket.c +@@ -983,6 +983,11 @@ static const struct proto_ops ieee802154_dgram_ops = { + #endif + }; + ++static void ieee802154_sock_destruct(struct sock *sk) ++{ ++ skb_queue_purge(&sk->sk_receive_queue); ++} ++ + /* Create a socket. Initialise the socket, blank the addresses + * set the state. + */ +@@ -1023,7 +1028,7 @@ static int ieee802154_create(struct net *net, struct socket *sock, + sock->ops = ops; + + sock_init_data(sock, sk); +- /* FIXME: sk->sk_destruct */ ++ sk->sk_destruct = ieee802154_sock_destruct; + sk->sk_family = PF_IEEE802154; + + /* Checksums on by default */ +-- +2.30.2 + diff --git a/queue-4.4/series b/queue-4.4/series index 67e40efb29d..c9df19a755f 100644 --- a/queue-4.4/series +++ b/queue-4.4/series @@ -1,2 +1,4 @@ asoc-intel-atom-fix-reference-to-pcm-buffer-address.patch i2c-dev-zero-out-array-used-for-i2c-reads-from-userspace.patch +net-fix-memory-leak-in-ieee802154_raw_deliver.patch +xen-events-fix-race-in-set_evtchn_to_irq.patch diff --git a/queue-4.4/xen-events-fix-race-in-set_evtchn_to_irq.patch b/queue-4.4/xen-events-fix-race-in-set_evtchn_to_irq.patch new file mode 100644 index 00000000000..bda99add931 --- /dev/null +++ b/queue-4.4/xen-events-fix-race-in-set_evtchn_to_irq.patch @@ -0,0 +1,127 @@ +From e0b0360acf4decc0eb3d12970cbc81d54643a7c6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 12 Aug 2021 13:09:27 +0000 +Subject: xen/events: Fix race in set_evtchn_to_irq + +From: Maximilian Heyne + +[ Upstream commit 88ca2521bd5b4e8b83743c01a2d4cb09325b51e9 ] + +There is a TOCTOU issue in set_evtchn_to_irq. Rows in the evtchn_to_irq +mapping are lazily allocated in this function. The check whether the row +is already present and the row initialization is not synchronized. Two +threads can at the same time allocate a new row for evtchn_to_irq and +add the irq mapping to the their newly allocated row. One thread will +overwrite what the other has set for evtchn_to_irq[row] and therefore +the irq mapping is lost. This will trigger a BUG_ON later in +bind_evtchn_to_cpu: + + INFO: pci 0000:1a:15.4: [1d0f:8061] type 00 class 0x010802 + INFO: nvme 0000:1a:12.1: enabling device (0000 -> 0002) + INFO: nvme nvme77: 1/0/0 default/read/poll queues + CRIT: kernel BUG at drivers/xen/events/events_base.c:427! + WARN: invalid opcode: 0000 [#1] SMP NOPTI + WARN: Workqueue: nvme-reset-wq nvme_reset_work [nvme] + WARN: RIP: e030:bind_evtchn_to_cpu+0xc2/0xd0 + WARN: Call Trace: + WARN: set_affinity_irq+0x121/0x150 + WARN: irq_do_set_affinity+0x37/0xe0 + WARN: irq_setup_affinity+0xf6/0x170 + WARN: irq_startup+0x64/0xe0 + WARN: __setup_irq+0x69e/0x740 + WARN: ? request_threaded_irq+0xad/0x160 + WARN: request_threaded_irq+0xf5/0x160 + WARN: ? nvme_timeout+0x2f0/0x2f0 [nvme] + WARN: pci_request_irq+0xa9/0xf0 + WARN: ? pci_alloc_irq_vectors_affinity+0xbb/0x130 + WARN: queue_request_irq+0x4c/0x70 [nvme] + WARN: nvme_reset_work+0x82d/0x1550 [nvme] + WARN: ? check_preempt_wakeup+0x14f/0x230 + WARN: ? check_preempt_curr+0x29/0x80 + WARN: ? nvme_irq_check+0x30/0x30 [nvme] + WARN: process_one_work+0x18e/0x3c0 + WARN: worker_thread+0x30/0x3a0 + WARN: ? process_one_work+0x3c0/0x3c0 + WARN: kthread+0x113/0x130 + WARN: ? kthread_park+0x90/0x90 + WARN: ret_from_fork+0x3a/0x50 + +This patch sets evtchn_to_irq rows via a cmpxchg operation so that they +will be set only once. The row is now cleared before writing it to +evtchn_to_irq in order to not create a race once the row is visible for +other threads. + +While at it, do not require the page to be zeroed, because it will be +overwritten with -1's in clear_evtchn_to_irq_row anyway. + +Signed-off-by: Maximilian Heyne +Fixes: d0b075ffeede ("xen/events: Refactor evtchn_to_irq array to be dynamically allocated") +Link: https://lore.kernel.org/r/20210812130930.127134-1-mheyne@amazon.de +Reviewed-by: Boris Ostrovsky +Signed-off-by: Boris Ostrovsky +Signed-off-by: Sasha Levin +--- + drivers/xen/events/events_base.c | 20 ++++++++++++++------ + 1 file changed, 14 insertions(+), 6 deletions(-) + +diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c +index f27118923390..0c5b187dc7a0 100644 +--- a/drivers/xen/events/events_base.c ++++ b/drivers/xen/events/events_base.c +@@ -134,12 +134,12 @@ static void disable_dynirq(struct irq_data *data); + + static DEFINE_PER_CPU(unsigned int, irq_epoch); + +-static void clear_evtchn_to_irq_row(unsigned row) ++static void clear_evtchn_to_irq_row(int *evtchn_row) + { + unsigned col; + + for (col = 0; col < EVTCHN_PER_ROW; col++) +- WRITE_ONCE(evtchn_to_irq[row][col], -1); ++ WRITE_ONCE(evtchn_row[col], -1); + } + + static void clear_evtchn_to_irq_all(void) +@@ -149,7 +149,7 @@ static void clear_evtchn_to_irq_all(void) + for (row = 0; row < EVTCHN_ROW(xen_evtchn_max_channels()); row++) { + if (evtchn_to_irq[row] == NULL) + continue; +- clear_evtchn_to_irq_row(row); ++ clear_evtchn_to_irq_row(evtchn_to_irq[row]); + } + } + +@@ -157,6 +157,7 @@ static int set_evtchn_to_irq(unsigned evtchn, unsigned irq) + { + unsigned row; + unsigned col; ++ int *evtchn_row; + + if (evtchn >= xen_evtchn_max_channels()) + return -EINVAL; +@@ -169,11 +170,18 @@ static int set_evtchn_to_irq(unsigned evtchn, unsigned irq) + if (irq == -1) + return 0; + +- evtchn_to_irq[row] = (int *)get_zeroed_page(GFP_KERNEL); +- if (evtchn_to_irq[row] == NULL) ++ evtchn_row = (int *) __get_free_pages(GFP_KERNEL, 0); ++ if (evtchn_row == NULL) + return -ENOMEM; + +- clear_evtchn_to_irq_row(row); ++ clear_evtchn_to_irq_row(evtchn_row); ++ ++ /* ++ * We've prepared an empty row for the mapping. If a different ++ * thread was faster inserting it, we can drop ours. ++ */ ++ if (cmpxchg(&evtchn_to_irq[row], NULL, evtchn_row) != NULL) ++ free_page((unsigned long) evtchn_row); + } + + WRITE_ONCE(evtchn_to_irq[row][col], irq); +-- +2.30.2 +