]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 6.1
authorSasha Levin <sashal@kernel.org>
Mon, 25 Sep 2023 11:23:32 +0000 (07:23 -0400)
committerSasha Levin <sashal@kernel.org>
Mon, 25 Sep 2023 11:23:32 +0000 (07:23 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-6.1/cifs-fix-uaf-in-cifs_demultiplex_thread.patch [new file with mode: 0644]
queue-6.1/gpio-tb10x-fix-an-error-handling-path-in-tb10x_gpio_.patch [new file with mode: 0644]
queue-6.1/i2c-mux-demux-pinctrl-check-the-return-value-of-devm.patch [new file with mode: 0644]
queue-6.1/i2c-mux-gpio-add-missing-fwnode_handle_put.patch [new file with mode: 0644]
queue-6.1/i2c-xiic-correct-return-value-check-for-xiic_reinit.patch [new file with mode: 0644]
queue-6.1/proc-nommu-fix-empty-proc-pid-maps.patch [new file with mode: 0644]
queue-6.1/proc-nommu-proc-pid-maps-release-mmap-read-lock.patch [new file with mode: 0644]
queue-6.1/series

diff --git a/queue-6.1/cifs-fix-uaf-in-cifs_demultiplex_thread.patch b/queue-6.1/cifs-fix-uaf-in-cifs_demultiplex_thread.patch
new file mode 100644 (file)
index 0000000..0fcb32e
--- /dev/null
@@ -0,0 +1,252 @@
+From 3b64ec142b0237c1722da38144144252c2343bc0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 19 Sep 2023 13:38:04 -0500
+Subject: cifs: Fix UAF in cifs_demultiplex_thread()
+
+From: Zhang Xiaoxu <zhangxiaoxu5@huawei.com>
+
+[ 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:
+   <TASK>
+   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
+   </TASK>
+
+  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) <pc@manguebit.com>
+Signed-off-by: Zhang Xiaoxu <zhangxiaoxu5@huawei.com>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 03f34ec63e10d..39602f39aea8f 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 e03ffcf7e201c..87aea456ee903 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);
+@@ -759,7 +762,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;
+@@ -912,7 +916,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:
+@@ -1011,6 +1015,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
+@@ -1206,7 +1213,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;
+@@ -1227,7 +1235,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;
+@@ -1414,7 +1422,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);
+@@ -1431,7 +1440,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;
+@@ -1555,14 +1564,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);
+@@ -1593,7 +1604,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);
+@@ -1613,7 +1625,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.1/gpio-tb10x-fix-an-error-handling-path-in-tb10x_gpio_.patch b/queue-6.1/gpio-tb10x-fix-an-error-handling-path-in-tb10x_gpio_.patch
new file mode 100644 (file)
index 0000000..a19f759
--- /dev/null
@@ -0,0 +1,48 @@
+From d66755d46c76279c1b53c5f8977c551211a20af0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 3 Sep 2023 08:13:21 +0200
+Subject: gpio: tb10x: Fix an error handling path in tb10x_gpio_probe()
+
+From: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+
+[ 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 <christophe.jaillet@wanadoo.fr>
+Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 de6afa3f97168..05357473d2a11 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.1/i2c-mux-demux-pinctrl-check-the-return-value-of-devm.patch b/queue-6.1/i2c-mux-demux-pinctrl-check-the-return-value-of-devm.patch
new file mode 100644 (file)
index 0000000..85e53e7
--- /dev/null
@@ -0,0 +1,38 @@
+From c3ae41e578ed47b04bcb2e3ab2ee21fc0c8f211e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 3 Mar 2022 20:39:14 +0800
+Subject: i2c: mux: demux-pinctrl: check the return value of devm_kstrdup()
+
+From: Xiaoke Wang <xkernel.wang@foxmail.com>
+
+[ 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 <xkernel.wang@foxmail.com>
+Signed-off-by: Wolfram Sang <wsa@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 f7a7405d4350a..8e8688e8de0fb 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.1/i2c-mux-gpio-add-missing-fwnode_handle_put.patch b/queue-6.1/i2c-mux-gpio-add-missing-fwnode_handle_put.patch
new file mode 100644 (file)
index 0000000..ba3e40b
--- /dev/null
@@ -0,0 +1,40 @@
+From afe4d31fa65a21e995513afc19358708e8c75f4a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 22 Mar 2023 12:29:51 +0800
+Subject: i2c: mux: gpio: Add missing fwnode_handle_put()
+
+From: Liang He <windhl@126.com>
+
+[ 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 <windhl@126.com>
+Signed-off-by: Wolfram Sang <wsa@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 73a23e117ebec..0930a51c8c7c0 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.1/i2c-xiic-correct-return-value-check-for-xiic_reinit.patch b/queue-6.1/i2c-xiic-correct-return-value-check-for-xiic_reinit.patch
new file mode 100644 (file)
index 0000000..abd63a6
--- /dev/null
@@ -0,0 +1,40 @@
+From 0fc1ab77479d0211a1b53e6072d16d0b29a35c63 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 20 Sep 2023 14:41:09 +0100
+Subject: i2c: xiic: Correct return value check for xiic_reinit()
+
+From: Daniel Scally <dan.scally@ideasonboard.com>
+
+[ 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 <dan.scally@ideasonboard.com>
+Acked-by: Michal Simek <michal.simek@amd.com>
+Reviewed-by: Andi Shyti <andi.shyti@kernel.org>
+Signed-off-by: Wolfram Sang <wsa@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 b41a6709e47f2..b27bfc7765993 100644
+--- a/drivers/i2c/busses/i2c-xiic.c
++++ b/drivers/i2c/busses/i2c-xiic.c
+@@ -420,7 +420,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.1/proc-nommu-fix-empty-proc-pid-maps.patch b/queue-6.1/proc-nommu-fix-empty-proc-pid-maps.patch
new file mode 100644 (file)
index 0000000..83c3fb2
--- /dev/null
@@ -0,0 +1,123 @@
+From 4e0c395209198f451085d5297a1efa1de504ac13 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 15 Sep 2023 12:00:56 -0400
+Subject: proc: nommu: fix empty /proc/<pid>/maps
+
+From: Ben Wolsieffer <ben.wolsieffer@hefring.com>
+
+[ Upstream commit fe4419801617514765974f3e796269bc512ad146 ]
+
+On no-MMU, /proc/<pid>/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 <ben.wolsieffer@hefring.com>
+Cc: Davidlohr Bueso <dave@stgolabs.net>
+Cc: Giulio Benetti <giulio.benetti@benettiengineering.com>
+Cc: Liam R. Howlett <Liam.Howlett@oracle.com>
+Cc: Matthew Wilcox (Oracle) <willy@infradead.org>
+Cc: Oleg Nesterov <oleg@redhat.com>
+Cc: Vlastimil Babka <vbabka@suse.cz>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 b701d0207edf0..6b921826d85b6 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 bfcf17f75ed50..dc05780f93e13 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.1/proc-nommu-proc-pid-maps-release-mmap-read-lock.patch b/queue-6.1/proc-nommu-proc-pid-maps-release-mmap-read-lock.patch
new file mode 100644 (file)
index 0000000..446450d
--- /dev/null
@@ -0,0 +1,119 @@
+From 7aa724a9e34de64c27a4c0be1f56b0489018b3de Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 14 Sep 2023 12:30:20 -0400
+Subject: proc: nommu: /proc/<pid>/maps: release mmap read lock
+
+From: Ben Wolsieffer <Ben.Wolsieffer@hefring.com>
+
+[ Upstream commit 578d7699e5c2add8c2e9549d9d75dfb56c460cb3 ]
+
+The no-MMU implementation of /proc/<pid>/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/<pid>/maps. To actually reproduce the bug, compile the
+following code as 'proc_maps_bug':
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/mman.h>
+
+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 <ben.wolsieffer@hefring.com>
+Acked-by: Oleg Nesterov <oleg@redhat.com>
+Cc: Giulio Benetti <giulio.benetti@benettiengineering.com>
+Cc: Greg Ungerer <gerg@uclinux.org>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Stable-dep-of: fe4419801617 ("proc: nommu: fix empty /proc/<pid>/maps")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 2fd06f52b6a44..bfcf17f75ed50 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
+
index f940e453414cb2516392940186f0bd7e8c55bc8e..e4b4df7cc160bb3ad657135a78e6148b2b4e0449 100644 (file)
@@ -82,3 +82,10 @@ 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
+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