From b0a5af7d6cda5ddc7a662d6f9409c506aef0472f Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Sun, 11 Feb 2024 18:43:18 -0500 Subject: [PATCH] Fixes for 6.1 Signed-off-by: Sasha Levin --- ...an-ubsan-shift-out-of-bounds-warning.patch | 72 ++++++++ ...lm-don-t-put-dlm_local_addrs-on-heap.patch | 160 ++++++++++++++++++ queue-6.1/series | 2 + 3 files changed, 234 insertions(+) create mode 100644 queue-6.1/blk-iocost-fix-an-ubsan-shift-out-of-bounds-warning.patch create mode 100644 queue-6.1/fs-dlm-don-t-put-dlm_local_addrs-on-heap.patch 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 index 00000000000..3802a21c855 --- /dev/null +++ b/queue-6.1/blk-iocost-fix-an-ubsan-shift-out-of-bounds-warning.patch @@ -0,0 +1,72 @@ +From 2dfc3bc82f7829b9fa9e9647c6262903a3b93a5f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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: + + 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 +Signed-off-by: Tejun Heo +Fixes: 5160a5a53c0c ("blk-iocost: implement delay adjustment hysteresis") +Link: https://lore.kernel.org/r/ZVvc9L_CYk5LO1fT@slm.duckdns.org +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..e8e335ab7f5 --- /dev/null +++ b/queue-6.1/fs-dlm-don-t-put-dlm_local_addrs-on-heap.patch @@ -0,0 +1,160 @@ +From 7382c4a340e2a3992e792926e3c2d3ca137d8d02 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Nov 2022 17:11:52 -0500 +Subject: fs: dlm: don't put dlm_local_addrs on heap + +From: Alexander Aring + +[ 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 +Signed-off-by: David Teigland +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/series b/queue-6.1/series index bc53210ccc9..a22c7f38e7d 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -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 -- 2.47.3