From: Sasha Levin Date: Sun, 23 Feb 2025 17:23:14 +0000 (-0500) Subject: Fixes for 6.1 X-Git-Tag: v6.6.80~25^2~6 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=07212de167018dc163c5ad43104ee7c4f7dda78a;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 6.1 Signed-off-by: Sasha Levin --- diff --git a/queue-6.1/bpf-fix-wrong-copied_seq-calculation.patch b/queue-6.1/bpf-fix-wrong-copied_seq-calculation.patch new file mode 100644 index 0000000000..54950a6fdb --- /dev/null +++ b/queue-6.1/bpf-fix-wrong-copied_seq-calculation.patch @@ -0,0 +1,235 @@ +From 4ba89f611b0bec08769d7a16521ed9a90c3a03c9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Jan 2025 18:09:14 +0800 +Subject: bpf: Fix wrong copied_seq calculation +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Jiayuan Chen + +[ Upstream commit 36b62df5683c315ba58c950f1a9c771c796c30ec ] + +'sk->copied_seq' was updated in the tcp_eat_skb() function when the action +of a BPF program was SK_REDIRECT. For other actions, like SK_PASS, the +update logic for 'sk->copied_seq' was moved to tcp_bpf_recvmsg_parser() +to ensure the accuracy of the 'fionread' feature. + +It works for a single stream_verdict scenario, as it also modified +sk_data_ready->sk_psock_verdict_data_ready->tcp_read_skb +to remove updating 'sk->copied_seq'. + +However, for programs where both stream_parser and stream_verdict are +active (strparser purpose), tcp_read_sock() was used instead of +tcp_read_skb() (sk_data_ready->strp_data_ready->tcp_read_sock). +tcp_read_sock() now still updates 'sk->copied_seq', leading to duplicate +updates. + +In summary, for strparser + SK_PASS, copied_seq is redundantly calculated +in both tcp_read_sock() and tcp_bpf_recvmsg_parser(). + +The issue causes incorrect copied_seq calculations, which prevent +correct data reads from the recv() interface in user-land. + +We do not want to add new proto_ops to implement a new version of +tcp_read_sock, as this would introduce code complexity [1]. + +We could have added noack and copied_seq to desc, and then called +ops->read_sock. However, unfortunately, other modules didn’t fully +initialize desc to zero. So, for now, we are directly calling +tcp_read_sock_noack() in tcp_bpf.c. + +[1]: https://lore.kernel.org/bpf/20241218053408.437295-1-mrpre@163.com + +Fixes: e5c6de5fa025 ("bpf, sockmap: Incorrectly handling copied_seq") +Suggested-by: Jakub Sitnicki +Signed-off-by: Jiayuan Chen +Signed-off-by: Martin KaFai Lau +Reviewed-by: Jakub Sitnicki +Acked-by: John Fastabend +Link: https://patch.msgid.link/20250122100917.49845-3-mrpre@163.com +Signed-off-by: Sasha Levin +--- + include/linux/skmsg.h | 2 ++ + include/net/tcp.h | 8 ++++++++ + net/core/skmsg.c | 7 +++++++ + net/ipv4/tcp.c | 29 ++++++++++++++++++++++++----- + net/ipv4/tcp_bpf.c | 36 ++++++++++++++++++++++++++++++++++++ + 5 files changed, 77 insertions(+), 5 deletions(-) + +diff --git a/include/linux/skmsg.h b/include/linux/skmsg.h +index 6ccfd9236387c..32bbebf5b71e3 100644 +--- a/include/linux/skmsg.h ++++ b/include/linux/skmsg.h +@@ -87,6 +87,8 @@ struct sk_psock { + struct sk_psock_progs progs; + #if IS_ENABLED(CONFIG_BPF_STREAM_PARSER) + struct strparser strp; ++ u32 copied_seq; ++ u32 ingress_bytes; + #endif + struct sk_buff_head ingress_skb; + struct list_head ingress_msg; +diff --git a/include/net/tcp.h b/include/net/tcp.h +index 14a00cdd31f42..83e0362e3b721 100644 +--- a/include/net/tcp.h ++++ b/include/net/tcp.h +@@ -700,6 +700,9 @@ void tcp_get_info(struct sock *, struct tcp_info *); + /* Read 'sendfile()'-style from a TCP socket */ + int tcp_read_sock(struct sock *sk, read_descriptor_t *desc, + sk_read_actor_t recv_actor); ++int tcp_read_sock_noack(struct sock *sk, read_descriptor_t *desc, ++ sk_read_actor_t recv_actor, bool noack, ++ u32 *copied_seq); + int tcp_read_skb(struct sock *sk, skb_read_actor_t recv_actor); + struct sk_buff *tcp_recv_skb(struct sock *sk, u32 seq, u32 *off); + void tcp_read_done(struct sock *sk, size_t len); +@@ -2351,6 +2354,11 @@ struct sk_psock; + struct proto *tcp_bpf_get_proto(struct sock *sk, struct sk_psock *psock); + int tcp_bpf_update_proto(struct sock *sk, struct sk_psock *psock, bool restore); + void tcp_bpf_clone(const struct sock *sk, struct sock *newsk); ++#ifdef CONFIG_BPF_STREAM_PARSER ++struct strparser; ++int tcp_bpf_strp_read_sock(struct strparser *strp, read_descriptor_t *desc, ++ sk_read_actor_t recv_actor); ++#endif /* CONFIG_BPF_STREAM_PARSER */ + #endif /* CONFIG_BPF_SYSCALL */ + + #ifdef CONFIG_INET +diff --git a/net/core/skmsg.c b/net/core/skmsg.c +index 65764952bc681..5a790cd1121b1 100644 +--- a/net/core/skmsg.c ++++ b/net/core/skmsg.c +@@ -547,6 +547,9 @@ static int sk_psock_skb_ingress_enqueue(struct sk_buff *skb, + return num_sge; + } + ++#if IS_ENABLED(CONFIG_BPF_STREAM_PARSER) ++ psock->ingress_bytes += len; ++#endif + copied = len; + msg->sg.start = 0; + msg->sg.size = copied; +@@ -1140,6 +1143,10 @@ int sk_psock_init_strp(struct sock *sk, struct sk_psock *psock) + if (!ret) + sk_psock_set_state(psock, SK_PSOCK_RX_STRP_ENABLED); + ++ if (sk_is_tcp(sk)) { ++ psock->strp.cb.read_sock = tcp_bpf_strp_read_sock; ++ psock->copied_seq = tcp_sk(sk)->copied_seq; ++ } + return ret; + } + +diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c +index e27a9a9bb1623..7d591a0cf0c70 100644 +--- a/net/ipv4/tcp.c ++++ b/net/ipv4/tcp.c +@@ -1699,12 +1699,13 @@ EXPORT_SYMBOL(tcp_recv_skb); + * or for 'peeking' the socket using this routine + * (although both would be easy to implement). + */ +-int tcp_read_sock(struct sock *sk, read_descriptor_t *desc, +- sk_read_actor_t recv_actor) ++static int __tcp_read_sock(struct sock *sk, read_descriptor_t *desc, ++ sk_read_actor_t recv_actor, bool noack, ++ u32 *copied_seq) + { + struct sk_buff *skb; + struct tcp_sock *tp = tcp_sk(sk); +- u32 seq = tp->copied_seq; ++ u32 seq = *copied_seq; + u32 offset; + int copied = 0; + +@@ -1758,9 +1759,12 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc, + tcp_eat_recv_skb(sk, skb); + if (!desc->count) + break; +- WRITE_ONCE(tp->copied_seq, seq); ++ WRITE_ONCE(*copied_seq, seq); + } +- WRITE_ONCE(tp->copied_seq, seq); ++ WRITE_ONCE(*copied_seq, seq); ++ ++ if (noack) ++ goto out; + + tcp_rcv_space_adjust(sk); + +@@ -1769,10 +1773,25 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc, + tcp_recv_skb(sk, seq, &offset); + tcp_cleanup_rbuf(sk, copied); + } ++out: + return copied; + } ++ ++int tcp_read_sock(struct sock *sk, read_descriptor_t *desc, ++ sk_read_actor_t recv_actor) ++{ ++ return __tcp_read_sock(sk, desc, recv_actor, false, ++ &tcp_sk(sk)->copied_seq); ++} + EXPORT_SYMBOL(tcp_read_sock); + ++int tcp_read_sock_noack(struct sock *sk, read_descriptor_t *desc, ++ sk_read_actor_t recv_actor, bool noack, ++ u32 *copied_seq) ++{ ++ return __tcp_read_sock(sk, desc, recv_actor, noack, copied_seq); ++} ++ + int tcp_read_skb(struct sock *sk, skb_read_actor_t recv_actor) + { + struct sk_buff *skb; +diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c +index a8db010e9e611..bf10fa3c37b76 100644 +--- a/net/ipv4/tcp_bpf.c ++++ b/net/ipv4/tcp_bpf.c +@@ -691,6 +691,42 @@ static int tcp_bpf_assert_proto_ops(struct proto *ops) + ops->sendpage == tcp_sendpage ? 0 : -ENOTSUPP; + } + ++#if IS_ENABLED(CONFIG_BPF_STREAM_PARSER) ++int tcp_bpf_strp_read_sock(struct strparser *strp, read_descriptor_t *desc, ++ sk_read_actor_t recv_actor) ++{ ++ struct sock *sk = strp->sk; ++ struct sk_psock *psock; ++ struct tcp_sock *tp; ++ int copied = 0; ++ ++ tp = tcp_sk(sk); ++ rcu_read_lock(); ++ psock = sk_psock(sk); ++ if (WARN_ON_ONCE(!psock)) { ++ desc->error = -EINVAL; ++ goto out; ++ } ++ ++ psock->ingress_bytes = 0; ++ copied = tcp_read_sock_noack(sk, desc, recv_actor, true, ++ &psock->copied_seq); ++ if (copied < 0) ++ goto out; ++ /* recv_actor may redirect skb to another socket (SK_REDIRECT) or ++ * just put skb into ingress queue of current socket (SK_PASS). ++ * For SK_REDIRECT, we need to ack the frame immediately but for ++ * SK_PASS, we want to delay the ack until tcp_bpf_recvmsg_parser(). ++ */ ++ tp->copied_seq = psock->copied_seq - psock->ingress_bytes; ++ tcp_rcv_space_adjust(sk); ++ __tcp_cleanup_rbuf(sk, copied - psock->ingress_bytes); ++out: ++ rcu_read_unlock(); ++ return copied; ++} ++#endif /* CONFIG_BPF_STREAM_PARSER */ ++ + int tcp_bpf_update_proto(struct sock *sk, struct sk_psock *psock, bool restore) + { + int family = sk->sk_family == AF_INET6 ? TCP_BPF_IPV6 : TCP_BPF_IPV4; +-- +2.39.5 + diff --git a/queue-6.1/bpf-skip-non-exist-keys-in-generic_map_lookup_batch.patch b/queue-6.1/bpf-skip-non-exist-keys-in-generic_map_lookup_batch.patch new file mode 100644 index 0000000000..5767f2ccbe --- /dev/null +++ b/queue-6.1/bpf-skip-non-exist-keys-in-generic_map_lookup_batch.patch @@ -0,0 +1,119 @@ +From b4441f8c3e8c14e3028a04061157e310b925cbdf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Feb 2025 23:22:35 -0800 +Subject: bpf: skip non exist keys in generic_map_lookup_batch + +From: Yan Zhai + +[ Upstream commit 5644c6b50ffee0a56c1e01430a8c88e34decb120 ] + +The generic_map_lookup_batch currently returns EINTR if it fails with +ENOENT and retries several times on bpf_map_copy_value. The next batch +would start from the same location, presuming it's a transient issue. +This is incorrect if a map can actually have "holes", i.e. +"get_next_key" can return a key that does not point to a valid value. At +least the array of maps type may contain such holes legitly. Right now +these holes show up, generic batch lookup cannot proceed any more. It +will always fail with EINTR errors. + +Rather, do not retry in generic_map_lookup_batch. If it finds a non +existing element, skip to the next key. This simple solution comes with +a price that transient errors may not be recovered, and the iteration +might cycle back to the first key under parallel deletion. For example, +Hou Tao pointed out a following scenario: + +For LPM trie map: +(1) ->map_get_next_key(map, prev_key, key) returns a valid key + +(2) bpf_map_copy_value() return -ENOMENT +It means the key must be deleted concurrently. + +(3) goto next_key +It swaps the prev_key and key + +(4) ->map_get_next_key(map, prev_key, key) again +prev_key points to a non-existing key, for LPM trie it will treat just +like prev_key=NULL case, the returned key will be duplicated. + +With the retry logic, the iteration can continue to the key next to the +deleted one. But if we directly skip to the next key, the iteration loop +would restart from the first key for the lpm_trie type. + +However, not all races may be recovered. For example, if current key is +deleted after instead of before bpf_map_copy_value, or if the prev_key +also gets deleted, then the loop will still restart from the first key +for lpm_tire anyway. For generic lookup it might be better to stay +simple, i.e. just skip to the next key. To guarantee that the output +keys are not duplicated, it is better to implement map type specific +batch operations, which can properly lock the trie and synchronize with +concurrent mutators. + +Fixes: cb4d03ab499d ("bpf: Add generic support for lookup batch op") +Closes: https://lore.kernel.org/bpf/Z6JXtA1M5jAZx8xD@debian.debian/ +Signed-off-by: Yan Zhai +Acked-by: Hou Tao +Link: https://lore.kernel.org/r/85618439eea75930630685c467ccefeac0942e2b.1739171594.git.yan@cloudflare.com +Signed-off-by: Alexei Starovoitov +Signed-off-by: Sasha Levin +--- + kernel/bpf/syscall.c | 18 +++++------------- + 1 file changed, 5 insertions(+), 13 deletions(-) + +diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c +index cfb361f4b00ea..7a4004f09bae7 100644 +--- a/kernel/bpf/syscall.c ++++ b/kernel/bpf/syscall.c +@@ -1713,8 +1713,6 @@ int generic_map_update_batch(struct bpf_map *map, + return err; + } + +-#define MAP_LOOKUP_RETRIES 3 +- + int generic_map_lookup_batch(struct bpf_map *map, + const union bpf_attr *attr, + union bpf_attr __user *uattr) +@@ -1724,8 +1722,8 @@ int generic_map_lookup_batch(struct bpf_map *map, + void __user *values = u64_to_user_ptr(attr->batch.values); + void __user *keys = u64_to_user_ptr(attr->batch.keys); + void *buf, *buf_prevkey, *prev_key, *key, *value; +- int err, retry = MAP_LOOKUP_RETRIES; + u32 value_size, cp, max_count; ++ int err; + + if (attr->batch.elem_flags & ~BPF_F_LOCK) + return -EINVAL; +@@ -1771,14 +1769,8 @@ int generic_map_lookup_batch(struct bpf_map *map, + err = bpf_map_copy_value(map, key, value, + attr->batch.elem_flags); + +- if (err == -ENOENT) { +- if (retry) { +- retry--; +- continue; +- } +- err = -EINTR; +- break; +- } ++ if (err == -ENOENT) ++ goto next_key; + + if (err) + goto free_buf; +@@ -1793,12 +1785,12 @@ int generic_map_lookup_batch(struct bpf_map *map, + goto free_buf; + } + ++ cp++; ++next_key: + if (!prev_key) + prev_key = buf_prevkey; + + swap(prev_key, key); +- retry = MAP_LOOKUP_RETRIES; +- cp++; + cond_resched(); + } + +-- +2.39.5 + diff --git a/queue-6.1/bpf-test_run-fix-use-after-free-issue-in-eth_skb_pkt.patch b/queue-6.1/bpf-test_run-fix-use-after-free-issue-in-eth_skb_pkt.patch new file mode 100644 index 0000000000..e093882b73 --- /dev/null +++ b/queue-6.1/bpf-test_run-fix-use-after-free-issue-in-eth_skb_pkt.patch @@ -0,0 +1,92 @@ +From c059a561f85a2ee9662e56feeaf8bc3484520f14 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Jan 2025 00:06:42 +0900 +Subject: bpf, test_run: Fix use-after-free issue in eth_skb_pkt_type() + +From: Shigeru Yoshida + +[ Upstream commit 6b3d638ca897e099fa99bd6d02189d3176f80a47 ] + +KMSAN reported a use-after-free issue in eth_skb_pkt_type()[1]. The +cause of the issue was that eth_skb_pkt_type() accessed skb's data +that didn't contain an Ethernet header. This occurs when +bpf_prog_test_run_xdp() passes an invalid value as the user_data +argument to bpf_test_init(). + +Fix this by returning an error when user_data is less than ETH_HLEN in +bpf_test_init(). Additionally, remove the check for "if (user_size > +size)" as it is unnecessary. + +[1] +BUG: KMSAN: use-after-free in eth_skb_pkt_type include/linux/etherdevice.h:627 [inline] +BUG: KMSAN: use-after-free in eth_type_trans+0x4ee/0x980 net/ethernet/eth.c:165 + eth_skb_pkt_type include/linux/etherdevice.h:627 [inline] + eth_type_trans+0x4ee/0x980 net/ethernet/eth.c:165 + __xdp_build_skb_from_frame+0x5a8/0xa50 net/core/xdp.c:635 + xdp_recv_frames net/bpf/test_run.c:272 [inline] + xdp_test_run_batch net/bpf/test_run.c:361 [inline] + bpf_test_run_xdp_live+0x2954/0x3330 net/bpf/test_run.c:390 + bpf_prog_test_run_xdp+0x148e/0x1b10 net/bpf/test_run.c:1318 + bpf_prog_test_run+0x5b7/0xa30 kernel/bpf/syscall.c:4371 + __sys_bpf+0x6a6/0xe20 kernel/bpf/syscall.c:5777 + __do_sys_bpf kernel/bpf/syscall.c:5866 [inline] + __se_sys_bpf kernel/bpf/syscall.c:5864 [inline] + __x64_sys_bpf+0xa4/0xf0 kernel/bpf/syscall.c:5864 + x64_sys_call+0x2ea0/0x3d90 arch/x86/include/generated/asm/syscalls_64.h:322 + do_syscall_x64 arch/x86/entry/common.c:52 [inline] + do_syscall_64+0xd9/0x1d0 arch/x86/entry/common.c:83 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +Uninit was created at: + free_pages_prepare mm/page_alloc.c:1056 [inline] + free_unref_page+0x156/0x1320 mm/page_alloc.c:2657 + __free_pages+0xa3/0x1b0 mm/page_alloc.c:4838 + bpf_ringbuf_free kernel/bpf/ringbuf.c:226 [inline] + ringbuf_map_free+0xff/0x1e0 kernel/bpf/ringbuf.c:235 + bpf_map_free kernel/bpf/syscall.c:838 [inline] + bpf_map_free_deferred+0x17c/0x310 kernel/bpf/syscall.c:862 + process_one_work kernel/workqueue.c:3229 [inline] + process_scheduled_works+0xa2b/0x1b60 kernel/workqueue.c:3310 + worker_thread+0xedf/0x1550 kernel/workqueue.c:3391 + kthread+0x535/0x6b0 kernel/kthread.c:389 + ret_from_fork+0x6e/0x90 arch/x86/kernel/process.c:147 + ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244 + +CPU: 1 UID: 0 PID: 17276 Comm: syz.1.16450 Not tainted 6.12.0-05490-g9bb88c659673 #8 +Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.3-3.fc41 04/01/2014 + +Fixes: be3d72a2896c ("bpf: move user_size out of bpf_test_init") +Reported-by: syzkaller +Suggested-by: Martin KaFai Lau +Signed-off-by: Shigeru Yoshida +Signed-off-by: Martin KaFai Lau +Acked-by: Stanislav Fomichev +Acked-by: Daniel Borkmann +Link: https://patch.msgid.link/20250121150643.671650-1-syoshida@redhat.com +Signed-off-by: Alexei Starovoitov +Signed-off-by: Sasha Levin +--- + net/bpf/test_run.c | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +diff --git a/net/bpf/test_run.c b/net/bpf/test_run.c +index 64be562f0fe32..77b386b76d463 100644 +--- a/net/bpf/test_run.c ++++ b/net/bpf/test_run.c +@@ -768,12 +768,9 @@ static void *bpf_test_init(const union bpf_attr *kattr, u32 user_size, + void __user *data_in = u64_to_user_ptr(kattr->test.data_in); + void *data; + +- if (size < ETH_HLEN || size > PAGE_SIZE - headroom - tailroom) ++ if (user_size < ETH_HLEN || user_size > PAGE_SIZE - headroom - tailroom) + return ERR_PTR(-EINVAL); + +- if (user_size > size) +- return ERR_PTR(-EMSGSIZE); +- + size = SKB_DATA_ALIGN(size); + data = kzalloc(size + headroom + tailroom, GFP_USER); + if (!data) +-- +2.39.5 + diff --git a/queue-6.1/drm-msm-dpu-don-t-leak-bits_per_component-into-rando.patch b/queue-6.1/drm-msm-dpu-don-t-leak-bits_per_component-into-rando.patch new file mode 100644 index 0000000000..379cde2ab5 --- /dev/null +++ b/queue-6.1/drm-msm-dpu-don-t-leak-bits_per_component-into-rando.patch @@ -0,0 +1,68 @@ +From 6fdd147fbbeaba75054c07587f90649ff8a189a0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Feb 2025 00:19:32 +0100 +Subject: drm/msm/dpu: Don't leak bits_per_component into random DSC_ENC fields + +From: Marijn Suijten + +[ Upstream commit 144429831f447223253a0e4376489f84ff37d1a7 ] + +What used to be the input_10_bits boolean - feeding into the lowest +bit of DSC_ENC - on MSM downstream turned into an accidental OR with +the full bits_per_component number when it was ported to the upstream +kernel. + +On typical bpc=8 setups we don't notice this because line_buf_depth is +always an odd value (it contains bpc+1) and will also set the 4th bit +after left-shifting by 3 (hence this |= bits_per_component is a no-op). + +Now that guards are being removed to allow more bits_per_component +values besides 8 (possible since commit 49fd30a7153b ("drm/msm/dsi: use +DRM DSC helpers for DSC setup")), a bpc of 10 will instead clash with +the 5th bit which is convert_rgb. This is "fortunately" also always set +to true by MSM's dsi_populate_dsc_params() already, but once a bpc of 12 +starts being used it'll write into simple_422 which is normally false. + +To solve all these overlaps, simply replicate downstream code and only +set this lowest bit if bits_per_component is equal to 10. It is unclear +why DSC requires this only for bpc=10 but not bpc=12, and also notice +that this lowest bit wasn't set previously despite having a panel and +patch on the list using it without any mentioned issues. + +Fixes: c110cfd1753e ("drm/msm/disp/dpu1: Add support for DSC") +Signed-off-by: Marijn Suijten +Reviewed-by: Abhinav Kumar +Reviewed-by: Konrad Dybcio +Reviewed-by: Dmitry Baryshkov +Patchwork: https://patchwork.freedesktop.org/patch/636311/ +Link: https://lore.kernel.org/r/20250211-dsc-10-bit-v1-1-1c85a9430d9a@somainline.org +Signed-off-by: Abhinav Kumar +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c +index c8f14555834a8..70a6dfe94faa5 100644 +--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c ++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c +@@ -46,6 +46,7 @@ static void dpu_hw_dsc_config(struct dpu_hw_dsc *hw_dsc, + u32 slice_last_group_size; + u32 det_thresh_flatness; + bool is_cmd_mode = !(mode & DSC_MODE_VIDEO); ++ bool input_10_bits = dsc->bits_per_component == 10; + + DPU_REG_WRITE(c, DSC_COMMON_MODE, mode); + +@@ -62,7 +63,7 @@ static void dpu_hw_dsc_config(struct dpu_hw_dsc *hw_dsc, + data |= (dsc->line_buf_depth << 3); + data |= (dsc->simple_422 << 2); + data |= (dsc->convert_rgb << 1); +- data |= dsc->bits_per_component; ++ data |= input_10_bits; + + DPU_REG_WRITE(c, DSC_ENC, data); + +-- +2.39.5 + diff --git a/queue-6.1/drm-rcar-du-dsi-fix-phy-lock-bit-check.patch b/queue-6.1/drm-rcar-du-dsi-fix-phy-lock-bit-check.patch new file mode 100644 index 0000000000..686494f4b8 --- /dev/null +++ b/queue-6.1/drm-rcar-du-dsi-fix-phy-lock-bit-check.patch @@ -0,0 +1,58 @@ +From a27fddcdeed6b8198026182cf6f0af3296ea1c8b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 17 Dec 2024 07:31:35 +0200 +Subject: drm/rcar-du: dsi: Fix PHY lock bit check + +From: Tomi Valkeinen + +[ Upstream commit 6389e616fae8a101ce00068f7690461ab57b29d8 ] + +The driver checks for bit 16 (using CLOCKSET1_LOCK define) in CLOCKSET1 +register when waiting for the PPI clock. However, the right bit to check +is bit 17 (CLOCKSET1_LOCK_PHY define). Not only that, but there's +nothing in the documents for bit 16 for V3U nor V4H. + +So, fix the check to use bit 17, and drop the define for bit 16. + +Fixes: 155358310f01 ("drm: rcar-du: Add R-Car DSI driver") +Fixes: 11696c5e8924 ("drm: Place Renesas drivers in a separate dir") +Cc: stable@vger.kernel.org +Signed-off-by: Tomi Valkeinen +Reviewed-by: Laurent Pinchart +Tested-by: Geert Uytterhoeven +Signed-off-by: Tomi Valkeinen +Link: https://patchwork.freedesktop.org/patch/msgid/20241217-rcar-gh-dsi-v5-1-e77421093c05@ideasonboard.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c | 2 +- + drivers/gpu/drm/rcar-du/rcar_mipi_dsi_regs.h | 1 - + 2 files changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c b/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c +index a7f2b7f66a176..9ec9c43971dfb 100644 +--- a/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c ++++ b/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c +@@ -396,7 +396,7 @@ static int rcar_mipi_dsi_startup(struct rcar_mipi_dsi *dsi, + for (timeout = 10; timeout > 0; --timeout) { + if ((rcar_mipi_dsi_read(dsi, PPICLSR) & PPICLSR_STPST) && + (rcar_mipi_dsi_read(dsi, PPIDLSR) & PPIDLSR_STPST) && +- (rcar_mipi_dsi_read(dsi, CLOCKSET1) & CLOCKSET1_LOCK)) ++ (rcar_mipi_dsi_read(dsi, CLOCKSET1) & CLOCKSET1_LOCK_PHY)) + break; + + usleep_range(1000, 2000); +diff --git a/drivers/gpu/drm/rcar-du/rcar_mipi_dsi_regs.h b/drivers/gpu/drm/rcar-du/rcar_mipi_dsi_regs.h +index 2eaca54636f3d..1f1eb46c721fe 100644 +--- a/drivers/gpu/drm/rcar-du/rcar_mipi_dsi_regs.h ++++ b/drivers/gpu/drm/rcar-du/rcar_mipi_dsi_regs.h +@@ -141,7 +141,6 @@ + + #define CLOCKSET1 0x101c + #define CLOCKSET1_LOCK_PHY (1 << 17) +-#define CLOCKSET1_LOCK (1 << 16) + #define CLOCKSET1_CLKSEL (1 << 8) + #define CLOCKSET1_CLKINSEL_EXTAL (0 << 2) + #define CLOCKSET1_CLKINSEL_DIG (1 << 2) +-- +2.39.5 + diff --git a/queue-6.1/drm-tidss-add-simple-k2g-manual-reset.patch b/queue-6.1/drm-tidss-add-simple-k2g-manual-reset.patch new file mode 100644 index 0000000000..2e391e2191 --- /dev/null +++ b/queue-6.1/drm-tidss-add-simple-k2g-manual-reset.patch @@ -0,0 +1,59 @@ +From 7cb0236996b50bb54fd1c5f2944484af3ef72eca Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 Nov 2023 09:38:00 +0200 +Subject: drm/tidss: Add simple K2G manual reset + +From: Tomi Valkeinen + +[ Upstream commit 576d96c5c896221b5bc8feae473739469a92e144 ] + +K2G display controller does not support soft reset, but we can do the +most important steps manually: mask the IRQs and disable the VPs. + +Reviewed-by: Aradhya Bhatia +Link: https://lore.kernel.org/r/20231109-tidss-probe-v2-7-ac91b5ea35c0@ideasonboard.com +Signed-off-by: Tomi Valkeinen +Stable-dep-of: a9a73f2661e6 ("drm/tidss: Fix race condition while handling interrupt registers") +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/tidss/tidss_dispc.c | 18 ++++++++++++++++-- + 1 file changed, 16 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/tidss/tidss_dispc.c b/drivers/gpu/drm/tidss/tidss_dispc.c +index c986d432af507..d3e57e6de5dbb 100644 +--- a/drivers/gpu/drm/tidss/tidss_dispc.c ++++ b/drivers/gpu/drm/tidss/tidss_dispc.c +@@ -2655,14 +2655,28 @@ static void dispc_init_errata(struct dispc_device *dispc) + } + } + ++/* ++ * K2G display controller does not support soft reset, so we do a basic manual ++ * reset here: make sure the IRQs are masked and VPs are disabled. ++ */ ++static void dispc_softreset_k2g(struct dispc_device *dispc) ++{ ++ dispc_set_irqenable(dispc, 0); ++ dispc_read_and_clear_irqstatus(dispc); ++ ++ for (unsigned int vp_idx = 0; vp_idx < dispc->feat->num_vps; ++vp_idx) ++ VP_REG_FLD_MOD(dispc, vp_idx, DISPC_VP_CONTROL, 0, 0, 0); ++} ++ + static int dispc_softreset(struct dispc_device *dispc) + { + u32 val; + int ret = 0; + +- /* K2G display controller does not support soft reset */ +- if (dispc->feat->subrev == DISPC_K2G) ++ if (dispc->feat->subrev == DISPC_K2G) { ++ dispc_softreset_k2g(dispc); + return 0; ++ } + + /* Soft reset */ + REG_FLD_MOD(dispc, DSS_SYSCONFIG, 1, 1, 1); +-- +2.39.5 + diff --git a/queue-6.1/drm-tidss-fix-race-condition-while-handling-interrup.patch b/queue-6.1/drm-tidss-fix-race-condition-while-handling-interrup.patch new file mode 100644 index 0000000000..9504cdfa40 --- /dev/null +++ b/queue-6.1/drm-tidss-fix-race-condition-while-handling-interrup.patch @@ -0,0 +1,64 @@ +From bc7cb75e89f1d34ec723d228aab68caa73defaee Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 21 Oct 2024 17:07:50 +0300 +Subject: drm/tidss: Fix race condition while handling interrupt registers + +From: Devarsh Thakkar + +[ Upstream commit a9a73f2661e6f625d306c9b0ef082e4593f45a21 ] + +The driver has a spinlock for protecting the irq_masks field and irq +enable registers. However, the driver misses protecting the irq status +registers which can lead to races. + +Take the spinlock when accessing irqstatus too. + +Fixes: 32a1795f57ee ("drm/tidss: New driver for TI Keystone platform Display SubSystem") +Cc: stable@vger.kernel.org +Signed-off-by: Devarsh Thakkar +[Tomi: updated the desc] +Reviewed-by: Jonathan Cormier +Tested-by: Jonathan Cormier +Reviewed-by: Aradhya Bhatia +Signed-off-by: Tomi Valkeinen +Link: https://patchwork.freedesktop.org/patch/msgid/20241021-tidss-irq-fix-v1-6-82ddaec94e4a@ideasonboard.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/tidss/tidss_dispc.c | 4 ++++ + drivers/gpu/drm/tidss/tidss_irq.c | 2 ++ + 2 files changed, 6 insertions(+) + +diff --git a/drivers/gpu/drm/tidss/tidss_dispc.c b/drivers/gpu/drm/tidss/tidss_dispc.c +index d3e57e6de5dbb..38b2ae0d7ec1d 100644 +--- a/drivers/gpu/drm/tidss/tidss_dispc.c ++++ b/drivers/gpu/drm/tidss/tidss_dispc.c +@@ -2661,8 +2661,12 @@ static void dispc_init_errata(struct dispc_device *dispc) + */ + static void dispc_softreset_k2g(struct dispc_device *dispc) + { ++ unsigned long flags; ++ ++ spin_lock_irqsave(&dispc->tidss->wait_lock, flags); + dispc_set_irqenable(dispc, 0); + dispc_read_and_clear_irqstatus(dispc); ++ spin_unlock_irqrestore(&dispc->tidss->wait_lock, flags); + + for (unsigned int vp_idx = 0; vp_idx < dispc->feat->num_vps; ++vp_idx) + VP_REG_FLD_MOD(dispc, vp_idx, DISPC_VP_CONTROL, 0, 0, 0); +diff --git a/drivers/gpu/drm/tidss/tidss_irq.c b/drivers/gpu/drm/tidss/tidss_irq.c +index 0c681c7600bcb..f13c7e434f8ed 100644 +--- a/drivers/gpu/drm/tidss/tidss_irq.c ++++ b/drivers/gpu/drm/tidss/tidss_irq.c +@@ -60,7 +60,9 @@ static irqreturn_t tidss_irq_handler(int irq, void *arg) + unsigned int id; + dispc_irq_t irqstatus; + ++ spin_lock(&tidss->wait_lock); + irqstatus = dispc_read_and_clear_irqstatus(tidss->dispc); ++ spin_unlock(&tidss->wait_lock); + + for (id = 0; id < tidss->num_crtcs; id++) { + struct drm_crtc *crtc = tidss->crtcs[id]; +-- +2.39.5 + diff --git a/queue-6.1/nouveau-svm-fix-missing-folio-unlock-put-after-make_.patch b/queue-6.1/nouveau-svm-fix-missing-folio-unlock-put-after-make_.patch new file mode 100644 index 0000000000..b9b5ed098a --- /dev/null +++ b/queue-6.1/nouveau-svm-fix-missing-folio-unlock-put-after-make_.patch @@ -0,0 +1,74 @@ +From e1a2d23ebf31af7b08094651f1e09ca36af1b42f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 24 Jan 2025 19:15:23 +0100 +Subject: nouveau/svm: fix missing folio unlock + put after + make_device_exclusive_range() + +From: David Hildenbrand + +[ Upstream commit b3fefbb30a1691533cb905006b69b2a474660744 ] + +In case we have to retry the loop, we are missing to unlock+put the +folio. In that case, we will keep failing make_device_exclusive_range() +because we cannot grab the folio lock, and even return from the function +with the folio locked and referenced, effectively never succeeding the +make_device_exclusive_range(). + +While at it, convert the other unlock+put to use a folio as well. + +This was found by code inspection. + +Fixes: 8f187163eb89 ("nouveau/svm: implement atomic SVM access") +Signed-off-by: David Hildenbrand +Reviewed-by: Alistair Popple +Tested-by: Alistair Popple +Signed-off-by: Danilo Krummrich +Link: https://patchwork.freedesktop.org/patch/msgid/20250124181524.3584236-2-david@redhat.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/nouveau/nouveau_svm.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/nouveau/nouveau_svm.c b/drivers/gpu/drm/nouveau/nouveau_svm.c +index be6674fb1af71..d0bff13ac758d 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_svm.c ++++ b/drivers/gpu/drm/nouveau/nouveau_svm.c +@@ -592,6 +592,7 @@ static int nouveau_atomic_range_fault(struct nouveau_svmm *svmm, + unsigned long timeout = + jiffies + msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT); + struct mm_struct *mm = svmm->notifier.mm; ++ struct folio *folio; + struct page *page; + unsigned long start = args->p.addr; + unsigned long notifier_seq; +@@ -618,12 +619,16 @@ static int nouveau_atomic_range_fault(struct nouveau_svmm *svmm, + ret = -EINVAL; + goto out; + } ++ folio = page_folio(page); + + mutex_lock(&svmm->mutex); + if (!mmu_interval_read_retry(¬ifier->notifier, + notifier_seq)) + break; + mutex_unlock(&svmm->mutex); ++ ++ folio_unlock(folio); ++ folio_put(folio); + } + + /* Map the page on the GPU. */ +@@ -639,8 +644,8 @@ static int nouveau_atomic_range_fault(struct nouveau_svmm *svmm, + ret = nvif_object_ioctl(&svmm->vmm->vmm.object, args, size, NULL); + mutex_unlock(&svmm->mutex); + +- unlock_page(page); +- put_page(page); ++ folio_unlock(folio); ++ folio_put(folio); + + out: + mmu_interval_notifier_remove(¬ifier->notifier); +-- +2.39.5 + diff --git a/queue-6.1/nvme-ioctl-add-missing-space-in-err-message.patch b/queue-6.1/nvme-ioctl-add-missing-space-in-err-message.patch new file mode 100644 index 0000000000..e7ac409dbd --- /dev/null +++ b/queue-6.1/nvme-ioctl-add-missing-space-in-err-message.patch @@ -0,0 +1,41 @@ +From 4ea9cc2308e84d7aa68cb92a0b01fa55577f5459 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Feb 2025 10:05:14 -0700 +Subject: nvme/ioctl: add missing space in err message + +From: Caleb Sander Mateos + +[ Upstream commit 487a3ea7b1b8ba2ca7d2c2bb3c3594dc360d6261 ] + +nvme_validate_passthru_nsid() logs an err message whose format string is +split over 2 lines. There is a missing space between the two pieces, +resulting in log lines like "... does not match nsid (1)of namespace". +Add the missing space between ")" and "of". Also combine the format +string pieces onto a single line to make the err message easier to grep. + +Fixes: e7d4b5493a2d ("nvme: factor out a nvme_validate_passthru_nsid helper") +Signed-off-by: Caleb Sander Mateos +Reviewed-by: Christoph Hellwig +Signed-off-by: Keith Busch +Signed-off-by: Sasha Levin +--- + drivers/nvme/host/ioctl.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/nvme/host/ioctl.c b/drivers/nvme/host/ioctl.c +index a02873792890e..acf73a91e87e7 100644 +--- a/drivers/nvme/host/ioctl.c ++++ b/drivers/nvme/host/ioctl.c +@@ -262,8 +262,7 @@ static bool nvme_validate_passthru_nsid(struct nvme_ctrl *ctrl, + { + if (ns && nsid != ns->head->ns_id) { + dev_err(ctrl->device, +- "%s: nsid (%u) in cmd does not match nsid (%u)" +- "of namespace\n", ++ "%s: nsid (%u) in cmd does not match nsid (%u) of namespace\n", + current->comm, nsid, ns->head->ns_id); + return false; + } +-- +2.39.5 + diff --git a/queue-6.1/power-supply-da9150-fg-fix-potential-overflow.patch b/queue-6.1/power-supply-da9150-fg-fix-potential-overflow.patch new file mode 100644 index 0000000000..fd5df7f451 --- /dev/null +++ b/queue-6.1/power-supply-da9150-fg-fix-potential-overflow.patch @@ -0,0 +1,56 @@ +From 5164d7c34a07028686a0539463c3887a0a667057 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 30 Jan 2025 09:00:34 +0000 +Subject: power: supply: da9150-fg: fix potential overflow + +From: Andrey Vatoropin + +[ Upstream commit 3fb3cb4350befc4f901c54e0cb4a2a47b1302e08 ] + +Size of variable sd_gain equals four bytes - DA9150_QIF_SD_GAIN_SIZE. +Size of variable shunt_val equals two bytes - DA9150_QIF_SHUNT_VAL_SIZE. + +The expression sd_gain * shunt_val is currently being evaluated using +32-bit arithmetic. So during the multiplication an overflow may occur. + +As the value of type 'u64' is used as storage for the eventual result, put +ULL variable at the first position of each expression in order to give the +compiler complete information about the proper arithmetic to use. According +to C99 the guaranteed width for a variable of type 'unsigned long long' >= +64 bits. + +Remove the explicit cast to u64 as it is meaningless. + +Just for the sake of consistency, perform the similar trick with another +expression concerning 'iavg'. + +Found by Linux Verification Center (linuxtesting.org) with SVACE. + +Fixes: a419b4fd9138 ("power: Add support for DA9150 Fuel-Gauge") +Signed-off-by: Andrey Vatoropin +Link: https://lore.kernel.org/r/20250130090030.53422-1-a.vatoropin@crpt.ru +Signed-off-by: Sebastian Reichel +Signed-off-by: Sasha Levin +--- + drivers/power/supply/da9150-fg.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/power/supply/da9150-fg.c b/drivers/power/supply/da9150-fg.c +index 8c5e2c49d6c1c..9d0a6ab698f58 100644 +--- a/drivers/power/supply/da9150-fg.c ++++ b/drivers/power/supply/da9150-fg.c +@@ -248,9 +248,9 @@ static int da9150_fg_current_avg(struct da9150_fg *fg, + DA9150_QIF_SD_GAIN_SIZE); + da9150_fg_read_sync_end(fg); + +- div = (u64) (sd_gain * shunt_val * 65536ULL); ++ div = 65536ULL * sd_gain * shunt_val; + do_div(div, 1000000); +- res = (u64) (iavg * 1000000ULL); ++ res = 1000000ULL * iavg; + do_div(res, div); + + val->intval = (int) res; +-- +2.39.5 + diff --git a/queue-6.1/series b/queue-6.1/series index d79bff3f61..626eed6efd 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -58,3 +58,14 @@ net-add-non-rcu-dev_getbyhwaddr-helper.patch arp-switch-to-dev_getbyhwaddr-in-arp_req_set_public.patch net-axienet-set-mac_managed_pm.patch tcp-drop-secpath-at-the-same-time-as-we-currently-dr.patch +drm-tidss-add-simple-k2g-manual-reset.patch +drm-tidss-fix-race-condition-while-handling-interrup.patch +drm-rcar-du-dsi-fix-phy-lock-bit-check.patch +bpf-test_run-fix-use-after-free-issue-in-eth_skb_pkt.patch +strparser-add-read_sock-callback.patch +bpf-fix-wrong-copied_seq-calculation.patch +power-supply-da9150-fg-fix-potential-overflow.patch +nouveau-svm-fix-missing-folio-unlock-put-after-make_.patch +drm-msm-dpu-don-t-leak-bits_per_component-into-rando.patch +nvme-ioctl-add-missing-space-in-err-message.patch +bpf-skip-non-exist-keys-in-generic_map_lookup_batch.patch diff --git a/queue-6.1/strparser-add-read_sock-callback.patch b/queue-6.1/strparser-add-read_sock-callback.patch new file mode 100644 index 0000000000..350ab8505c --- /dev/null +++ b/queue-6.1/strparser-add-read_sock-callback.patch @@ -0,0 +1,104 @@ +From 52e655997539477f3d168b08659ffdb121523230 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Jan 2025 18:09:13 +0800 +Subject: strparser: Add read_sock callback + +From: Jiayuan Chen + +[ Upstream commit 0532a79efd68a4d9686b0385e4993af4b130ff82 ] + +Added a new read_sock handler, allowing users to customize read operations +instead of relying on the native socket's read_sock. + +Signed-off-by: Jiayuan Chen +Signed-off-by: Martin KaFai Lau +Reviewed-by: Jakub Sitnicki +Acked-by: John Fastabend +Link: https://patch.msgid.link/20250122100917.49845-2-mrpre@163.com +Stable-dep-of: 36b62df5683c ("bpf: Fix wrong copied_seq calculation") +Signed-off-by: Sasha Levin +--- + Documentation/networking/strparser.rst | 9 ++++++++- + include/net/strparser.h | 2 ++ + net/strparser/strparser.c | 11 +++++++++-- + 3 files changed, 19 insertions(+), 3 deletions(-) + +diff --git a/Documentation/networking/strparser.rst b/Documentation/networking/strparser.rst +index 6cab1f74ae05a..7f623d1db72aa 100644 +--- a/Documentation/networking/strparser.rst ++++ b/Documentation/networking/strparser.rst +@@ -112,7 +112,7 @@ Functions + Callbacks + ========= + +-There are six callbacks: ++There are seven callbacks: + + :: + +@@ -182,6 +182,13 @@ There are six callbacks: + the length of the message. skb->len - offset may be greater + then full_len since strparser does not trim the skb. + ++ :: ++ ++ int (*read_sock)(struct strparser *strp, read_descriptor_t *desc, ++ sk_read_actor_t recv_actor); ++ ++ The read_sock callback is used by strparser instead of ++ sock->ops->read_sock, if provided. + :: + + int (*read_sock_done)(struct strparser *strp, int err); +diff --git a/include/net/strparser.h b/include/net/strparser.h +index 41e2ce9e9e10f..0a83010b3a64a 100644 +--- a/include/net/strparser.h ++++ b/include/net/strparser.h +@@ -43,6 +43,8 @@ struct strparser; + struct strp_callbacks { + int (*parse_msg)(struct strparser *strp, struct sk_buff *skb); + void (*rcv_msg)(struct strparser *strp, struct sk_buff *skb); ++ int (*read_sock)(struct strparser *strp, read_descriptor_t *desc, ++ sk_read_actor_t recv_actor); + int (*read_sock_done)(struct strparser *strp, int err); + void (*abort_parser)(struct strparser *strp, int err); + void (*lock)(struct strparser *strp); +diff --git a/net/strparser/strparser.c b/net/strparser/strparser.c +index 8299ceb3e3739..95696f42647ec 100644 +--- a/net/strparser/strparser.c ++++ b/net/strparser/strparser.c +@@ -347,7 +347,10 @@ static int strp_read_sock(struct strparser *strp) + struct socket *sock = strp->sk->sk_socket; + read_descriptor_t desc; + +- if (unlikely(!sock || !sock->ops || !sock->ops->read_sock)) ++ if (unlikely(!sock || !sock->ops)) ++ return -EBUSY; ++ ++ if (unlikely(!strp->cb.read_sock && !sock->ops->read_sock)) + return -EBUSY; + + desc.arg.data = strp; +@@ -355,7 +358,10 @@ static int strp_read_sock(struct strparser *strp) + desc.count = 1; /* give more than one skb per call */ + + /* sk should be locked here, so okay to do read_sock */ +- sock->ops->read_sock(strp->sk, &desc, strp_recv); ++ if (strp->cb.read_sock) ++ strp->cb.read_sock(strp, &desc, strp_recv); ++ else ++ sock->ops->read_sock(strp->sk, &desc, strp_recv); + + desc.error = strp->cb.read_sock_done(strp, desc.error); + +@@ -468,6 +474,7 @@ int strp_init(struct strparser *strp, struct sock *sk, + strp->cb.unlock = cb->unlock ? : strp_sock_unlock; + strp->cb.rcv_msg = cb->rcv_msg; + strp->cb.parse_msg = cb->parse_msg; ++ strp->cb.read_sock = cb->read_sock; + strp->cb.read_sock_done = cb->read_sock_done ? : default_read_sock_done; + strp->cb.abort_parser = cb->abort_parser ? : strp_abort_strp; + +-- +2.39.5 +