]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 6.1
authorSasha Levin <sashal@kernel.org>
Sun, 11 Feb 2024 23:43:18 +0000 (18:43 -0500)
committerSasha Levin <sashal@kernel.org>
Sun, 11 Feb 2024 23:43:18 +0000 (18:43 -0500)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-6.1/blk-iocost-fix-an-ubsan-shift-out-of-bounds-warning.patch [new file with mode: 0644]
queue-6.1/fs-dlm-don-t-put-dlm_local_addrs-on-heap.patch [new file with mode: 0644]
queue-6.1/series

diff --git a/queue-6.1/blk-iocost-fix-an-ubsan-shift-out-of-bounds-warning.patch b/queue-6.1/blk-iocost-fix-an-ubsan-shift-out-of-bounds-warning.patch
new file mode 100644 (file)
index 0000000..3802a21
--- /dev/null
@@ -0,0 +1,72 @@
+From 2dfc3bc82f7829b9fa9e9647c6262903a3b93a5f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 20 Nov 2023 12:25:56 -1000
+Subject: blk-iocost: Fix an UBSAN shift-out-of-bounds warning
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Tejun Heo <tj@kernel.org>
+
+[ Upstream commit 2a427b49d02995ea4a6ff93a1432c40fa4d36821 ]
+
+When iocg_kick_delay() is called from a CPU different than the one which set
+the delay, @now may be in the past of @iocg->delay_at leading to the
+following warning:
+
+  UBSAN: shift-out-of-bounds in block/blk-iocost.c:1359:23
+  shift exponent 18446744073709 is too large for 64-bit type 'u64' (aka 'unsigned long long')
+  ...
+  Call Trace:
+   <TASK>
+   dump_stack_lvl+0x79/0xc0
+   __ubsan_handle_shift_out_of_bounds+0x2ab/0x300
+   iocg_kick_delay+0x222/0x230
+   ioc_rqos_merge+0x1d7/0x2c0
+   __rq_qos_merge+0x2c/0x80
+   bio_attempt_back_merge+0x83/0x190
+   blk_attempt_plug_merge+0x101/0x150
+   blk_mq_submit_bio+0x2b1/0x720
+   submit_bio_noacct_nocheck+0x320/0x3e0
+   __swap_writepage+0x2ab/0x9d0
+
+The underflow itself doesn't really affect the behavior in any meaningful
+way; however, the past timestamp may exaggerate the delay amount calculated
+later in the code, which shouldn't be a material problem given the nature of
+the delay mechanism.
+
+If @now is in the past, this CPU is racing another CPU which recently set up
+the delay and there's nothing this CPU can contribute w.r.t. the delay.
+Let's bail early from iocg_kick_delay() in such cases.
+
+Reported-by: Breno Leitão <leitao@debian.org>
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Fixes: 5160a5a53c0c ("blk-iocost: implement delay adjustment hysteresis")
+Link: https://lore.kernel.org/r/ZVvc9L_CYk5LO1fT@slm.duckdns.org
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ block/blk-iocost.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/block/blk-iocost.c b/block/blk-iocost.c
+index 7dd6a33e1d6a..e6557024e3da 100644
+--- a/block/blk-iocost.c
++++ b/block/blk-iocost.c
+@@ -1337,6 +1337,13 @@ static bool iocg_kick_delay(struct ioc_gq *iocg, struct ioc_now *now)
+       lockdep_assert_held(&iocg->waitq.lock);
++      /*
++       * If the delay is set by another CPU, we may be in the past. No need to
++       * change anything if so. This avoids decay calculation underflow.
++       */
++      if (time_before64(now->now, iocg->delay_at))
++              return false;
++
+       /* calculate the current delay in effect - 1/2 every second */
+       tdelta = now->now - iocg->delay_at;
+       if (iocg->delay)
+-- 
+2.43.0
+
diff --git a/queue-6.1/fs-dlm-don-t-put-dlm_local_addrs-on-heap.patch b/queue-6.1/fs-dlm-don-t-put-dlm_local_addrs-on-heap.patch
new file mode 100644 (file)
index 0000000..e8e335a
--- /dev/null
@@ -0,0 +1,160 @@
+From 7382c4a340e2a3992e792926e3c2d3ca137d8d02 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 17 Nov 2022 17:11:52 -0500
+Subject: fs: dlm: don't put dlm_local_addrs on heap
+
+From: Alexander Aring <aahringo@redhat.com>
+
+[ Upstream commit c51c9cd8addcfbdc097dbefd59f022402183644b ]
+
+This patch removes to allocate the dlm_local_addr[] pointers on the
+heap. Instead we directly store the type of "struct sockaddr_storage".
+This removes function deinit_local() because it was freeing memory only.
+
+Signed-off-by: Alexander Aring <aahringo@redhat.com>
+Signed-off-by: David Teigland <teigland@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/dlm/lowcomms.c | 38 ++++++++++++--------------------------
+ 1 file changed, 12 insertions(+), 26 deletions(-)
+
+diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c
+index 72f34f96d015..2c797eb519da 100644
+--- a/fs/dlm/lowcomms.c
++++ b/fs/dlm/lowcomms.c
+@@ -174,7 +174,7 @@ static LIST_HEAD(dlm_node_addrs);
+ static DEFINE_SPINLOCK(dlm_node_addrs_spin);
+ static struct listen_connection listen_con;
+-static struct sockaddr_storage *dlm_local_addr[DLM_MAX_ADDR_COUNT];
++static struct sockaddr_storage dlm_local_addr[DLM_MAX_ADDR_COUNT];
+ static int dlm_local_count;
+ int dlm_allow_conn;
+@@ -398,7 +398,7 @@ static int nodeid_to_addr(int nodeid, struct sockaddr_storage *sas_out,
+       if (!sa_out)
+               return 0;
+-      if (dlm_local_addr[0]->ss_family == AF_INET) {
++      if (dlm_local_addr[0].ss_family == AF_INET) {
+               struct sockaddr_in *in4  = (struct sockaddr_in *) &sas;
+               struct sockaddr_in *ret4 = (struct sockaddr_in *) sa_out;
+               ret4->sin_addr.s_addr = in4->sin_addr.s_addr;
+@@ -727,7 +727,7 @@ static void add_sock(struct socket *sock, struct connection *con)
+ static void make_sockaddr(struct sockaddr_storage *saddr, uint16_t port,
+                         int *addr_len)
+ {
+-      saddr->ss_family =  dlm_local_addr[0]->ss_family;
++      saddr->ss_family =  dlm_local_addr[0].ss_family;
+       if (saddr->ss_family == AF_INET) {
+               struct sockaddr_in *in4_addr = (struct sockaddr_in *)saddr;
+               in4_addr->sin_port = cpu_to_be16(port);
+@@ -1167,7 +1167,7 @@ static int sctp_bind_addrs(struct socket *sock, uint16_t port)
+       int i, addr_len, result = 0;
+       for (i = 0; i < dlm_local_count; i++) {
+-              memcpy(&localaddr, dlm_local_addr[i], sizeof(localaddr));
++              memcpy(&localaddr, &dlm_local_addr[i], sizeof(localaddr));
+               make_sockaddr(&localaddr, port, &addr_len);
+               if (!i)
+@@ -1187,7 +1187,7 @@ static int sctp_bind_addrs(struct socket *sock, uint16_t port)
+ /* Get local addresses */
+ static void init_local(void)
+ {
+-      struct sockaddr_storage sas, *addr;
++      struct sockaddr_storage sas;
+       int i;
+       dlm_local_count = 0;
+@@ -1195,21 +1195,10 @@ static void init_local(void)
+               if (dlm_our_addr(&sas, i))
+                       break;
+-              addr = kmemdup(&sas, sizeof(*addr), GFP_NOFS);
+-              if (!addr)
+-                      break;
+-              dlm_local_addr[dlm_local_count++] = addr;
++              memcpy(&dlm_local_addr[dlm_local_count++], &sas, sizeof(sas));
+       }
+ }
+-static void deinit_local(void)
+-{
+-      int i;
+-
+-      for (i = 0; i < dlm_local_count; i++)
+-              kfree(dlm_local_addr[i]);
+-}
+-
+ static struct writequeue_entry *new_writequeue_entry(struct connection *con)
+ {
+       struct writequeue_entry *entry;
+@@ -1575,7 +1564,7 @@ static void dlm_connect(struct connection *con)
+       }
+       /* Create a socket to communicate with */
+-      result = sock_create_kern(&init_net, dlm_local_addr[0]->ss_family,
++      result = sock_create_kern(&init_net, dlm_local_addr[0].ss_family,
+                                 SOCK_STREAM, dlm_proto_ops->proto, &sock);
+       if (result < 0)
+               goto socket_err;
+@@ -1786,7 +1775,6 @@ void dlm_lowcomms_stop(void)
+       foreach_conn(free_conn);
+       srcu_read_unlock(&connections_srcu, idx);
+       work_stop();
+-      deinit_local();
+       dlm_proto_ops = NULL;
+ }
+@@ -1803,7 +1791,7 @@ static int dlm_listen_for_all(void)
+       if (result < 0)
+               return result;
+-      result = sock_create_kern(&init_net, dlm_local_addr[0]->ss_family,
++      result = sock_create_kern(&init_net, dlm_local_addr[0].ss_family,
+                                 SOCK_STREAM, dlm_proto_ops->proto, &sock);
+       if (result < 0) {
+               log_print("Can't create comms socket: %d", result);
+@@ -1842,7 +1830,7 @@ static int dlm_tcp_bind(struct socket *sock)
+       /* Bind to our cluster-known address connecting to avoid
+        * routing problems.
+        */
+-      memcpy(&src_addr, dlm_local_addr[0], sizeof(src_addr));
++      memcpy(&src_addr, &dlm_local_addr[0], sizeof(src_addr));
+       make_sockaddr(&src_addr, 0, &addr_len);
+       result = kernel_bind(sock, (struct sockaddr *)&src_addr,
+@@ -1899,9 +1887,9 @@ static int dlm_tcp_listen_bind(struct socket *sock)
+       int addr_len;
+       /* Bind to our port */
+-      make_sockaddr(dlm_local_addr[0], dlm_config.ci_tcp_port, &addr_len);
++      make_sockaddr(&dlm_local_addr[0], dlm_config.ci_tcp_port, &addr_len);
+       return kernel_bind(sock, (struct sockaddr *)&dlm_local_addr[0],
+-                         addr_len);
++                         addr_len);
+ }
+ static const struct dlm_proto_ops dlm_tcp_ops = {
+@@ -1992,7 +1980,7 @@ int dlm_lowcomms_start(void)
+       error = work_start();
+       if (error)
+-              goto fail_local;
++              goto fail;
+       dlm_allow_conn = 1;
+@@ -2022,8 +2010,6 @@ int dlm_lowcomms_start(void)
+ fail_proto_ops:
+       dlm_allow_conn = 0;
+       work_stop();
+-fail_local:
+-      deinit_local();
+ fail:
+       return error;
+ }
+-- 
+2.43.0
+
index bc53210ccc9d758ddd31ef5fd9e067cdf90e692a..a22c7f38e7d1636f41bc6da639ddb2923e26db63 100644 (file)
@@ -39,3 +39,5 @@ netfilter-nft_set_pipapo-add-helper-to-release-pcpu-.patch
 netfilter-nft_set_pipapo-remove-scratch_aligned-poin.patch
 fs-ntfs3-fix-an-null-dereference-bug.patch
 scsi-core-move-scsi_host_busy-out-of-host-lock-if-it.patch
+blk-iocost-fix-an-ubsan-shift-out-of-bounds-warning.patch
+fs-dlm-don-t-put-dlm_local_addrs-on-heap.patch