From: Sasha Levin Date: Mon, 25 Sep 2023 11:23:31 +0000 (-0400) Subject: Fixes for 6.5 X-Git-Tag: v6.5.6~97 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=affdb08cbf339b06f38e9bb317f3fc2de7e9aa3b;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 6.5 Signed-off-by: Sasha Levin --- diff --git a/queue-6.5/cifs-fix-uaf-in-cifs_demultiplex_thread.patch b/queue-6.5/cifs-fix-uaf-in-cifs_demultiplex_thread.patch new file mode 100644 index 00000000000..4be898a5b7f --- /dev/null +++ b/queue-6.5/cifs-fix-uaf-in-cifs_demultiplex_thread.patch @@ -0,0 +1,252 @@ +From 7a9d56e6777413b65bf6d5e02ab222768f1448f7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 19 Sep 2023 13:38:04 -0500 +Subject: cifs: Fix UAF in cifs_demultiplex_thread() + +From: Zhang Xiaoxu + +[ Upstream commit d527f51331cace562393a8038d870b3e9916686f ] + +There is a UAF when xfstests on cifs: + + BUG: KASAN: use-after-free in smb2_is_network_name_deleted+0x27/0x160 + Read of size 4 at addr ffff88810103fc08 by task cifsd/923 + + CPU: 1 PID: 923 Comm: cifsd Not tainted 6.1.0-rc4+ #45 + ... + Call Trace: + + dump_stack_lvl+0x34/0x44 + print_report+0x171/0x472 + kasan_report+0xad/0x130 + kasan_check_range+0x145/0x1a0 + smb2_is_network_name_deleted+0x27/0x160 + cifs_demultiplex_thread.cold+0x172/0x5a4 + kthread+0x165/0x1a0 + ret_from_fork+0x1f/0x30 + + + Allocated by task 923: + kasan_save_stack+0x1e/0x40 + kasan_set_track+0x21/0x30 + __kasan_slab_alloc+0x54/0x60 + kmem_cache_alloc+0x147/0x320 + mempool_alloc+0xe1/0x260 + cifs_small_buf_get+0x24/0x60 + allocate_buffers+0xa1/0x1c0 + cifs_demultiplex_thread+0x199/0x10d0 + kthread+0x165/0x1a0 + ret_from_fork+0x1f/0x30 + + Freed by task 921: + kasan_save_stack+0x1e/0x40 + kasan_set_track+0x21/0x30 + kasan_save_free_info+0x2a/0x40 + ____kasan_slab_free+0x143/0x1b0 + kmem_cache_free+0xe3/0x4d0 + cifs_small_buf_release+0x29/0x90 + SMB2_negotiate+0x8b7/0x1c60 + smb2_negotiate+0x51/0x70 + cifs_negotiate_protocol+0xf0/0x160 + cifs_get_smb_ses+0x5fa/0x13c0 + mount_get_conns+0x7a/0x750 + cifs_mount+0x103/0xd00 + cifs_smb3_do_mount+0x1dd/0xcb0 + smb3_get_tree+0x1d5/0x300 + vfs_get_tree+0x41/0xf0 + path_mount+0x9b3/0xdd0 + __x64_sys_mount+0x190/0x1d0 + do_syscall_64+0x35/0x80 + entry_SYSCALL_64_after_hwframe+0x46/0xb0 + +The UAF is because: + + mount(pid: 921) | cifsd(pid: 923) +-------------------------------|------------------------------- + | cifs_demultiplex_thread +SMB2_negotiate | + cifs_send_recv | + compound_send_recv | + smb_send_rqst | + wait_for_response | + wait_event_state [1] | + | standard_receive3 + | cifs_handle_standard + | handle_mid + | mid->resp_buf = buf; [2] + | dequeue_mid [3] + KILL the process [4] | + resp_iov[i].iov_base = buf | + free_rsp_buf [5] | + | is_network_name_deleted [6] + | callback + +1. After send request to server, wait the response until + mid->mid_state != SUBMITTED; +2. Receive response from server, and set it to mid; +3. Set the mid state to RECEIVED; +4. Kill the process, the mid state already RECEIVED, get 0; +5. Handle and release the negotiate response; +6. UAF. + +It can be easily reproduce with add some delay in [3] - [6]. + +Only sync call has the problem since async call's callback is +executed in cifsd process. + +Add an extra state to mark the mid state to READY before wakeup the +waitter, then it can get the resp safely. + +Fixes: ec637e3ffb6b ("[CIFS] Avoid extra large buffer allocation (and memcpy) in cifs_readpages") +Reviewed-by: Paulo Alcantara (SUSE) +Signed-off-by: Zhang Xiaoxu +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/client/cifsglob.h | 1 + + fs/smb/client/transport.c | 34 +++++++++++++++++++++++----------- + 2 files changed, 24 insertions(+), 11 deletions(-) + +diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h +index 051f15b9d6078..35782a6bede0b 100644 +--- a/fs/smb/client/cifsglob.h ++++ b/fs/smb/client/cifsglob.h +@@ -1776,6 +1776,7 @@ static inline bool is_retryable_error(int error) + #define MID_RETRY_NEEDED 8 /* session closed while this request out */ + #define MID_RESPONSE_MALFORMED 0x10 + #define MID_SHUTDOWN 0x20 ++#define MID_RESPONSE_READY 0x40 /* ready for other process handle the rsp */ + + /* Flags */ + #define MID_WAIT_CANCELLED 1 /* Cancelled while waiting for response */ +diff --git a/fs/smb/client/transport.c b/fs/smb/client/transport.c +index f280502a2aee8..2b9a2ed45a652 100644 +--- a/fs/smb/client/transport.c ++++ b/fs/smb/client/transport.c +@@ -35,6 +35,8 @@ + void + cifs_wake_up_task(struct mid_q_entry *mid) + { ++ if (mid->mid_state == MID_RESPONSE_RECEIVED) ++ mid->mid_state = MID_RESPONSE_READY; + wake_up_process(mid->callback_data); + } + +@@ -87,7 +89,8 @@ static void __release_mid(struct kref *refcount) + struct TCP_Server_Info *server = midEntry->server; + + if (midEntry->resp_buf && (midEntry->mid_flags & MID_WAIT_CANCELLED) && +- midEntry->mid_state == MID_RESPONSE_RECEIVED && ++ (midEntry->mid_state == MID_RESPONSE_RECEIVED || ++ midEntry->mid_state == MID_RESPONSE_READY) && + server->ops->handle_cancelled_mid) + server->ops->handle_cancelled_mid(midEntry, server); + +@@ -732,7 +735,8 @@ wait_for_response(struct TCP_Server_Info *server, struct mid_q_entry *midQ) + int error; + + error = wait_event_state(server->response_q, +- midQ->mid_state != MID_REQUEST_SUBMITTED, ++ midQ->mid_state != MID_REQUEST_SUBMITTED && ++ midQ->mid_state != MID_RESPONSE_RECEIVED, + (TASK_KILLABLE|TASK_FREEZABLE_UNSAFE)); + if (error < 0) + return -ERESTARTSYS; +@@ -885,7 +889,7 @@ cifs_sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server) + + spin_lock(&server->mid_lock); + switch (mid->mid_state) { +- case MID_RESPONSE_RECEIVED: ++ case MID_RESPONSE_READY: + spin_unlock(&server->mid_lock); + return rc; + case MID_RETRY_NEEDED: +@@ -984,6 +988,9 @@ cifs_compound_callback(struct mid_q_entry *mid) + credits.instance = server->reconnect_instance; + + add_credits(server, &credits, mid->optype); ++ ++ if (mid->mid_state == MID_RESPONSE_RECEIVED) ++ mid->mid_state = MID_RESPONSE_READY; + } + + static void +@@ -1204,7 +1211,8 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses, + send_cancel(server, &rqst[i], midQ[i]); + spin_lock(&server->mid_lock); + midQ[i]->mid_flags |= MID_WAIT_CANCELLED; +- if (midQ[i]->mid_state == MID_REQUEST_SUBMITTED) { ++ if (midQ[i]->mid_state == MID_REQUEST_SUBMITTED || ++ midQ[i]->mid_state == MID_RESPONSE_RECEIVED) { + midQ[i]->callback = cifs_cancelled_callback; + cancelled_mid[i] = true; + credits[i].value = 0; +@@ -1225,7 +1233,7 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses, + } + + if (!midQ[i]->resp_buf || +- midQ[i]->mid_state != MID_RESPONSE_RECEIVED) { ++ midQ[i]->mid_state != MID_RESPONSE_READY) { + rc = -EIO; + cifs_dbg(FYI, "Bad MID state?\n"); + goto out; +@@ -1412,7 +1420,8 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses, + if (rc != 0) { + send_cancel(server, &rqst, midQ); + spin_lock(&server->mid_lock); +- if (midQ->mid_state == MID_REQUEST_SUBMITTED) { ++ if (midQ->mid_state == MID_REQUEST_SUBMITTED || ++ midQ->mid_state == MID_RESPONSE_RECEIVED) { + /* no longer considered to be "in-flight" */ + midQ->callback = release_mid; + spin_unlock(&server->mid_lock); +@@ -1429,7 +1438,7 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses, + } + + if (!midQ->resp_buf || !out_buf || +- midQ->mid_state != MID_RESPONSE_RECEIVED) { ++ midQ->mid_state != MID_RESPONSE_READY) { + rc = -EIO; + cifs_server_dbg(VFS, "Bad MID state?\n"); + goto out; +@@ -1553,14 +1562,16 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon, + + /* Wait for a reply - allow signals to interrupt. */ + rc = wait_event_interruptible(server->response_q, +- (!(midQ->mid_state == MID_REQUEST_SUBMITTED)) || ++ (!(midQ->mid_state == MID_REQUEST_SUBMITTED || ++ midQ->mid_state == MID_RESPONSE_RECEIVED)) || + ((server->tcpStatus != CifsGood) && + (server->tcpStatus != CifsNew))); + + /* Were we interrupted by a signal ? */ + spin_lock(&server->srv_lock); + if ((rc == -ERESTARTSYS) && +- (midQ->mid_state == MID_REQUEST_SUBMITTED) && ++ (midQ->mid_state == MID_REQUEST_SUBMITTED || ++ midQ->mid_state == MID_RESPONSE_RECEIVED) && + ((server->tcpStatus == CifsGood) || + (server->tcpStatus == CifsNew))) { + spin_unlock(&server->srv_lock); +@@ -1591,7 +1602,8 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon, + if (rc) { + send_cancel(server, &rqst, midQ); + spin_lock(&server->mid_lock); +- if (midQ->mid_state == MID_REQUEST_SUBMITTED) { ++ if (midQ->mid_state == MID_REQUEST_SUBMITTED || ++ midQ->mid_state == MID_RESPONSE_RECEIVED) { + /* no longer considered to be "in-flight" */ + midQ->callback = release_mid; + spin_unlock(&server->mid_lock); +@@ -1611,7 +1623,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon, + return rc; + + /* rcvd frame is ok */ +- if (out_buf == NULL || midQ->mid_state != MID_RESPONSE_RECEIVED) { ++ if (out_buf == NULL || midQ->mid_state != MID_RESPONSE_READY) { + rc = -EIO; + cifs_tcon_dbg(VFS, "Bad MID state?\n"); + goto out; +-- +2.40.1 + diff --git a/queue-6.5/cxl-region-match-auto-discovered-region-decoders-by-.patch b/queue-6.5/cxl-region-match-auto-discovered-region-decoders-by-.patch new file mode 100644 index 00000000000..6145d45ad9f --- /dev/null +++ b/queue-6.5/cxl-region-match-auto-discovered-region-decoders-by-.patch @@ -0,0 +1,87 @@ +From df4fa23ff13cda36c7c13862ef87004624d16027 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 5 Sep 2023 14:10:07 -0700 +Subject: cxl/region: Match auto-discovered region decoders by HPA range + +From: Alison Schofield + +[ Upstream commit 9e4edf1a2196fa4bea6e8201f166785bd066446a ] + +Currently, when the region driver attaches a region to a port, it +selects the ports next available decoder to program. + +With the addition of auto-discovered regions, a port decoder has +already been programmed so grabbing the next available decoder can +be a mismatch when there is more than one region using the port. + +The failure appears like this with CXL DEBUG enabled: + +[] cxl_core:alloc_region_ref:754: cxl region0: endpoint9: HPA order violation region0:[mem 0x14780000000-0x1478fffffff flags 0x200] vs [mem 0x880000000-0x185fffffff flags 0x200] +[] cxl_core:cxl_port_attach_region:972: cxl region0: endpoint9: failed to allocate region reference + +When CXL DEBUG is not enabled, there is no failure message. The region +just never materializes. Users can suspect this issue if they know their +firmware has programmed decoders so that more than one region is using +a port. Note that the problem may appear intermittently, ie not on +every reboot. + +Add a matching method for auto-discovered regions that finds a decoder +based on an HPA range. The decoder range must exactly match the region +resource parameter. + +Fixes: a32320b71f08 ("cxl/region: Add region autodiscovery") +Signed-off-by: Alison Schofield +Reviewed-by: Dave Jiang +Reviewed-by: Davidlohr Bueso +Reviewed-by: Jonathan Cameron +Link: https://lore.kernel.org/r/20230905211007.256385-1-alison.schofield@intel.com +Signed-off-by: Dan Williams +Signed-off-by: Sasha Levin +--- + drivers/cxl/core/region.c | 24 +++++++++++++++++++++++- + 1 file changed, 23 insertions(+), 1 deletion(-) + +diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c +index e115ba382e044..b4c6a749406f1 100644 +--- a/drivers/cxl/core/region.c ++++ b/drivers/cxl/core/region.c +@@ -717,13 +717,35 @@ static int match_free_decoder(struct device *dev, void *data) + return 0; + } + ++static int match_auto_decoder(struct device *dev, void *data) ++{ ++ struct cxl_region_params *p = data; ++ struct cxl_decoder *cxld; ++ struct range *r; ++ ++ if (!is_switch_decoder(dev)) ++ return 0; ++ ++ cxld = to_cxl_decoder(dev); ++ r = &cxld->hpa_range; ++ ++ if (p->res && p->res->start == r->start && p->res->end == r->end) ++ return 1; ++ ++ return 0; ++} ++ + static struct cxl_decoder *cxl_region_find_decoder(struct cxl_port *port, + struct cxl_region *cxlr) + { + struct device *dev; + int id = 0; + +- dev = device_find_child(&port->dev, &id, match_free_decoder); ++ if (test_bit(CXL_REGION_F_AUTO, &cxlr->flags)) ++ dev = device_find_child(&port->dev, &cxlr->params, ++ match_auto_decoder); ++ else ++ dev = device_find_child(&port->dev, &id, match_free_decoder); + if (!dev) + return NULL; + /* +-- +2.40.1 + diff --git a/queue-6.5/gpio-tb10x-fix-an-error-handling-path-in-tb10x_gpio_.patch b/queue-6.5/gpio-tb10x-fix-an-error-handling-path-in-tb10x_gpio_.patch new file mode 100644 index 00000000000..f64f0569fc0 --- /dev/null +++ b/queue-6.5/gpio-tb10x-fix-an-error-handling-path-in-tb10x_gpio_.patch @@ -0,0 +1,48 @@ +From cd014ab404fd98c80d38b3f44a7f0a4b201151e8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 3 Sep 2023 08:13:21 +0200 +Subject: gpio: tb10x: Fix an error handling path in tb10x_gpio_probe() + +From: Christophe JAILLET + +[ Upstream commit b547b5e52a0587e6b25ea520bf2f9e03d00cbcb6 ] + +If an error occurs after a successful irq_domain_add_linear() call, it +should be undone by a corresponding irq_domain_remove(), as already done +in the remove function. + +Fixes: c6ce2b6bffe5 ("gpio: add TB10x GPIO driver") +Signed-off-by: Christophe JAILLET +Signed-off-by: Bartosz Golaszewski +Signed-off-by: Sasha Levin +--- + drivers/gpio/gpio-tb10x.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpio/gpio-tb10x.c b/drivers/gpio/gpio-tb10x.c +index 78f8790168ae1..f96d260a4a19d 100644 +--- a/drivers/gpio/gpio-tb10x.c ++++ b/drivers/gpio/gpio-tb10x.c +@@ -195,7 +195,7 @@ static int tb10x_gpio_probe(struct platform_device *pdev) + handle_edge_irq, IRQ_NOREQUEST, IRQ_NOPROBE, + IRQ_GC_INIT_MASK_CACHE); + if (ret) +- return ret; ++ goto err_remove_domain; + + gc = tb10x_gpio->domain->gc->gc[0]; + gc->reg_base = tb10x_gpio->base; +@@ -209,6 +209,10 @@ static int tb10x_gpio_probe(struct platform_device *pdev) + } + + return 0; ++ ++err_remove_domain: ++ irq_domain_remove(tb10x_gpio->domain); ++ return ret; + } + + static int tb10x_gpio_remove(struct platform_device *pdev) +-- +2.40.1 + diff --git a/queue-6.5/i2c-mux-demux-pinctrl-check-the-return-value-of-devm.patch b/queue-6.5/i2c-mux-demux-pinctrl-check-the-return-value-of-devm.patch new file mode 100644 index 00000000000..520f857232a --- /dev/null +++ b/queue-6.5/i2c-mux-demux-pinctrl-check-the-return-value-of-devm.patch @@ -0,0 +1,38 @@ +From 18b13f4d5432152221cc92451daf2370c3725888 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 3 Mar 2022 20:39:14 +0800 +Subject: i2c: mux: demux-pinctrl: check the return value of devm_kstrdup() + +From: Xiaoke Wang + +[ Upstream commit 7c0195fa9a9e263df204963f88a22b21688ffb66 ] + +devm_kstrdup() returns pointer to allocated string on success, +NULL on failure. So it is better to check the return value of it. + +Fixes: e35478eac030 ("i2c: mux: demux-pinctrl: run properly with multiple instances") +Signed-off-by: Xiaoke Wang +Signed-off-by: Wolfram Sang +Signed-off-by: Sasha Levin +--- + drivers/i2c/muxes/i2c-demux-pinctrl.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/i2c/muxes/i2c-demux-pinctrl.c b/drivers/i2c/muxes/i2c-demux-pinctrl.c +index a3a122fae71e0..22f2280eab7f7 100644 +--- a/drivers/i2c/muxes/i2c-demux-pinctrl.c ++++ b/drivers/i2c/muxes/i2c-demux-pinctrl.c +@@ -243,6 +243,10 @@ static int i2c_demux_pinctrl_probe(struct platform_device *pdev) + + props[i].name = devm_kstrdup(&pdev->dev, "status", GFP_KERNEL); + props[i].value = devm_kstrdup(&pdev->dev, "ok", GFP_KERNEL); ++ if (!props[i].name || !props[i].value) { ++ err = -ENOMEM; ++ goto err_rollback; ++ } + props[i].length = 3; + + of_changeset_init(&priv->chan[i].chgset); +-- +2.40.1 + diff --git a/queue-6.5/i2c-mux-gpio-add-missing-fwnode_handle_put.patch b/queue-6.5/i2c-mux-gpio-add-missing-fwnode_handle_put.patch new file mode 100644 index 00000000000..7a734597b1d --- /dev/null +++ b/queue-6.5/i2c-mux-gpio-add-missing-fwnode_handle_put.patch @@ -0,0 +1,40 @@ +From b496d7ce9092eb10ec9cb3078cab312a7013b28f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Mar 2023 12:29:51 +0800 +Subject: i2c: mux: gpio: Add missing fwnode_handle_put() + +From: Liang He + +[ Upstream commit db6aee6083a56ac4a6cd1b08fff7938072bcd0a3 ] + +In i2c_mux_gpio_probe_fw(), we should add fwnode_handle_put() +when break out of the iteration device_for_each_child_node() +as it will automatically increase and decrease the refcounter. + +Fixes: 98b2b712bc85 ("i2c: i2c-mux-gpio: Enable this driver in ACPI land") +Signed-off-by: Liang He +Signed-off-by: Wolfram Sang +Signed-off-by: Sasha Levin +--- + drivers/i2c/muxes/i2c-mux-gpio.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/i2c/muxes/i2c-mux-gpio.c b/drivers/i2c/muxes/i2c-mux-gpio.c +index 5d5cbe0130cdf..5ca03bd34c8d1 100644 +--- a/drivers/i2c/muxes/i2c-mux-gpio.c ++++ b/drivers/i2c/muxes/i2c-mux-gpio.c +@@ -105,8 +105,10 @@ static int i2c_mux_gpio_probe_fw(struct gpiomux *mux, + + } else if (is_acpi_node(child)) { + rc = acpi_get_local_address(ACPI_HANDLE_FWNODE(child), values + i); +- if (rc) ++ if (rc) { ++ fwnode_handle_put(child); + return dev_err_probe(dev, rc, "Cannot get address\n"); ++ } + } + + i++; +-- +2.40.1 + diff --git a/queue-6.5/i2c-xiic-correct-return-value-check-for-xiic_reinit.patch b/queue-6.5/i2c-xiic-correct-return-value-check-for-xiic_reinit.patch new file mode 100644 index 00000000000..c042965fe10 --- /dev/null +++ b/queue-6.5/i2c-xiic-correct-return-value-check-for-xiic_reinit.patch @@ -0,0 +1,40 @@ +From 887d99ee315a34241d52c3d12517f87537a1bef9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 20 Sep 2023 14:41:09 +0100 +Subject: i2c: xiic: Correct return value check for xiic_reinit() + +From: Daniel Scally + +[ Upstream commit 59851fb05d759f13662be143eff0aae605815b0e ] + +The error paths for xiic_reinit() return negative values on failure +and 0 on success - this error message therefore is triggered on +_success_ rather than failure. Correct the condition so it's only +shown on failure as intended. + +Fixes: 8fa9c9388053 ("i2c: xiic: return value of xiic_reinit") +Signed-off-by: Daniel Scally +Acked-by: Michal Simek +Reviewed-by: Andi Shyti +Signed-off-by: Wolfram Sang +Signed-off-by: Sasha Levin +--- + drivers/i2c/busses/i2c-xiic.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c +index b3bb97762c859..71391b590adae 100644 +--- a/drivers/i2c/busses/i2c-xiic.c ++++ b/drivers/i2c/busses/i2c-xiic.c +@@ -710,7 +710,7 @@ static irqreturn_t xiic_process(int irq, void *dev_id) + * reset the IP instead of just flush fifos + */ + ret = xiic_reinit(i2c); +- if (!ret) ++ if (ret < 0) + dev_dbg(i2c->adap.dev.parent, "reinit failed\n"); + + if (i2c->rx_msg) { +-- +2.40.1 + diff --git a/queue-6.5/proc-nommu-fix-empty-proc-pid-maps.patch b/queue-6.5/proc-nommu-fix-empty-proc-pid-maps.patch new file mode 100644 index 00000000000..98b0a213a80 --- /dev/null +++ b/queue-6.5/proc-nommu-fix-empty-proc-pid-maps.patch @@ -0,0 +1,123 @@ +From 84ed37ad33c2b841bfb7051cb032dd79f049e351 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 15 Sep 2023 12:00:56 -0400 +Subject: proc: nommu: fix empty /proc//maps + +From: Ben Wolsieffer + +[ Upstream commit fe4419801617514765974f3e796269bc512ad146 ] + +On no-MMU, /proc//maps reads as an empty file. This happens because +find_vma(mm, 0) always returns NULL (assuming no vma actually contains the +zero address, which is normally the case). + +To fix this bug and improve the maintainability in the future, this patch +makes the no-MMU implementation as similar as possible to the MMU +implementation. + +The only remaining differences are the lack of hold/release_task_mempolicy +and the extra code to shoehorn the gate vma into the iterator. + +This has been tested on top of 6.5.3 on an STM32F746. + +Link: https://lkml.kernel.org/r/20230915160055.971059-2-ben.wolsieffer@hefring.com +Fixes: 0c563f148043 ("proc: remove VMA rbtree use from nommu") +Signed-off-by: Ben Wolsieffer +Cc: Davidlohr Bueso +Cc: Giulio Benetti +Cc: Liam R. Howlett +Cc: Matthew Wilcox (Oracle) +Cc: Oleg Nesterov +Cc: Vlastimil Babka +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + fs/proc/internal.h | 2 -- + fs/proc/task_nommu.c | 37 ++++++++++++++++++++++--------------- + 2 files changed, 22 insertions(+), 17 deletions(-) + +diff --git a/fs/proc/internal.h b/fs/proc/internal.h +index 9dda7e54b2d0d..9a8f32f21ff56 100644 +--- a/fs/proc/internal.h ++++ b/fs/proc/internal.h +@@ -289,9 +289,7 @@ struct proc_maps_private { + struct inode *inode; + struct task_struct *task; + struct mm_struct *mm; +-#ifdef CONFIG_MMU + struct vma_iterator iter; +-#endif + #ifdef CONFIG_NUMA + struct mempolicy *task_mempolicy; + #endif +diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c +index 061bd3f82756e..d3e19080df4af 100644 +--- a/fs/proc/task_nommu.c ++++ b/fs/proc/task_nommu.c +@@ -188,15 +188,28 @@ static int show_map(struct seq_file *m, void *_p) + return nommu_vma_show(m, _p); + } + +-static void *m_start(struct seq_file *m, loff_t *pos) ++static struct vm_area_struct *proc_get_vma(struct proc_maps_private *priv, ++ loff_t *ppos) ++{ ++ struct vm_area_struct *vma = vma_next(&priv->iter); ++ ++ if (vma) { ++ *ppos = vma->vm_start; ++ } else { ++ *ppos = -1UL; ++ } ++ ++ return vma; ++} ++ ++static void *m_start(struct seq_file *m, loff_t *ppos) + { + struct proc_maps_private *priv = m->private; ++ unsigned long last_addr = *ppos; + struct mm_struct *mm; +- struct vm_area_struct *vma; +- unsigned long addr = *pos; + +- /* See m_next(). Zero at the start or after lseek. */ +- if (addr == -1UL) ++ /* See proc_get_vma(). Zero at the start or after lseek. */ ++ if (last_addr == -1UL) + return NULL; + + /* pin the task and mm whilst we play with them */ +@@ -218,12 +231,9 @@ static void *m_start(struct seq_file *m, loff_t *pos) + return ERR_PTR(-EINTR); + } + +- /* start the next element from addr */ +- vma = find_vma(mm, addr); +- if (vma) +- return vma; ++ vma_iter_init(&priv->iter, mm, last_addr); + +- return NULL; ++ return proc_get_vma(priv, ppos); + } + + static void m_stop(struct seq_file *m, void *v) +@@ -240,12 +250,9 @@ static void m_stop(struct seq_file *m, void *v) + priv->task = NULL; + } + +-static void *m_next(struct seq_file *m, void *_p, loff_t *pos) ++static void *m_next(struct seq_file *m, void *_p, loff_t *ppos) + { +- struct vm_area_struct *vma = _p; +- +- *pos = vma->vm_end; +- return find_vma(vma->vm_mm, vma->vm_end); ++ return proc_get_vma(m->private, ppos); + } + + static const struct seq_operations proc_pid_maps_ops = { +-- +2.40.1 + diff --git a/queue-6.5/proc-nommu-proc-pid-maps-release-mmap-read-lock.patch b/queue-6.5/proc-nommu-proc-pid-maps-release-mmap-read-lock.patch new file mode 100644 index 00000000000..647323153e2 --- /dev/null +++ b/queue-6.5/proc-nommu-proc-pid-maps-release-mmap-read-lock.patch @@ -0,0 +1,119 @@ +From 97485f8262e083642c675966e23c0fef7ddd816e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 14 Sep 2023 12:30:20 -0400 +Subject: proc: nommu: /proc//maps: release mmap read lock + +From: Ben Wolsieffer + +[ Upstream commit 578d7699e5c2add8c2e9549d9d75dfb56c460cb3 ] + +The no-MMU implementation of /proc//map doesn't normally release +the mmap read lock, because it uses !IS_ERR_OR_NULL(_vml) to determine +whether to release the lock. Since _vml is NULL when the end of the +mappings is reached, the lock is not released. + +Reading /proc/1/maps twice doesn't cause a hang because it only +takes the read lock, which can be taken multiple times and therefore +doesn't show any problem if the lock isn't released. Instead, you need +to perform some operation that attempts to take the write lock after +reading /proc//maps. To actually reproduce the bug, compile the +following code as 'proc_maps_bug': + +#include +#include +#include + +int main(int argc, char *argv[]) { + void *buf; + sleep(1); + buf = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + puts("mmap returned"); + return 0; +} + +Then, run: + + ./proc_maps_bug &; cat /proc/$!/maps; fg + +Without this patch, mmap() will hang and the command will never +complete. + +This code was incorrectly adapted from the MMU implementation, which at +the time released the lock in m_next() before returning the last entry. + +The MMU implementation has diverged further from the no-MMU version since +then, so this patch brings their locking and error handling into sync, +fixing the bug and hopefully avoiding similar issues in the future. + +Link: https://lkml.kernel.org/r/20230914163019.4050530-2-ben.wolsieffer@hefring.com +Fixes: 47fecca15c09 ("fs/proc/task_nommu.c: don't use priv->task->mm") +Signed-off-by: Ben Wolsieffer +Acked-by: Oleg Nesterov +Cc: Giulio Benetti +Cc: Greg Ungerer +Cc: +Signed-off-by: Andrew Morton +Stable-dep-of: fe4419801617 ("proc: nommu: fix empty /proc//maps") +Signed-off-by: Sasha Levin +--- + fs/proc/task_nommu.c | 27 +++++++++++++++------------ + 1 file changed, 15 insertions(+), 12 deletions(-) + +diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c +index 2c8b622659814..061bd3f82756e 100644 +--- a/fs/proc/task_nommu.c ++++ b/fs/proc/task_nommu.c +@@ -205,11 +205,16 @@ static void *m_start(struct seq_file *m, loff_t *pos) + return ERR_PTR(-ESRCH); + + mm = priv->mm; +- if (!mm || !mmget_not_zero(mm)) ++ if (!mm || !mmget_not_zero(mm)) { ++ put_task_struct(priv->task); ++ priv->task = NULL; + return NULL; ++ } + + if (mmap_read_lock_killable(mm)) { + mmput(mm); ++ put_task_struct(priv->task); ++ priv->task = NULL; + return ERR_PTR(-EINTR); + } + +@@ -218,23 +223,21 @@ static void *m_start(struct seq_file *m, loff_t *pos) + if (vma) + return vma; + +- mmap_read_unlock(mm); +- mmput(mm); + return NULL; + } + +-static void m_stop(struct seq_file *m, void *_vml) ++static void m_stop(struct seq_file *m, void *v) + { + struct proc_maps_private *priv = m->private; ++ struct mm_struct *mm = priv->mm; + +- if (!IS_ERR_OR_NULL(_vml)) { +- mmap_read_unlock(priv->mm); +- mmput(priv->mm); +- } +- if (priv->task) { +- put_task_struct(priv->task); +- priv->task = NULL; +- } ++ if (!priv->task) ++ return; ++ ++ mmap_read_unlock(mm); ++ mmput(mm); ++ put_task_struct(priv->task); ++ priv->task = NULL; + } + + static void *m_next(struct seq_file *m, void *_p, loff_t *pos) +-- +2.40.1 + diff --git a/queue-6.5/series b/queue-6.5/series index 840c4501e6c..c10fce2d874 100644 --- a/queue-6.5/series +++ b/queue-6.5/series @@ -100,3 +100,11 @@ net-ena-flush-xdp-packets-on-error.patch bnxt_en-flush-xdp-for-bnxt_poll_nitroa0-s-napi.patch octeontx2-pf-do-xdp_do_flush-after-redirects.patch igc-expose-tx-usecs-coalesce-setting-to-user.patch +cxl-region-match-auto-discovered-region-decoders-by-.patch +proc-nommu-proc-pid-maps-release-mmap-read-lock.patch +proc-nommu-fix-empty-proc-pid-maps.patch +cifs-fix-uaf-in-cifs_demultiplex_thread.patch +gpio-tb10x-fix-an-error-handling-path-in-tb10x_gpio_.patch +i2c-mux-demux-pinctrl-check-the-return-value-of-devm.patch +i2c-mux-gpio-add-missing-fwnode_handle_put.patch +i2c-xiic-correct-return-value-check-for-xiic_reinit.patch