From: Sasha Levin Date: Fri, 27 Dec 2024 15:06:15 +0000 (-0500) Subject: Fixes for 5.15 X-Git-Tag: v6.1.123~58 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=7207197092c91d0d0eff872875c5ec8db1434e76;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 5.15 Signed-off-by: Sasha Levin --- diff --git a/queue-5.15/bpf-check-negative-offsets-in-__bpf_skb_min_len.patch b/queue-5.15/bpf-check-negative-offsets-in-__bpf_skb_min_len.patch new file mode 100644 index 00000000000..7e67d3e176b --- /dev/null +++ b/queue-5.15/bpf-check-negative-offsets-in-__bpf_skb_min_len.patch @@ -0,0 +1,66 @@ +From b7d7c0f895b83ebac04fd3704d2c8573b5b376e9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 12 Dec 2024 19:40:54 -0800 +Subject: bpf: Check negative offsets in __bpf_skb_min_len() + +From: Cong Wang + +[ Upstream commit 9ecc4d858b92c1bb0673ad9c327298e600c55659 ] + +skb_network_offset() and skb_transport_offset() can be negative when +they are called after we pull the transport header, for example, when +we use eBPF sockmap at the point of ->sk_data_ready(). + +__bpf_skb_min_len() uses an unsigned int to get these offsets, this +leads to a very large number which then causes bpf_skb_change_tail() +failed unexpectedly. + +Fix this by using a signed int to get these offsets and ensure the +minimum is at least zero. + +Fixes: 5293efe62df8 ("bpf: add bpf_skb_change_tail helper") +Signed-off-by: Cong Wang +Signed-off-by: Daniel Borkmann +Acked-by: John Fastabend +Link: https://lore.kernel.org/bpf/20241213034057.246437-2-xiyou.wangcong@gmail.com +Signed-off-by: Sasha Levin +--- + net/core/filter.c | 21 +++++++++++++++------ + 1 file changed, 15 insertions(+), 6 deletions(-) + +diff --git a/net/core/filter.c b/net/core/filter.c +index e35d86ba00e2..d6042d285aa2 100644 +--- a/net/core/filter.c ++++ b/net/core/filter.c +@@ -3683,13 +3683,22 @@ static const struct bpf_func_proto bpf_skb_adjust_room_proto = { + + static u32 __bpf_skb_min_len(const struct sk_buff *skb) + { +- u32 min_len = skb_network_offset(skb); ++ int offset = skb_network_offset(skb); ++ u32 min_len = 0; + +- if (skb_transport_header_was_set(skb)) +- min_len = skb_transport_offset(skb); +- if (skb->ip_summed == CHECKSUM_PARTIAL) +- min_len = skb_checksum_start_offset(skb) + +- skb->csum_offset + sizeof(__sum16); ++ if (offset > 0) ++ min_len = offset; ++ if (skb_transport_header_was_set(skb)) { ++ offset = skb_transport_offset(skb); ++ if (offset > 0) ++ min_len = offset; ++ } ++ if (skb->ip_summed == CHECKSUM_PARTIAL) { ++ offset = skb_checksum_start_offset(skb) + ++ skb->csum_offset + sizeof(__sum16); ++ if (offset > 0) ++ min_len = offset; ++ } + return min_len; + } + +-- +2.39.5 + diff --git a/queue-5.15/media-dvb-frontends-dib3000mb-fix-uninit-value-in-di.patch b/queue-5.15/media-dvb-frontends-dib3000mb-fix-uninit-value-in-di.patch new file mode 100644 index 00000000000..27f3905fc6c --- /dev/null +++ b/queue-5.15/media-dvb-frontends-dib3000mb-fix-uninit-value-in-di.patch @@ -0,0 +1,62 @@ +From a1127cdae03df69b535e25673906947d44ad3afa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 May 2024 08:58:00 -0700 +Subject: media: dvb-frontends: dib3000mb: fix uninit-value in + dib3000_write_reg + +From: Nikita Zhandarovich + +[ Upstream commit 2dd59fe0e19e1ab955259978082b62e5751924c7 ] + +Syzbot reports [1] an uninitialized value issue found by KMSAN in +dib3000_read_reg(). + +Local u8 rb[2] is used in i2c_transfer() as a read buffer; in case +that call fails, the buffer may end up with some undefined values. + +Since no elaborate error handling is expected in dib3000_write_reg(), +simply zero out rb buffer to mitigate the problem. + +[1] Syzkaller report +dvb-usb: bulk message failed: -22 (6/0) +===================================================== +BUG: KMSAN: uninit-value in dib3000mb_attach+0x2d8/0x3c0 drivers/media/dvb-frontends/dib3000mb.c:758 + dib3000mb_attach+0x2d8/0x3c0 drivers/media/dvb-frontends/dib3000mb.c:758 + dibusb_dib3000mb_frontend_attach+0x155/0x2f0 drivers/media/usb/dvb-usb/dibusb-mb.c:31 + dvb_usb_adapter_frontend_init+0xed/0x9a0 drivers/media/usb/dvb-usb/dvb-usb-dvb.c:290 + dvb_usb_adapter_init drivers/media/usb/dvb-usb/dvb-usb-init.c:90 [inline] + dvb_usb_init drivers/media/usb/dvb-usb/dvb-usb-init.c:186 [inline] + dvb_usb_device_init+0x25a8/0x3760 drivers/media/usb/dvb-usb/dvb-usb-init.c:310 + dibusb_probe+0x46/0x250 drivers/media/usb/dvb-usb/dibusb-mb.c:110 +... +Local variable rb created at: + dib3000_read_reg+0x86/0x4e0 drivers/media/dvb-frontends/dib3000mb.c:54 + dib3000mb_attach+0x123/0x3c0 drivers/media/dvb-frontends/dib3000mb.c:758 +... + +Fixes: 74340b0a8bc6 ("V4L/DVB (4457): Remove dib3000-common-module") +Reported-by: syzbot+c88fc0ebe0d5935c70da@syzkaller.appspotmail.com +Signed-off-by: Nikita Zhandarovich +Link: https://lore.kernel.org/r/20240517155800.9881-1-n.zhandarovich@fintech.ru +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Sasha Levin +--- + drivers/media/dvb-frontends/dib3000mb.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/media/dvb-frontends/dib3000mb.c b/drivers/media/dvb-frontends/dib3000mb.c +index c598b2a63325..7c452ddd9e40 100644 +--- a/drivers/media/dvb-frontends/dib3000mb.c ++++ b/drivers/media/dvb-frontends/dib3000mb.c +@@ -51,7 +51,7 @@ MODULE_PARM_DESC(debug, "set debugging level (1=info,2=xfer,4=setfe,8=getfe (|-a + static int dib3000_read_reg(struct dib3000_state *state, u16 reg) + { + u8 wb[] = { ((reg >> 8) | 0x80) & 0xff, reg & 0xff }; +- u8 rb[2]; ++ u8 rb[2] = {}; + struct i2c_msg msg[] = { + { .addr = state->config.demod_address, .flags = 0, .buf = wb, .len = 2 }, + { .addr = state->config.demod_address, .flags = I2C_M_RD, .buf = rb, .len = 2 }, +-- +2.39.5 + diff --git a/queue-5.15/mm-vmstat-fix-a-w-1-clang-compiler-warning.patch b/queue-5.15/mm-vmstat-fix-a-w-1-clang-compiler-warning.patch new file mode 100644 index 00000000000..619130e5a1c --- /dev/null +++ b/queue-5.15/mm-vmstat-fix-a-w-1-clang-compiler-warning.patch @@ -0,0 +1,43 @@ +From 5bbbd02aef0fc45f6a4f643ad87c8d4be046c8e7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 12 Dec 2024 13:31:26 -0800 +Subject: mm/vmstat: fix a W=1 clang compiler warning + +From: Bart Van Assche + +[ Upstream commit 30c2de0a267c04046d89e678cc0067a9cfb455df ] + +Fix the following clang compiler warning that is reported if the kernel is +built with W=1: + +./include/linux/vmstat.h:518:36: error: arithmetic between different enumeration types ('enum node_stat_item' and 'enum lru_list') [-Werror,-Wenum-enum-conversion] + 518 | return node_stat_name(NR_LRU_BASE + lru) + 3; // skip "nr_" + | ~~~~~~~~~~~ ^ ~~~ + +Link: https://lkml.kernel.org/r/20241212213126.1269116-1-bvanassche@acm.org +Fixes: 9d7ea9a297e6 ("mm/vmstat: add helpers to get vmstat item names for each enum type") +Signed-off-by: Bart Van Assche +Cc: Konstantin Khlebnikov +Cc: Nathan Chancellor +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + include/linux/vmstat.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/include/linux/vmstat.h b/include/linux/vmstat.h +index d6a6cf53b127..bcb2b2b037c0 100644 +--- a/include/linux/vmstat.h ++++ b/include/linux/vmstat.h +@@ -447,7 +447,7 @@ static inline const char *node_stat_name(enum node_stat_item item) + + static inline const char *lru_list_name(enum lru_list lru) + { +- return node_stat_name(NR_LRU_BASE + lru) + 3; // skip "nr_" ++ return node_stat_name(NR_LRU_BASE + (enum node_stat_item)lru) + 3; // skip "nr_" + } + + static inline const char *writeback_stat_name(enum writeback_stat_item item) +-- +2.39.5 + diff --git a/queue-5.15/nfsd-restore-callback-functionality-for-nfsv4.0.patch b/queue-5.15/nfsd-restore-callback-functionality-for-nfsv4.0.patch new file mode 100644 index 00000000000..c7067803ea2 --- /dev/null +++ b/queue-5.15/nfsd-restore-callback-functionality-for-nfsv4.0.patch @@ -0,0 +1,51 @@ +From c3d06d7f827625fe1141b98e248ae3a1fb4aaf09 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Dec 2024 15:28:18 +1100 +Subject: nfsd: restore callback functionality for NFSv4.0 + +From: NeilBrown + +[ Upstream commit 7917f01a286ce01e9c085e24468421f596ee1a0c ] + +A recent patch inadvertently broke callbacks for NFSv4.0. + +In the 4.0 case we do not expect a session to be found but still need to +call setup_callback_client() which will not try to dereference it. + +This patch moves the check for failure to find a session into the 4.1+ +branch of setup_callback_client() + +Fixes: 1e02c641c3a4 ("NFSD: Prevent NULL dereference in nfsd4_process_cb_update()") +Signed-off-by: NeilBrown +Reviewed-by: Jeff Layton +Signed-off-by: Chuck Lever +Signed-off-by: Sasha Levin +--- + fs/nfsd/nfs4callback.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c +index a6dc8c479a4b..d2885dd4822d 100644 +--- a/fs/nfsd/nfs4callback.c ++++ b/fs/nfsd/nfs4callback.c +@@ -986,7 +986,7 @@ static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *c + args.authflavor = clp->cl_cred.cr_flavor; + clp->cl_cb_ident = conn->cb_ident; + } else { +- if (!conn->cb_xprt) ++ if (!conn->cb_xprt || !ses) + return -EINVAL; + clp->cl_cb_session = ses; + args.bc_xprt = conn->cb_xprt; +@@ -1379,8 +1379,6 @@ static void nfsd4_process_cb_update(struct nfsd4_callback *cb) + ses = c->cn_session; + } + spin_unlock(&clp->cl_lock); +- if (!c) +- return; + + err = setup_callback_client(clp, &conn, ses); + if (err) { +-- +2.39.5 + diff --git a/queue-5.15/series b/queue-5.15/series index 378304ed91b..d07edb7d071 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -54,3 +54,9 @@ of-fix-refcount-leakage-for-of-node-returned-by-__of_get_dma_parent.patch ceph-validate-snapdirname-option-length-when-mounting.patch epoll-add-synchronous-wakeup-support-for-ep_poll_callback.patch drm-amdgpu-handle-null-bo-tbo.resource-again-in-amdgpu_vm_bo_update.patch +media-dvb-frontends-dib3000mb-fix-uninit-value-in-di.patch +mm-vmstat-fix-a-w-1-clang-compiler-warning.patch +tcp_bpf-charge-receive-socket-buffer-in-bpf_tcp_ingr.patch +tcp_bpf-add-sk_rmem_alloc-related-logic-for-tcp_bpf-.patch +bpf-check-negative-offsets-in-__bpf_skb_min_len.patch +nfsd-restore-callback-functionality-for-nfsv4.0.patch diff --git a/queue-5.15/tcp_bpf-add-sk_rmem_alloc-related-logic-for-tcp_bpf-.patch b/queue-5.15/tcp_bpf-add-sk_rmem_alloc-related-logic-for-tcp_bpf-.patch new file mode 100644 index 00000000000..9087fa01b2e --- /dev/null +++ b/queue-5.15/tcp_bpf-add-sk_rmem_alloc-related-logic-for-tcp_bpf-.patch @@ -0,0 +1,116 @@ +From b5937b443a9ae99c95a947908fc76e3d775dc6a7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 10 Dec 2024 01:20:39 +0000 +Subject: tcp_bpf: Add sk_rmem_alloc related logic for tcp_bpf ingress + redirection + +From: Zijian Zhang + +[ Upstream commit d888b7af7c149c115dd6ac772cc11c375da3e17c ] + +When we do sk_psock_verdict_apply->sk_psock_skb_ingress, an sk_msg will +be created out of the skb, and the rmem accounting of the sk_msg will be +handled by the skb. + +For skmsgs in __SK_REDIRECT case of tcp_bpf_send_verdict, when redirecting +to the ingress of a socket, although we sk_rmem_schedule and add sk_msg to +the ingress_msg of sk_redir, we do not update sk_rmem_alloc. As a result, +except for the global memory limit, the rmem of sk_redir is nearly +unlimited. Thus, add sk_rmem_alloc related logic to limit the recv buffer. + +Since the function sk_msg_recvmsg and __sk_psock_purge_ingress_msg are +used in these two paths. We use "msg->skb" to test whether the sk_msg is +skb backed up. If it's not, we shall do the memory accounting explicitly. + +Fixes: 604326b41a6f ("bpf, sockmap: convert to generic sk_msg interface") +Signed-off-by: Zijian Zhang +Signed-off-by: Daniel Borkmann +Reviewed-by: John Fastabend +Link: https://lore.kernel.org/bpf/20241210012039.1669389-3-zijianzhang@bytedance.com +Signed-off-by: Sasha Levin +--- + include/linux/skmsg.h | 11 ++++++++--- + net/core/skmsg.c | 6 +++++- + net/ipv4/tcp_bpf.c | 4 +++- + 3 files changed, 16 insertions(+), 5 deletions(-) + +diff --git a/include/linux/skmsg.h b/include/linux/skmsg.h +index 422b391d931f..5d3e4d4d9438 100644 +--- a/include/linux/skmsg.h ++++ b/include/linux/skmsg.h +@@ -313,17 +313,22 @@ static inline void sock_drop(struct sock *sk, struct sk_buff *skb) + kfree_skb(skb); + } + +-static inline void sk_psock_queue_msg(struct sk_psock *psock, ++static inline bool sk_psock_queue_msg(struct sk_psock *psock, + struct sk_msg *msg) + { ++ bool ret; ++ + spin_lock_bh(&psock->ingress_lock); +- if (sk_psock_test_state(psock, SK_PSOCK_TX_ENABLED)) ++ if (sk_psock_test_state(psock, SK_PSOCK_TX_ENABLED)) { + list_add_tail(&msg->list, &psock->ingress_msg); +- else { ++ ret = true; ++ } else { + sk_msg_free(psock->sk, msg); + kfree(msg); ++ ret = false; + } + spin_unlock_bh(&psock->ingress_lock); ++ return ret; + } + + static inline struct sk_msg *sk_psock_dequeue_msg(struct sk_psock *psock) +diff --git a/net/core/skmsg.c b/net/core/skmsg.c +index f8563d4da0b1..a5947aa55983 100644 +--- a/net/core/skmsg.c ++++ b/net/core/skmsg.c +@@ -445,8 +445,10 @@ int sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghdr *msg, + if (likely(!peek)) { + sge->offset += copy; + sge->length -= copy; +- if (!msg_rx->skb) ++ if (!msg_rx->skb) { + sk_mem_uncharge(sk, copy); ++ atomic_sub(copy, &sk->sk_rmem_alloc); ++ } + msg_rx->sg.size -= copy; + + if (!sge->length) { +@@ -761,6 +763,8 @@ static void __sk_psock_purge_ingress_msg(struct sk_psock *psock) + + list_for_each_entry_safe(msg, tmp, &psock->ingress_msg, list) { + list_del(&msg->list); ++ if (!msg->skb) ++ atomic_sub(msg->sg.size, &psock->sk->sk_rmem_alloc); + sk_msg_free(psock->sk, msg); + kfree(msg); + } +diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c +index dc1291827381..9e24542251b1 100644 +--- a/net/ipv4/tcp_bpf.c ++++ b/net/ipv4/tcp_bpf.c +@@ -38,6 +38,7 @@ static int bpf_tcp_ingress(struct sock *sk, struct sk_psock *psock, + } + + sk_mem_charge(sk, size); ++ atomic_add(size, &sk->sk_rmem_alloc); + sk_msg_xfer(tmp, msg, i, size); + copied += size; + if (sge->length) +@@ -56,7 +57,8 @@ static int bpf_tcp_ingress(struct sock *sk, struct sk_psock *psock, + + if (!ret) { + msg->sg.start = i; +- sk_psock_queue_msg(psock, tmp); ++ if (!sk_psock_queue_msg(psock, tmp)) ++ atomic_sub(copied, &sk->sk_rmem_alloc); + sk_psock_data_ready(sk, psock); + } else { + sk_msg_free(sk, tmp); +-- +2.39.5 + diff --git a/queue-5.15/tcp_bpf-charge-receive-socket-buffer-in-bpf_tcp_ingr.patch b/queue-5.15/tcp_bpf-charge-receive-socket-buffer-in-bpf_tcp_ingr.patch new file mode 100644 index 00000000000..435a4f2a467 --- /dev/null +++ b/queue-5.15/tcp_bpf-charge-receive-socket-buffer-in-bpf_tcp_ingr.patch @@ -0,0 +1,71 @@ +From 88e46ac4db8980e218bc750de94d14deb69364d7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 10 Dec 2024 01:20:38 +0000 +Subject: tcp_bpf: Charge receive socket buffer in bpf_tcp_ingress() + +From: Cong Wang + +[ Upstream commit 54f89b3178d5448dd4457afbb98fc1ab99090a65 ] + +When bpf_tcp_ingress() is called, the skmsg is being redirected to the +ingress of the destination socket. Therefore, we should charge its +receive socket buffer, instead of sending socket buffer. + +Because sk_rmem_schedule() tests pfmemalloc of skb, we need to +introduce a wrapper and call it for skmsg. + +Fixes: 604326b41a6f ("bpf, sockmap: convert to generic sk_msg interface") +Signed-off-by: Cong Wang +Signed-off-by: Daniel Borkmann +Reviewed-by: John Fastabend +Link: https://lore.kernel.org/bpf/20241210012039.1669389-2-zijianzhang@bytedance.com +Signed-off-by: Sasha Levin +--- + include/net/sock.h | 10 ++++++++-- + net/ipv4/tcp_bpf.c | 2 +- + 2 files changed, 9 insertions(+), 3 deletions(-) + +diff --git a/include/net/sock.h b/include/net/sock.h +index 1680d6dc4d19..ca3cc2b325d7 100644 +--- a/include/net/sock.h ++++ b/include/net/sock.h +@@ -1570,7 +1570,7 @@ static inline bool sk_wmem_schedule(struct sock *sk, int size) + } + + static inline bool +-sk_rmem_schedule(struct sock *sk, struct sk_buff *skb, int size) ++__sk_rmem_schedule(struct sock *sk, int size, bool pfmemalloc) + { + int delta; + +@@ -1578,7 +1578,13 @@ sk_rmem_schedule(struct sock *sk, struct sk_buff *skb, int size) + return true; + delta = size - sk->sk_forward_alloc; + return delta <= 0 || __sk_mem_schedule(sk, delta, SK_MEM_RECV) || +- skb_pfmemalloc(skb); ++ pfmemalloc; ++} ++ ++static inline bool ++sk_rmem_schedule(struct sock *sk, struct sk_buff *skb, int size) ++{ ++ return __sk_rmem_schedule(sk, size, skb_pfmemalloc(skb)); + } + + static inline void sk_mem_reclaim(struct sock *sk) +diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c +index f2ae1e51e59f..dc1291827381 100644 +--- a/net/ipv4/tcp_bpf.c ++++ b/net/ipv4/tcp_bpf.c +@@ -31,7 +31,7 @@ static int bpf_tcp_ingress(struct sock *sk, struct sk_psock *psock, + sge = sk_msg_elem(msg, i); + size = (apply && apply_bytes < sge->length) ? + apply_bytes : sge->length; +- if (!sk_wmem_schedule(sk, size)) { ++ if (!__sk_rmem_schedule(sk, size, false)) { + if (!copied) + ret = -ENOMEM; + break; +-- +2.39.5 +