From: Sasha Levin Date: Mon, 17 Jun 2024 11:30:31 +0000 (-0400) Subject: Fixes for 6.9 X-Git-Tag: v6.1.95~113 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=86b772eda9a9aec6cb3d4f75c1d579c44b132e1f;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 6.9 Signed-off-by: Sasha Levin --- diff --git a/queue-6.9/af_unix-allocate-struct-unix_vertex-for-each-infligh.patch b/queue-6.9/af_unix-allocate-struct-unix_vertex-for-each-infligh.patch new file mode 100644 index 00000000000..9112511e871 --- /dev/null +++ b/queue-6.9/af_unix-allocate-struct-unix_vertex-for-each-infligh.patch @@ -0,0 +1,212 @@ +From 2c81612444e1e204161559f10885b1e9de76e20c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Mar 2024 13:24:11 -0700 +Subject: af_unix: Allocate struct unix_vertex for each inflight AF_UNIX fd. + +From: Kuniyuki Iwashima + +[ Upstream commit 1fbfdfaa590248c1d86407f578e40e5c65136330 ] + +We will replace the garbage collection algorithm for AF_UNIX, where +we will consider each inflight AF_UNIX socket as a vertex and its file +descriptor as an edge in a directed graph. + +This patch introduces a new struct unix_vertex representing a vertex +in the graph and adds its pointer to struct unix_sock. + +When we send a fd using the SCM_RIGHTS message, we allocate struct +scm_fp_list to struct scm_cookie in scm_fp_copy(). Then, we bump +each refcount of the inflight fds' struct file and save them in +scm_fp_list.fp. + +After that, unix_attach_fds() inexplicably clones scm_fp_list of +scm_cookie and sets it to skb. (We will remove this part after +replacing GC.) + +Here, we add a new function call in unix_attach_fds() to preallocate +struct unix_vertex per inflight AF_UNIX fd and link each vertex to +skb's scm_fp_list.vertices. + +When sendmsg() succeeds later, if the socket of the inflight fd is +still not inflight yet, we will set the preallocated vertex to struct +unix_sock.vertex and link it to a global list unix_unvisited_vertices +under spin_lock(&unix_gc_lock). + +If the socket is already inflight, we free the preallocated vertex. +This is to avoid taking the lock unnecessarily when sendmsg() could +fail later. + +In the following patch, we will similarly allocate another struct +per edge, which will finally be linked to the inflight socket's +unix_vertex.edges. + +And then, we will count the number of edges as unix_vertex.out_degree. + +Signed-off-by: Kuniyuki Iwashima +Acked-by: Paolo Abeni +Link: https://lore.kernel.org/r/20240325202425.60930-2-kuniyu@amazon.com +Signed-off-by: Jakub Kicinski +Stable-dep-of: 1b536948e805 ("af_unix: Annotate data-race of sk->sk_state in unix_accept().") +Signed-off-by: Sasha Levin +--- + include/net/af_unix.h | 9 +++++++++ + include/net/scm.h | 3 +++ + net/core/scm.c | 7 +++++++ + net/unix/af_unix.c | 6 ++++++ + net/unix/garbage.c | 38 ++++++++++++++++++++++++++++++++++++++ + 5 files changed, 63 insertions(+) + +diff --git a/include/net/af_unix.h b/include/net/af_unix.h +index 3dee0b2721aa4..07f0f698c9490 100644 +--- a/include/net/af_unix.h ++++ b/include/net/af_unix.h +@@ -22,9 +22,17 @@ extern unsigned int unix_tot_inflight; + + void unix_inflight(struct user_struct *user, struct file *fp); + void unix_notinflight(struct user_struct *user, struct file *fp); ++int unix_prepare_fpl(struct scm_fp_list *fpl); ++void unix_destroy_fpl(struct scm_fp_list *fpl); + void unix_gc(void); + void wait_for_unix_gc(struct scm_fp_list *fpl); + ++struct unix_vertex { ++ struct list_head edges; ++ struct list_head entry; ++ unsigned long out_degree; ++}; ++ + struct sock *unix_peer_get(struct sock *sk); + + #define UNIX_HASH_MOD (256 - 1) +@@ -62,6 +70,7 @@ struct unix_sock { + struct path path; + struct mutex iolock, bindlock; + struct sock *peer; ++ struct unix_vertex *vertex; + struct list_head link; + unsigned long inflight; + spinlock_t lock; +diff --git a/include/net/scm.h b/include/net/scm.h +index 92276a2c55436..e34321b6e204b 100644 +--- a/include/net/scm.h ++++ b/include/net/scm.h +@@ -27,6 +27,9 @@ struct scm_fp_list { + short count; + short count_unix; + short max; ++#ifdef CONFIG_UNIX ++ struct list_head vertices; ++#endif + struct user_struct *user; + struct file *fp[SCM_MAX_FD]; + }; +diff --git a/net/core/scm.c b/net/core/scm.c +index 9cd4b0a01cd60..87dfec1c33787 100644 +--- a/net/core/scm.c ++++ b/net/core/scm.c +@@ -89,6 +89,9 @@ static int scm_fp_copy(struct cmsghdr *cmsg, struct scm_fp_list **fplp) + fpl->count_unix = 0; + fpl->max = SCM_MAX_FD; + fpl->user = NULL; ++#if IS_ENABLED(CONFIG_UNIX) ++ INIT_LIST_HEAD(&fpl->vertices); ++#endif + } + fpp = &fpl->fp[fpl->count]; + +@@ -376,8 +379,12 @@ struct scm_fp_list *scm_fp_dup(struct scm_fp_list *fpl) + if (new_fpl) { + for (i = 0; i < fpl->count; i++) + get_file(fpl->fp[i]); ++ + new_fpl->max = new_fpl->count; + new_fpl->user = get_uid(fpl->user); ++#if IS_ENABLED(CONFIG_UNIX) ++ INIT_LIST_HEAD(&new_fpl->vertices); ++#endif + } + return new_fpl; + } +diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c +index cbc011ceb89b4..4100541c8c00f 100644 +--- a/net/unix/af_unix.c ++++ b/net/unix/af_unix.c +@@ -974,6 +974,7 @@ static struct sock *unix_create1(struct net *net, struct socket *sock, int kern, + sk->sk_destruct = unix_sock_destructor; + u = unix_sk(sk); + u->inflight = 0; ++ u->vertex = NULL; + u->path.dentry = NULL; + u->path.mnt = NULL; + spin_lock_init(&u->lock); +@@ -1808,6 +1809,9 @@ static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb) + for (i = scm->fp->count - 1; i >= 0; i--) + unix_inflight(scm->fp->user, scm->fp->fp[i]); + ++ if (unix_prepare_fpl(UNIXCB(skb).fp)) ++ return -ENOMEM; ++ + return 0; + } + +@@ -1818,6 +1822,8 @@ static void unix_detach_fds(struct scm_cookie *scm, struct sk_buff *skb) + scm->fp = UNIXCB(skb).fp; + UNIXCB(skb).fp = NULL; + ++ unix_destroy_fpl(scm->fp); ++ + for (i = scm->fp->count - 1; i >= 0; i--) + unix_notinflight(scm->fp->user, scm->fp->fp[i]); + } +diff --git a/net/unix/garbage.c b/net/unix/garbage.c +index 0104be9d47045..8ea7640e032e8 100644 +--- a/net/unix/garbage.c ++++ b/net/unix/garbage.c +@@ -101,6 +101,44 @@ struct unix_sock *unix_get_socket(struct file *filp) + return NULL; + } + ++static void unix_free_vertices(struct scm_fp_list *fpl) ++{ ++ struct unix_vertex *vertex, *next_vertex; ++ ++ list_for_each_entry_safe(vertex, next_vertex, &fpl->vertices, entry) { ++ list_del(&vertex->entry); ++ kfree(vertex); ++ } ++} ++ ++int unix_prepare_fpl(struct scm_fp_list *fpl) ++{ ++ struct unix_vertex *vertex; ++ int i; ++ ++ if (!fpl->count_unix) ++ return 0; ++ ++ for (i = 0; i < fpl->count_unix; i++) { ++ vertex = kmalloc(sizeof(*vertex), GFP_KERNEL); ++ if (!vertex) ++ goto err; ++ ++ list_add(&vertex->entry, &fpl->vertices); ++ } ++ ++ return 0; ++ ++err: ++ unix_free_vertices(fpl); ++ return -ENOMEM; ++} ++ ++void unix_destroy_fpl(struct scm_fp_list *fpl) ++{ ++ unix_free_vertices(fpl); ++} ++ + DEFINE_SPINLOCK(unix_gc_lock); + unsigned int unix_tot_inflight; + static LIST_HEAD(gc_candidates); +-- +2.43.0 + diff --git a/queue-6.9/af_unix-annotate-data-race-of-sk-sk_state-in-unix_ac.patch b/queue-6.9/af_unix-annotate-data-race-of-sk-sk_state-in-unix_ac.patch new file mode 100644 index 00000000000..7a544911124 --- /dev/null +++ b/queue-6.9/af_unix-annotate-data-race-of-sk-sk_state-in-unix_ac.patch @@ -0,0 +1,40 @@ +From f44da56f66cf382f9e3ddca5dfa5d585163a927d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Jun 2024 09:52:32 -0700 +Subject: af_unix: Annotate data-race of sk->sk_state in unix_accept(). + +From: Kuniyuki Iwashima + +[ Upstream commit 1b536948e805aab61a48c5aa5db10c9afee880bd ] + +Once sk->sk_state is changed to TCP_LISTEN, it never changes. + +unix_accept() takes the advantage and reads sk->sk_state without +holding unix_state_lock(). + +Let's use READ_ONCE() there. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Kuniyuki Iwashima +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/unix/af_unix.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c +index 417cf4adb4e04..23f9efa8c008b 100644 +--- a/net/unix/af_unix.c ++++ b/net/unix/af_unix.c +@@ -1706,7 +1706,7 @@ static int unix_accept(struct socket *sock, struct socket *newsock, + goto out; + + arg->err = -EINVAL; +- if (sk->sk_state != TCP_LISTEN) ++ if (READ_ONCE(sk->sk_state) != TCP_LISTEN) + goto out; + + /* If socket state is TCP_LISTEN it cannot change (for now...), +-- +2.43.0 + diff --git a/queue-6.9/af_unix-read-with-msg_peek-loops-if-the-first-unread.patch b/queue-6.9/af_unix-read-with-msg_peek-loops-if-the-first-unread.patch new file mode 100644 index 00000000000..a7be8d7c5dd --- /dev/null +++ b/queue-6.9/af_unix-read-with-msg_peek-loops-if-the-first-unread.patch @@ -0,0 +1,85 @@ +From 0a86aa83158b29111c38c583d98b8778133ac7b8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Jun 2024 01:46:39 -0700 +Subject: af_unix: Read with MSG_PEEK loops if the first unread byte is OOB + +From: Rao Shoaib + +[ Upstream commit a6736a0addd60fccc3a3508461d72314cc609772 ] + +Read with MSG_PEEK flag loops if the first byte to read is an OOB byte. +commit 22dd70eb2c3d ("af_unix: Don't peek OOB data without MSG_OOB.") +addresses the loop issue but does not address the issue that no data +beyond OOB byte can be read. + +>>> from socket import * +>>> c1, c2 = socketpair(AF_UNIX, SOCK_STREAM) +>>> c1.send(b'a', MSG_OOB) +1 +>>> c1.send(b'b') +1 +>>> c2.recv(1, MSG_PEEK | MSG_DONTWAIT) +b'b' + +>>> from socket import * +>>> c1, c2 = socketpair(AF_UNIX, SOCK_STREAM) +>>> c2.setsockopt(SOL_SOCKET, SO_OOBINLINE, 1) +>>> c1.send(b'a', MSG_OOB) +1 +>>> c1.send(b'b') +1 +>>> c2.recv(1, MSG_PEEK | MSG_DONTWAIT) +b'a' +>>> c2.recv(1, MSG_PEEK | MSG_DONTWAIT) +b'a' +>>> c2.recv(1, MSG_DONTWAIT) +b'a' +>>> c2.recv(1, MSG_PEEK | MSG_DONTWAIT) +b'b' +>>> + +Fixes: 314001f0bf92 ("af_unix: Add OOB support") +Signed-off-by: Rao Shoaib +Reviewed-by: Kuniyuki Iwashima +Link: https://lore.kernel.org/r/20240611084639.2248934-1-Rao.Shoaib@oracle.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/unix/af_unix.c | 18 +++++++++--------- + 1 file changed, 9 insertions(+), 9 deletions(-) + +diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c +index 23f9efa8c008b..bbafe293ef6a1 100644 +--- a/net/unix/af_unix.c ++++ b/net/unix/af_unix.c +@@ -2680,18 +2680,18 @@ static struct sk_buff *manage_oob(struct sk_buff *skb, struct sock *sk, + if (skb == u->oob_skb) { + if (copied) { + skb = NULL; +- } else if (sock_flag(sk, SOCK_URGINLINE)) { +- if (!(flags & MSG_PEEK)) { ++ } else if (!(flags & MSG_PEEK)) { ++ if (sock_flag(sk, SOCK_URGINLINE)) { + WRITE_ONCE(u->oob_skb, NULL); + consume_skb(skb); ++ } else { ++ __skb_unlink(skb, &sk->sk_receive_queue); ++ WRITE_ONCE(u->oob_skb, NULL); ++ unlinked_skb = skb; ++ skb = skb_peek(&sk->sk_receive_queue); + } +- } else if (flags & MSG_PEEK) { +- skb = NULL; +- } else { +- __skb_unlink(skb, &sk->sk_receive_queue); +- WRITE_ONCE(u->oob_skb, NULL); +- unlinked_skb = skb; +- skb = skb_peek(&sk->sk_receive_queue); ++ } else if (!sock_flag(sk, SOCK_URGINLINE)) { ++ skb = skb_peek_next(skb, &sk->sk_receive_queue); + } + } + +-- +2.43.0 + diff --git a/queue-6.9/af_unix-save-listener-for-embryo-socket.patch b/queue-6.9/af_unix-save-listener-for-embryo-socket.patch new file mode 100644 index 00000000000..2fb3d1c4d16 --- /dev/null +++ b/queue-6.9/af_unix-save-listener-for-embryo-socket.patch @@ -0,0 +1,83 @@ +From ba5c6a7c20e9109378e787b954a8f3efeb0dade3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Mar 2024 13:24:17 -0700 +Subject: af_unix: Save listener for embryo socket. + +From: Kuniyuki Iwashima + +[ Upstream commit aed6ecef55d70de3762ce41c561b7f547dbaf107 ] + +This is a prep patch for the following change, where we need to +fetch the listening socket from the successor embryo socket +during GC. + +We add a new field to struct unix_sock to save a pointer to a +listening socket. + +We set it when connect() creates a new socket, and clear it when +accept() is called. + +Signed-off-by: Kuniyuki Iwashima +Acked-by: Paolo Abeni +Link: https://lore.kernel.org/r/20240325202425.60930-8-kuniyu@amazon.com +Signed-off-by: Jakub Kicinski +Stable-dep-of: 1b536948e805 ("af_unix: Annotate data-race of sk->sk_state in unix_accept().") +Signed-off-by: Sasha Levin +--- + include/net/af_unix.h | 1 + + net/unix/af_unix.c | 5 ++++- + 2 files changed, 5 insertions(+), 1 deletion(-) + +diff --git a/include/net/af_unix.h b/include/net/af_unix.h +index 07f0f698c9490..ba863dfc95e1f 100644 +--- a/include/net/af_unix.h ++++ b/include/net/af_unix.h +@@ -70,6 +70,7 @@ struct unix_sock { + struct path path; + struct mutex iolock, bindlock; + struct sock *peer; ++ struct sock *listener; + struct unix_vertex *vertex; + struct list_head link; + unsigned long inflight; +diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c +index 4100541c8c00f..a1938ba24a696 100644 +--- a/net/unix/af_unix.c ++++ b/net/unix/af_unix.c +@@ -973,6 +973,7 @@ static struct sock *unix_create1(struct net *net, struct socket *sock, int kern, + sk->sk_max_ack_backlog = READ_ONCE(net->unx.sysctl_max_dgram_qlen); + sk->sk_destruct = unix_sock_destructor; + u = unix_sk(sk); ++ u->listener = NULL; + u->inflight = 0; + u->vertex = NULL; + u->path.dentry = NULL; +@@ -1601,6 +1602,7 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr, + newsk->sk_type = sk->sk_type; + init_peercred(newsk); + newu = unix_sk(newsk); ++ newu->listener = other; + RCU_INIT_POINTER(newsk->sk_wq, &newu->peer_wq); + otheru = unix_sk(other); + +@@ -1696,8 +1698,8 @@ static int unix_accept(struct socket *sock, struct socket *newsock, int flags, + bool kern) + { + struct sock *sk = sock->sk; +- struct sock *tsk; + struct sk_buff *skb; ++ struct sock *tsk; + int err; + + err = -EOPNOTSUPP; +@@ -1722,6 +1724,7 @@ static int unix_accept(struct socket *sock, struct socket *newsock, int flags, + } + + tsk = skb->sk; ++ unix_sk(tsk)->listener = NULL; + skb_free_datagram(sk, skb); + wake_up_interruptible(&unix_sk(sk)->peer_wait); + +-- +2.43.0 + diff --git a/queue-6.9/block-fix-request.queuelist-usage-in-flush.patch b/queue-6.9/block-fix-request.queuelist-usage-in-flush.patch new file mode 100644 index 00000000000..50d9635146b --- /dev/null +++ b/queue-6.9/block-fix-request.queuelist-usage-in-flush.patch @@ -0,0 +1,75 @@ +From 63f2509974d6a40e5d315f68c854a7d4e0808bad Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Jun 2024 22:31:15 +0800 +Subject: block: fix request.queuelist usage in flush + +From: Chengming Zhou + +[ Upstream commit d0321c812d89c5910d8da8e4b10c891c6b96ff70 ] + +Friedrich Weber reported a kernel crash problem and bisected to commit +81ada09cc25e ("blk-flush: reuse rq queuelist in flush state machine"). + +The root cause is that we use "list_move_tail(&rq->queuelist, pending)" +in the PREFLUSH/POSTFLUSH sequences. But rq->queuelist.next == xxx since +it's popped out from plug->cached_rq in __blk_mq_alloc_requests_batch(). +We don't initialize its queuelist just for this first request, although +the queuelist of all later popped requests will be initialized. + +Fix it by changing to use "list_add_tail(&rq->queuelist, pending)" so +rq->queuelist doesn't need to be initialized. It should be ok since rq +can't be on any list when PREFLUSH or POSTFLUSH, has no move actually. + +Please note the commit 81ada09cc25e ("blk-flush: reuse rq queuelist in +flush state machine") also has another requirement that no drivers would +touch rq->queuelist after blk_mq_end_request() since we will reuse it to +add rq to the post-flush pending list in POSTFLUSH. If this is not true, +we will have to revert that commit IMHO. + +This updated version adds "list_del_init(&rq->queuelist)" in flush rq +callback since the dm layer may submit request of a weird invalid format +(REQ_FSEQ_PREFLUSH | REQ_FSEQ_POSTFLUSH), which causes double list_add +if without this "list_del_init(&rq->queuelist)". The weird invalid format +problem should be fixed in dm layer. + +Reported-by: Friedrich Weber +Closes: https://lore.kernel.org/lkml/14b89dfb-505c-49f7-aebb-01c54451db40@proxmox.com/ +Closes: https://lore.kernel.org/lkml/c9d03ff7-27c5-4ebd-b3f6-5a90d96f35ba@proxmox.com/ +Fixes: 81ada09cc25e ("blk-flush: reuse rq queuelist in flush state machine") +Cc: Christoph Hellwig +Cc: ming.lei@redhat.com +Cc: bvanassche@acm.org +Tested-by: Friedrich Weber +Signed-off-by: Chengming Zhou +Reviewed-by: Christoph Hellwig +Link: https://lore.kernel.org/r/20240608143115.972486-1-chengming.zhou@linux.dev +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + block/blk-flush.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/block/blk-flush.c b/block/blk-flush.c +index b0f314f4bc149..9944414bf7eed 100644 +--- a/block/blk-flush.c ++++ b/block/blk-flush.c +@@ -183,7 +183,7 @@ static void blk_flush_complete_seq(struct request *rq, + /* queue for flush */ + if (list_empty(pending)) + fq->flush_pending_since = jiffies; +- list_move_tail(&rq->queuelist, pending); ++ list_add_tail(&rq->queuelist, pending); + break; + + case REQ_FSEQ_DATA: +@@ -261,6 +261,7 @@ static enum rq_end_io_ret flush_end_io(struct request *flush_rq, + unsigned int seq = blk_flush_cur_seq(rq); + + BUG_ON(seq != REQ_FSEQ_PREFLUSH && seq != REQ_FSEQ_POSTFLUSH); ++ list_del_init(&rq->queuelist); + blk_flush_complete_seq(rq, fq, seq, error); + } + +-- +2.43.0 + diff --git a/queue-6.9/block-sed-opal-avoid-possible-wrong-address-referenc.patch b/queue-6.9/block-sed-opal-avoid-possible-wrong-address-referenc.patch new file mode 100644 index 00000000000..677b62e799e --- /dev/null +++ b/queue-6.9/block-sed-opal-avoid-possible-wrong-address-referenc.patch @@ -0,0 +1,42 @@ +From 24c82a850e86ea0ad6df54a0cfafd4473246aa33 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Jun 2024 15:37:00 +0800 +Subject: block: sed-opal: avoid possible wrong address reference in + read_sed_opal_key() + +From: Su Hui + +[ Upstream commit 9b1ebce6a1fded90d4a1c6c57dc6262dac4c4c14 ] + +Clang static checker (scan-build) warning: +block/sed-opal.c:line 317, column 3 +Value stored to 'ret' is never read. + +Fix this problem by returning the error code when keyring_search() failed. +Otherwise, 'key' will have a wrong value when 'kerf' stores the error code. + +Fixes: 3bfeb6125664 ("block: sed-opal: keyring support for SED keys") +Signed-off-by: Su Hui +Link: https://lore.kernel.org/r/20240611073659.429582-1-suhui@nfschina.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + block/sed-opal.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/block/sed-opal.c b/block/sed-opal.c +index 14fe0fef811cf..598fd3e7fcc8e 100644 +--- a/block/sed-opal.c ++++ b/block/sed-opal.c +@@ -314,7 +314,7 @@ static int read_sed_opal_key(const char *key_name, u_char *buffer, int buflen) + &key_type_user, key_name, true); + + if (IS_ERR(kref)) +- ret = PTR_ERR(kref); ++ return PTR_ERR(kref); + + key = key_ref_to_ptr(kref); + down_read(&key->sem); +-- +2.43.0 + diff --git a/queue-6.9/bluetooth-fix-connection-setup-in-l2cap_connect.patch b/queue-6.9/bluetooth-fix-connection-setup-in-l2cap_connect.patch new file mode 100644 index 00000000000..2a978d277c1 --- /dev/null +++ b/queue-6.9/bluetooth-fix-connection-setup-in-l2cap_connect.patch @@ -0,0 +1,45 @@ +From 006001c79d5915ab4223e073c93114725cb00ac0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Jun 2024 18:06:20 +0300 +Subject: Bluetooth: fix connection setup in l2cap_connect + +From: Pauli Virtanen + +[ Upstream commit c695439d198d30e10553a3b98360c5efe77b6903 ] + +The amp_id argument of l2cap_connect() was removed in +commit 84a4bb6548a2 ("Bluetooth: HCI: Remove HCI_AMP support") + +It was always called with amp_id == 0, i.e. AMP_ID_BREDR == 0x00 (ie. +non-AMP controller). In the above commit, the code path for amp_id != 0 +was preserved, although it should have used the amp_id == 0 one. + +Restore the previous behavior of the non-AMP code path, to fix problems +with L2CAP connections. + +Fixes: 84a4bb6548a2 ("Bluetooth: HCI: Remove HCI_AMP support") +Signed-off-by: Pauli Virtanen +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/l2cap_core.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index e3f5d830e42bf..9394a158d1b1a 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -4009,8 +4009,8 @@ static void l2cap_connect(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, + status = L2CAP_CS_AUTHOR_PEND; + chan->ops->defer(chan); + } else { +- l2cap_state_change(chan, BT_CONNECT2); +- result = L2CAP_CR_PEND; ++ l2cap_state_change(chan, BT_CONFIG); ++ result = L2CAP_CR_SUCCESS; + status = L2CAP_CS_NO_INFO; + } + } else { +-- +2.43.0 + diff --git a/queue-6.9/bluetooth-hci_sync-fix-not-using-correct-handle.patch b/queue-6.9/bluetooth-hci_sync-fix-not-using-correct-handle.patch new file mode 100644 index 00000000000..e451e85a10f --- /dev/null +++ b/queue-6.9/bluetooth-hci_sync-fix-not-using-correct-handle.patch @@ -0,0 +1,36 @@ +From ba684a20b5014ed419b86f1611e2647ad9719639 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 May 2024 10:32:01 -0400 +Subject: Bluetooth: hci_sync: Fix not using correct handle + +From: Luiz Augusto von Dentz + +[ Upstream commit 86fbd9f63a6b42b8f158361334f5a25762aea358 ] + +When setting up an advertisement the code shall always attempt to use +the handle set by the instance since it may not be equal to the instance +ID. + +Fixes: e77f43d531af ("Bluetooth: hci_core: Fix not handling hdev->le_num_of_adv_sets=1") +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/hci_sync.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c +index 64f794d198cdc..7bfa6b59ba87e 100644 +--- a/net/bluetooth/hci_sync.c ++++ b/net/bluetooth/hci_sync.c +@@ -1194,7 +1194,7 @@ int hci_setup_ext_adv_instance_sync(struct hci_dev *hdev, u8 instance) + + cp.own_addr_type = own_addr_type; + cp.channel_map = hdev->le_adv_channel_map; +- cp.handle = instance; ++ cp.handle = adv ? adv->handle : instance; + + if (flags & MGMT_ADV_FLAG_SEC_2M) { + cp.primary_phy = HCI_ADV_PHY_1M; +-- +2.43.0 + diff --git a/queue-6.9/bluetooth-l2cap-fix-rejecting-l2cap_conn_param_updat.patch b/queue-6.9/bluetooth-l2cap-fix-rejecting-l2cap_conn_param_updat.patch new file mode 100644 index 00000000000..33545b706aa --- /dev/null +++ b/queue-6.9/bluetooth-l2cap-fix-rejecting-l2cap_conn_param_updat.patch @@ -0,0 +1,108 @@ +From 549181285a70aa6bbe4ec1be1e54851e69efb849 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 May 2024 16:03:07 -0400 +Subject: Bluetooth: L2CAP: Fix rejecting L2CAP_CONN_PARAM_UPDATE_REQ + +From: Luiz Augusto von Dentz + +[ Upstream commit 806a5198c05987b748b50f3d0c0cfb3d417381a4 ] + +This removes the bogus check for max > hcon->le_conn_max_interval since +the later is just the initial maximum conn interval not the maximum the +stack could support which is really 3200=4000ms. + +In order to pass GAP/CONN/CPUP/BV-05-C one shall probably enter values +of the following fields in IXIT that would cause hci_check_conn_params +to fail: + +TSPX_conn_update_int_min +TSPX_conn_update_int_max +TSPX_conn_update_peripheral_latency +TSPX_conn_update_supervision_timeout + +Link: https://github.com/bluez/bluez/issues/847 +Fixes: e4b019515f95 ("Bluetooth: Enforce validation on max value of connection interval") +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + include/net/bluetooth/hci_core.h | 36 ++++++++++++++++++++++++++++---- + net/bluetooth/l2cap_core.c | 8 +------ + 2 files changed, 33 insertions(+), 11 deletions(-) + +diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h +index 970101184cf10..17b2a7baa4d8f 100644 +--- a/include/net/bluetooth/hci_core.h ++++ b/include/net/bluetooth/hci_core.h +@@ -2113,18 +2113,46 @@ static inline int hci_check_conn_params(u16 min, u16 max, u16 latency, + { + u16 max_latency; + +- if (min > max || min < 6 || max > 3200) ++ if (min > max) { ++ BT_WARN("min %d > max %d", min, max); + return -EINVAL; ++ } ++ ++ if (min < 6) { ++ BT_WARN("min %d < 6", min); ++ return -EINVAL; ++ } ++ ++ if (max > 3200) { ++ BT_WARN("max %d > 3200", max); ++ return -EINVAL; ++ } ++ ++ if (to_multiplier < 10) { ++ BT_WARN("to_multiplier %d < 10", to_multiplier); ++ return -EINVAL; ++ } + +- if (to_multiplier < 10 || to_multiplier > 3200) ++ if (to_multiplier > 3200) { ++ BT_WARN("to_multiplier %d > 3200", to_multiplier); + return -EINVAL; ++ } + +- if (max >= to_multiplier * 8) ++ if (max >= to_multiplier * 8) { ++ BT_WARN("max %d >= to_multiplier %d * 8", max, to_multiplier); + return -EINVAL; ++ } + + max_latency = (to_multiplier * 4 / max) - 1; +- if (latency > 499 || latency > max_latency) ++ if (latency > 499) { ++ BT_WARN("latency %d > 499", latency); + return -EINVAL; ++ } ++ ++ if (latency > max_latency) { ++ BT_WARN("latency %d > max_latency %d", latency, max_latency); ++ return -EINVAL; ++ } + + return 0; + } +diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c +index 4a633c1b68825..e3f5d830e42bf 100644 +--- a/net/bluetooth/l2cap_core.c ++++ b/net/bluetooth/l2cap_core.c +@@ -4645,13 +4645,7 @@ static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn, + + memset(&rsp, 0, sizeof(rsp)); + +- if (max > hcon->le_conn_max_interval) { +- BT_DBG("requested connection interval exceeds current bounds."); +- err = -EINVAL; +- } else { +- err = hci_check_conn_params(min, max, latency, to_multiplier); +- } +- ++ err = hci_check_conn_params(min, max, latency, to_multiplier); + if (err) + rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED); + else +-- +2.43.0 + diff --git a/queue-6.9/bnxt_en-adjust-logging-of-firmware-messages-in-case-.patch b/queue-6.9/bnxt_en-adjust-logging-of-firmware-messages-in-case-.patch new file mode 100644 index 00000000000..f139f8c5aa0 --- /dev/null +++ b/queue-6.9/bnxt_en-adjust-logging-of-firmware-messages-in-case-.patch @@ -0,0 +1,47 @@ +From b117e3d18e518a2a802548a97e815fe313e7bafe Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Jun 2024 11:25:46 +0300 +Subject: bnxt_en: Adjust logging of firmware messages in case of released + token in __hwrm_send() + +From: Aleksandr Mishin + +[ Upstream commit a9b9741854a9fe9df948af49ca5514e0ed0429df ] + +In case of token is released due to token->state == BNXT_HWRM_DEFERRED, +released token (set to NULL) is used in log messages. This issue is +expected to be prevented by HWRM_ERR_CODE_PF_UNAVAILABLE error code. But +this error code is returned by recent firmware. So some firmware may not +return it. This may lead to NULL pointer dereference. +Adjust this issue by adding token pointer check. + +Found by Linux Verification Center (linuxtesting.org) with SVACE. + +Fixes: 8fa4219dba8e ("bnxt_en: add dynamic debug support for HWRM messages") +Suggested-by: Michael Chan +Signed-off-by: Aleksandr Mishin +Reviewed-by: Wojciech Drewek +Reviewed-by: Michael Chan +Link: https://lore.kernel.org/r/20240611082547.12178-1-amishin@t-argos.ru +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/broadcom/bnxt/bnxt_hwrm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_hwrm.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_hwrm.c +index 1df3d56cc4b51..d2fd2d04ed474 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_hwrm.c ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_hwrm.c +@@ -680,7 +680,7 @@ static int __hwrm_send(struct bnxt *bp, struct bnxt_hwrm_ctx *ctx) + req_type); + else if (rc && rc != HWRM_ERR_CODE_PF_UNAVAILABLE) + hwrm_err(bp, ctx, "hwrm req_type 0x%x seq id 0x%x error 0x%x\n", +- req_type, token->seq_id, rc); ++ req_type, le16_to_cpu(ctx->req->seq_id), rc); + rc = __hwrm_to_stderr(rc); + exit: + if (token) +-- +2.43.0 + diff --git a/queue-6.9/bnxt_en-cap-the-size-of-hwrm_port_phy_qcfg-forwarded.patch b/queue-6.9/bnxt_en-cap-the-size-of-hwrm_port_phy_qcfg-forwarded.patch new file mode 100644 index 00000000000..5a7302d52a8 --- /dev/null +++ b/queue-6.9/bnxt_en-cap-the-size-of-hwrm_port_phy_qcfg-forwarded.patch @@ -0,0 +1,137 @@ +From 8674871d665b44216fec1925524ab6ced71e5fd2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Jun 2024 16:17:36 -0700 +Subject: bnxt_en: Cap the size of HWRM_PORT_PHY_QCFG forwarded response + +From: Michael Chan + +[ Upstream commit 7d9df38c9c037ab84502ce7eeae9f1e1e7e72603 ] + +Firmware interface 1.10.2.118 has increased the size of +HWRM_PORT_PHY_QCFG response beyond the maximum size that can be +forwarded. When the VF's link state is not the default auto state, +the PF will need to forward the response back to the VF to indicate +the forced state. This regression may cause the VF to fail to +initialize. + +Fix it by capping the HWRM_PORT_PHY_QCFG response to the maximum +96 bytes. The SPEEDS2_SUPPORTED flag needs to be cleared because the +new speeds2 fields are beyond the legacy structure. Also modify +bnxt_hwrm_fwd_resp() to print a warning if the message size exceeds 96 +bytes to make this failure more obvious. + +Fixes: 84a911db8305 ("bnxt_en: Update firmware interface to 1.10.2.118") +Reviewed-by: Somnath Kotur +Reviewed-by: Pavan Chebbi +Signed-off-by: Michael Chan +Link: https://lore.kernel.org/r/20240612231736.57823-1-michael.chan@broadcom.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/broadcom/bnxt/bnxt.h | 51 +++++++++++++++++++ + .../net/ethernet/broadcom/bnxt/bnxt_sriov.c | 12 ++++- + 2 files changed, 61 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h +index dd849e715c9ba..c46abcccfca10 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h +@@ -1419,6 +1419,57 @@ struct bnxt_l2_filter { + atomic_t refcnt; + }; + ++/* Compat version of hwrm_port_phy_qcfg_output capped at 96 bytes. The ++ * first 95 bytes are identical to hwrm_port_phy_qcfg_output in bnxt_hsi.h. ++ * The last valid byte in the compat version is different. ++ */ ++struct hwrm_port_phy_qcfg_output_compat { ++ __le16 error_code; ++ __le16 req_type; ++ __le16 seq_id; ++ __le16 resp_len; ++ u8 link; ++ u8 active_fec_signal_mode; ++ __le16 link_speed; ++ u8 duplex_cfg; ++ u8 pause; ++ __le16 support_speeds; ++ __le16 force_link_speed; ++ u8 auto_mode; ++ u8 auto_pause; ++ __le16 auto_link_speed; ++ __le16 auto_link_speed_mask; ++ u8 wirespeed; ++ u8 lpbk; ++ u8 force_pause; ++ u8 module_status; ++ __le32 preemphasis; ++ u8 phy_maj; ++ u8 phy_min; ++ u8 phy_bld; ++ u8 phy_type; ++ u8 media_type; ++ u8 xcvr_pkg_type; ++ u8 eee_config_phy_addr; ++ u8 parallel_detect; ++ __le16 link_partner_adv_speeds; ++ u8 link_partner_adv_auto_mode; ++ u8 link_partner_adv_pause; ++ __le16 adv_eee_link_speed_mask; ++ __le16 link_partner_adv_eee_link_speed_mask; ++ __le32 xcvr_identifier_type_tx_lpi_timer; ++ __le16 fec_cfg; ++ u8 duplex_state; ++ u8 option_flags; ++ char phy_vendor_name[16]; ++ char phy_vendor_partnumber[16]; ++ __le16 support_pam4_speeds; ++ __le16 force_pam4_link_speed; ++ __le16 auto_pam4_link_speed_mask; ++ u8 link_partner_pam4_adv_speeds; ++ u8 valid; ++}; ++ + struct bnxt_link_info { + u8 phy_type; + u8 media_type; +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c +index 175192ebaa773..22898d3d088b0 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c +@@ -950,8 +950,11 @@ static int bnxt_hwrm_fwd_resp(struct bnxt *bp, struct bnxt_vf_info *vf, + struct hwrm_fwd_resp_input *req; + int rc; + +- if (BNXT_FWD_RESP_SIZE_ERR(msg_size)) ++ if (BNXT_FWD_RESP_SIZE_ERR(msg_size)) { ++ netdev_warn_once(bp->dev, "HWRM fwd response too big (%d bytes)\n", ++ msg_size); + return -EINVAL; ++ } + + rc = hwrm_req_init(bp, req, HWRM_FWD_RESP); + if (!rc) { +@@ -1085,7 +1088,7 @@ static int bnxt_vf_set_link(struct bnxt *bp, struct bnxt_vf_info *vf) + rc = bnxt_hwrm_exec_fwd_resp( + bp, vf, sizeof(struct hwrm_port_phy_qcfg_input)); + } else { +- struct hwrm_port_phy_qcfg_output phy_qcfg_resp = {0}; ++ struct hwrm_port_phy_qcfg_output_compat phy_qcfg_resp = {}; + struct hwrm_port_phy_qcfg_input *phy_qcfg_req; + + phy_qcfg_req = +@@ -1096,6 +1099,11 @@ static int bnxt_vf_set_link(struct bnxt *bp, struct bnxt_vf_info *vf) + mutex_unlock(&bp->link_lock); + phy_qcfg_resp.resp_len = cpu_to_le16(sizeof(phy_qcfg_resp)); + phy_qcfg_resp.seq_id = phy_qcfg_req->seq_id; ++ /* New SPEEDS2 fields are beyond the legacy structure, so ++ * clear the SPEEDS2_SUPPORTED flag. ++ */ ++ phy_qcfg_resp.option_flags &= ++ ~PORT_PHY_QCAPS_RESP_FLAGS2_SPEEDS2_SUPPORTED; + phy_qcfg_resp.valid = 1; + + if (vf->flags & BNXT_VF_LINK_UP) { +-- +2.43.0 + diff --git a/queue-6.9/cachefiles-add-output-string-to-cachefiles_obj_-get-.patch b/queue-6.9/cachefiles-add-output-string-to-cachefiles_obj_-get-.patch new file mode 100644 index 00000000000..e233f235554 --- /dev/null +++ b/queue-6.9/cachefiles-add-output-string-to-cachefiles_obj_-get-.patch @@ -0,0 +1,40 @@ +From 09d028fd3f55edf0b34e46738441d7120b1ba020 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 May 2024 19:42:57 +0800 +Subject: cachefiles: add output string to cachefiles_obj_[get|put]_ondemand_fd + +From: Baokun Li + +[ Upstream commit cc5ac966f26193ab185cc43d64d9f1ae998ccb6e ] + +This lets us see the correct trace output. + +Fixes: c8383054506c ("cachefiles: notify the user daemon when looking up cookie") +Signed-off-by: Baokun Li +Link: https://lore.kernel.org/r/20240522114308.2402121-2-libaokun@huaweicloud.com +Acked-by: Jeff Layton +Reviewed-by: Jingbo Xu +Signed-off-by: Christian Brauner +Signed-off-by: Sasha Levin +--- + include/trace/events/cachefiles.h | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/include/trace/events/cachefiles.h b/include/trace/events/cachefiles.h +index cf4b98b9a9edc..e3213af847cdf 100644 +--- a/include/trace/events/cachefiles.h ++++ b/include/trace/events/cachefiles.h +@@ -127,7 +127,9 @@ enum cachefiles_error_trace { + EM(cachefiles_obj_see_lookup_cookie, "SEE lookup_cookie") \ + EM(cachefiles_obj_see_lookup_failed, "SEE lookup_failed") \ + EM(cachefiles_obj_see_withdraw_cookie, "SEE withdraw_cookie") \ +- E_(cachefiles_obj_see_withdrawal, "SEE withdrawal") ++ EM(cachefiles_obj_see_withdrawal, "SEE withdrawal") \ ++ EM(cachefiles_obj_get_ondemand_fd, "GET ondemand_fd") \ ++ E_(cachefiles_obj_put_ondemand_fd, "PUT ondemand_fd") + + #define cachefiles_coherency_traces \ + EM(cachefiles_coherency_check_aux, "BAD aux ") \ +-- +2.43.0 + diff --git a/queue-6.9/cachefiles-add-spin_lock-for-cachefiles_ondemand_inf.patch b/queue-6.9/cachefiles-add-spin_lock-for-cachefiles_ondemand_inf.patch new file mode 100644 index 00000000000..2ba159ff4dd --- /dev/null +++ b/queue-6.9/cachefiles-add-spin_lock-for-cachefiles_ondemand_inf.patch @@ -0,0 +1,138 @@ +From 9002add39838ca539cf3e6eaedb9023884ae01de Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 May 2024 19:43:03 +0800 +Subject: cachefiles: add spin_lock for cachefiles_ondemand_info + +From: Baokun Li + +[ Upstream commit 0a790040838c736495d5afd6b2d636f159f817f1 ] + +The following concurrency may cause a read request to fail to be completed +and result in a hung: + + t1 | t2 +--------------------------------------------------------- + cachefiles_ondemand_copen + req = xa_erase(&cache->reqs, id) +// Anon fd is maliciously closed. +cachefiles_ondemand_fd_release + xa_lock(&cache->reqs) + cachefiles_ondemand_set_object_close(object) + xa_unlock(&cache->reqs) + cachefiles_ondemand_set_object_open + // No one will ever close it again. +cachefiles_ondemand_daemon_read + cachefiles_ondemand_select_req + // Get a read req but its fd is already closed. + // The daemon can't issue a cread ioctl with an closed fd, then hung. + +So add spin_lock for cachefiles_ondemand_info to protect ondemand_id and +state, thus we can avoid the above problem in cachefiles_ondemand_copen() +by using ondemand_id to determine if fd has been closed. + +Fixes: c8383054506c ("cachefiles: notify the user daemon when looking up cookie") +Signed-off-by: Baokun Li +Link: https://lore.kernel.org/r/20240522114308.2402121-8-libaokun@huaweicloud.com +Acked-by: Jeff Layton +Signed-off-by: Christian Brauner +Signed-off-by: Sasha Levin +--- + fs/cachefiles/internal.h | 1 + + fs/cachefiles/ondemand.c | 35 ++++++++++++++++++++++++++++++++++- + 2 files changed, 35 insertions(+), 1 deletion(-) + +diff --git a/fs/cachefiles/internal.h b/fs/cachefiles/internal.h +index 7745b8abc3aa3..45c8bed605383 100644 +--- a/fs/cachefiles/internal.h ++++ b/fs/cachefiles/internal.h +@@ -55,6 +55,7 @@ struct cachefiles_ondemand_info { + int ondemand_id; + enum cachefiles_object_state state; + struct cachefiles_object *object; ++ spinlock_t lock; + }; + + /* +diff --git a/fs/cachefiles/ondemand.c b/fs/cachefiles/ondemand.c +index 3dd002108a872..7b667ddc84ca5 100644 +--- a/fs/cachefiles/ondemand.c ++++ b/fs/cachefiles/ondemand.c +@@ -16,13 +16,16 @@ static int cachefiles_ondemand_fd_release(struct inode *inode, + struct cachefiles_object *object = file->private_data; + struct cachefiles_cache *cache = object->volume->cache; + struct cachefiles_ondemand_info *info = object->ondemand; +- int object_id = info->ondemand_id; ++ int object_id; + struct cachefiles_req *req; + XA_STATE(xas, &cache->reqs, 0); + + xa_lock(&cache->reqs); ++ spin_lock(&info->lock); ++ object_id = info->ondemand_id; + info->ondemand_id = CACHEFILES_ONDEMAND_ID_CLOSED; + cachefiles_ondemand_set_object_close(object); ++ spin_unlock(&info->lock); + + /* Only flush CACHEFILES_REQ_NEW marked req to avoid race with daemon_read */ + xas_for_each_marked(&xas, req, ULONG_MAX, CACHEFILES_REQ_NEW) { +@@ -122,6 +125,7 @@ int cachefiles_ondemand_copen(struct cachefiles_cache *cache, char *args) + { + struct cachefiles_req *req; + struct fscache_cookie *cookie; ++ struct cachefiles_ondemand_info *info; + char *pid, *psize; + unsigned long id; + long size; +@@ -172,6 +176,33 @@ int cachefiles_ondemand_copen(struct cachefiles_cache *cache, char *args) + goto out; + } + ++ info = req->object->ondemand; ++ spin_lock(&info->lock); ++ /* ++ * The anonymous fd was closed before copen ? Fail the request. ++ * ++ * t1 | t2 ++ * --------------------------------------------------------- ++ * cachefiles_ondemand_copen ++ * req = xa_erase(&cache->reqs, id) ++ * // Anon fd is maliciously closed. ++ * cachefiles_ondemand_fd_release ++ * xa_lock(&cache->reqs) ++ * cachefiles_ondemand_set_object_close(object) ++ * xa_unlock(&cache->reqs) ++ * cachefiles_ondemand_set_object_open ++ * // No one will ever close it again. ++ * cachefiles_ondemand_daemon_read ++ * cachefiles_ondemand_select_req ++ * ++ * Get a read req but its fd is already closed. The daemon can't ++ * issue a cread ioctl with an closed fd, then hung. ++ */ ++ if (info->ondemand_id == CACHEFILES_ONDEMAND_ID_CLOSED) { ++ spin_unlock(&info->lock); ++ req->error = -EBADFD; ++ goto out; ++ } + cookie = req->object->cookie; + cookie->object_size = size; + if (size) +@@ -181,6 +212,7 @@ int cachefiles_ondemand_copen(struct cachefiles_cache *cache, char *args) + trace_cachefiles_ondemand_copen(req->object, id, size); + + cachefiles_ondemand_set_object_open(req->object); ++ spin_unlock(&info->lock); + wake_up_all(&cache->daemon_pollwq); + + out: +@@ -596,6 +628,7 @@ int cachefiles_ondemand_init_obj_info(struct cachefiles_object *object, + return -ENOMEM; + + object->ondemand->object = object; ++ spin_lock_init(&object->ondemand->lock); + INIT_WORK(&object->ondemand->ondemand_work, ondemand_object_worker); + return 0; + } +-- +2.43.0 + diff --git a/queue-6.9/cachefiles-defer-exposing-anon_fd-until-after-copy_t.patch b/queue-6.9/cachefiles-defer-exposing-anon_fd-until-after-copy_t.patch new file mode 100644 index 00000000000..6934b04538a --- /dev/null +++ b/queue-6.9/cachefiles-defer-exposing-anon_fd-until-after-copy_t.patch @@ -0,0 +1,164 @@ +From 3a859de049d490ec098146936a925681a3f72a5e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 May 2024 19:43:05 +0800 +Subject: cachefiles: defer exposing anon_fd until after copy_to_user() + succeeds + +From: Baokun Li + +[ Upstream commit 4b4391e77a6bf24cba2ef1590e113d9b73b11039 ] + +After installing the anonymous fd, we can now see it in userland and close +it. However, at this point we may not have gotten the reference count of +the cache, but we will put it during colse fd, so this may cause a cache +UAF. + +So grab the cache reference count before fd_install(). In addition, by +kernel convention, fd is taken over by the user land after fd_install(), +and the kernel should not call close_fd() after that, i.e., it should call +fd_install() after everything is ready, thus fd_install() is called after +copy_to_user() succeeds. + +Fixes: c8383054506c ("cachefiles: notify the user daemon when looking up cookie") +Suggested-by: Hou Tao +Signed-off-by: Baokun Li +Link: https://lore.kernel.org/r/20240522114308.2402121-10-libaokun@huaweicloud.com +Acked-by: Jeff Layton +Signed-off-by: Christian Brauner +Signed-off-by: Sasha Levin +--- + fs/cachefiles/ondemand.c | 53 +++++++++++++++++++++++++--------------- + 1 file changed, 33 insertions(+), 20 deletions(-) + +diff --git a/fs/cachefiles/ondemand.c b/fs/cachefiles/ondemand.c +index dbcd4161ea3a1..89f118d68d125 100644 +--- a/fs/cachefiles/ondemand.c ++++ b/fs/cachefiles/ondemand.c +@@ -4,6 +4,11 @@ + #include + #include "internal.h" + ++struct ondemand_anon_file { ++ struct file *file; ++ int fd; ++}; ++ + static inline void cachefiles_req_put(struct cachefiles_req *req) + { + if (refcount_dec_and_test(&req->ref)) +@@ -250,14 +255,14 @@ int cachefiles_ondemand_restore(struct cachefiles_cache *cache, char *args) + return 0; + } + +-static int cachefiles_ondemand_get_fd(struct cachefiles_req *req) ++static int cachefiles_ondemand_get_fd(struct cachefiles_req *req, ++ struct ondemand_anon_file *anon_file) + { + struct cachefiles_object *object; + struct cachefiles_cache *cache; + struct cachefiles_open *load; +- struct file *file; + u32 object_id; +- int ret, fd; ++ int ret; + + object = cachefiles_grab_object(req->object, + cachefiles_obj_get_ondemand_fd); +@@ -269,16 +274,16 @@ static int cachefiles_ondemand_get_fd(struct cachefiles_req *req) + if (ret < 0) + goto err; + +- fd = get_unused_fd_flags(O_WRONLY); +- if (fd < 0) { +- ret = fd; ++ anon_file->fd = get_unused_fd_flags(O_WRONLY); ++ if (anon_file->fd < 0) { ++ ret = anon_file->fd; + goto err_free_id; + } + +- file = anon_inode_getfile("[cachefiles]", &cachefiles_ondemand_fd_fops, +- object, O_WRONLY); +- if (IS_ERR(file)) { +- ret = PTR_ERR(file); ++ anon_file->file = anon_inode_getfile("[cachefiles]", ++ &cachefiles_ondemand_fd_fops, object, O_WRONLY); ++ if (IS_ERR(anon_file->file)) { ++ ret = PTR_ERR(anon_file->file); + goto err_put_fd; + } + +@@ -286,16 +291,15 @@ static int cachefiles_ondemand_get_fd(struct cachefiles_req *req) + if (object->ondemand->ondemand_id > 0) { + spin_unlock(&object->ondemand->lock); + /* Pair with check in cachefiles_ondemand_fd_release(). */ +- file->private_data = NULL; ++ anon_file->file->private_data = NULL; + ret = -EEXIST; + goto err_put_file; + } + +- file->f_mode |= FMODE_PWRITE | FMODE_LSEEK; +- fd_install(fd, file); ++ anon_file->file->f_mode |= FMODE_PWRITE | FMODE_LSEEK; + + load = (void *)req->msg.data; +- load->fd = fd; ++ load->fd = anon_file->fd; + object->ondemand->ondemand_id = object_id; + spin_unlock(&object->ondemand->lock); + +@@ -304,9 +308,11 @@ static int cachefiles_ondemand_get_fd(struct cachefiles_req *req) + return 0; + + err_put_file: +- fput(file); ++ fput(anon_file->file); ++ anon_file->file = NULL; + err_put_fd: +- put_unused_fd(fd); ++ put_unused_fd(anon_file->fd); ++ anon_file->fd = ret; + err_free_id: + xa_erase(&cache->ondemand_ids, object_id); + err: +@@ -363,6 +369,7 @@ ssize_t cachefiles_ondemand_daemon_read(struct cachefiles_cache *cache, + struct cachefiles_msg *msg; + size_t n; + int ret = 0; ++ struct ondemand_anon_file anon_file; + XA_STATE(xas, &cache->reqs, cache->req_id_next); + + xa_lock(&cache->reqs); +@@ -396,7 +403,7 @@ ssize_t cachefiles_ondemand_daemon_read(struct cachefiles_cache *cache, + xa_unlock(&cache->reqs); + + if (msg->opcode == CACHEFILES_OP_OPEN) { +- ret = cachefiles_ondemand_get_fd(req); ++ ret = cachefiles_ondemand_get_fd(req, &anon_file); + if (ret) + goto out; + } +@@ -404,10 +411,16 @@ ssize_t cachefiles_ondemand_daemon_read(struct cachefiles_cache *cache, + msg->msg_id = xas.xa_index; + msg->object_id = req->object->ondemand->ondemand_id; + +- if (copy_to_user(_buffer, msg, n) != 0) { ++ if (copy_to_user(_buffer, msg, n) != 0) + ret = -EFAULT; +- if (msg->opcode == CACHEFILES_OP_OPEN) +- close_fd(((struct cachefiles_open *)msg->data)->fd); ++ ++ if (msg->opcode == CACHEFILES_OP_OPEN) { ++ if (ret < 0) { ++ fput(anon_file.file); ++ put_unused_fd(anon_file.fd); ++ goto out; ++ } ++ fd_install(anon_file.fd, anon_file.file); + } + out: + cachefiles_put_object(req->object, cachefiles_obj_put_read_req); +-- +2.43.0 + diff --git a/queue-6.9/cachefiles-fix-slab-use-after-free-in-cachefiles_ond.patch b/queue-6.9/cachefiles-fix-slab-use-after-free-in-cachefiles_ond.patch new file mode 100644 index 00000000000..2acebb93785 --- /dev/null +++ b/queue-6.9/cachefiles-fix-slab-use-after-free-in-cachefiles_ond.patch @@ -0,0 +1,188 @@ +From 0c87d9263994fb9d66b8968b4224a30e003aa25b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 May 2024 19:42:59 +0800 +Subject: cachefiles: fix slab-use-after-free in cachefiles_ondemand_get_fd() + +From: Baokun Li + +[ Upstream commit de3e26f9e5b76fc628077578c001c4a51bf54d06 ] + +We got the following issue in a fuzz test of randomly issuing the restore +command: + +================================================================== +BUG: KASAN: slab-use-after-free in cachefiles_ondemand_daemon_read+0x609/0xab0 +Write of size 4 at addr ffff888109164a80 by task ondemand-04-dae/4962 + +CPU: 11 PID: 4962 Comm: ondemand-04-dae Not tainted 6.8.0-rc7-dirty #542 +Call Trace: + kasan_report+0x94/0xc0 + cachefiles_ondemand_daemon_read+0x609/0xab0 + vfs_read+0x169/0xb50 + ksys_read+0xf5/0x1e0 + +Allocated by task 626: + __kmalloc+0x1df/0x4b0 + cachefiles_ondemand_send_req+0x24d/0x690 + cachefiles_create_tmpfile+0x249/0xb30 + cachefiles_create_file+0x6f/0x140 + cachefiles_look_up_object+0x29c/0xa60 + cachefiles_lookup_cookie+0x37d/0xca0 + fscache_cookie_state_machine+0x43c/0x1230 + [...] + +Freed by task 626: + kfree+0xf1/0x2c0 + cachefiles_ondemand_send_req+0x568/0x690 + cachefiles_create_tmpfile+0x249/0xb30 + cachefiles_create_file+0x6f/0x140 + cachefiles_look_up_object+0x29c/0xa60 + cachefiles_lookup_cookie+0x37d/0xca0 + fscache_cookie_state_machine+0x43c/0x1230 + [...] +================================================================== + +Following is the process that triggers the issue: + + mount | daemon_thread1 | daemon_thread2 +------------------------------------------------------------ + cachefiles_ondemand_init_object + cachefiles_ondemand_send_req + REQ_A = kzalloc(sizeof(*req) + data_len) + wait_for_completion(&REQ_A->done) + + cachefiles_daemon_read + cachefiles_ondemand_daemon_read + REQ_A = cachefiles_ondemand_select_req + cachefiles_ondemand_get_fd + copy_to_user(_buffer, msg, n) + process_open_req(REQ_A) + ------ restore ------ + cachefiles_ondemand_restore + xas_for_each(&xas, req, ULONG_MAX) + xas_set_mark(&xas, CACHEFILES_REQ_NEW); + + cachefiles_daemon_read + cachefiles_ondemand_daemon_read + REQ_A = cachefiles_ondemand_select_req + + write(devfd, ("copen %u,%llu", msg->msg_id, size)); + cachefiles_ondemand_copen + xa_erase(&cache->reqs, id) + complete(&REQ_A->done) + kfree(REQ_A) + cachefiles_ondemand_get_fd(REQ_A) + fd = get_unused_fd_flags + file = anon_inode_getfile + fd_install(fd, file) + load = (void *)REQ_A->msg.data; + load->fd = fd; + // load UAF !!! + +This issue is caused by issuing a restore command when the daemon is still +alive, which results in a request being processed multiple times thus +triggering a UAF. So to avoid this problem, add an additional reference +count to cachefiles_req, which is held while waiting and reading, and then +released when the waiting and reading is over. + +Note that since there is only one reference count for waiting, we need to +avoid the same request being completed multiple times, so we can only +complete the request if it is successfully removed from the xarray. + +Fixes: e73fa11a356c ("cachefiles: add restore command to recover inflight ondemand read requests") +Suggested-by: Hou Tao +Signed-off-by: Baokun Li +Link: https://lore.kernel.org/r/20240522114308.2402121-4-libaokun@huaweicloud.com +Acked-by: Jeff Layton +Reviewed-by: Jia Zhu +Reviewed-by: Jingbo Xu +Signed-off-by: Christian Brauner +Signed-off-by: Sasha Levin +--- + fs/cachefiles/internal.h | 1 + + fs/cachefiles/ondemand.c | 23 +++++++++++++++++++---- + 2 files changed, 20 insertions(+), 4 deletions(-) + +diff --git a/fs/cachefiles/internal.h b/fs/cachefiles/internal.h +index d33169f0018b1..7745b8abc3aa3 100644 +--- a/fs/cachefiles/internal.h ++++ b/fs/cachefiles/internal.h +@@ -138,6 +138,7 @@ static inline bool cachefiles_in_ondemand_mode(struct cachefiles_cache *cache) + struct cachefiles_req { + struct cachefiles_object *object; + struct completion done; ++ refcount_t ref; + int error; + struct cachefiles_msg msg; + }; +diff --git a/fs/cachefiles/ondemand.c b/fs/cachefiles/ondemand.c +index 4ba42f1fa3b40..c011fb24d2382 100644 +--- a/fs/cachefiles/ondemand.c ++++ b/fs/cachefiles/ondemand.c +@@ -4,6 +4,12 @@ + #include + #include "internal.h" + ++static inline void cachefiles_req_put(struct cachefiles_req *req) ++{ ++ if (refcount_dec_and_test(&req->ref)) ++ kfree(req); ++} ++ + static int cachefiles_ondemand_fd_release(struct inode *inode, + struct file *file) + { +@@ -330,6 +336,7 @@ ssize_t cachefiles_ondemand_daemon_read(struct cachefiles_cache *cache, + + xas_clear_mark(&xas, CACHEFILES_REQ_NEW); + cache->req_id_next = xas.xa_index + 1; ++ refcount_inc(&req->ref); + xa_unlock(&cache->reqs); + + id = xas.xa_index; +@@ -356,15 +363,22 @@ ssize_t cachefiles_ondemand_daemon_read(struct cachefiles_cache *cache, + complete(&req->done); + } + ++ cachefiles_req_put(req); + return n; + + err_put_fd: + if (msg->opcode == CACHEFILES_OP_OPEN) + close_fd(((struct cachefiles_open *)msg->data)->fd); + error: +- xa_erase(&cache->reqs, id); +- req->error = ret; +- complete(&req->done); ++ xas_reset(&xas); ++ xas_lock(&xas); ++ if (xas_load(&xas) == req) { ++ req->error = ret; ++ complete(&req->done); ++ xas_store(&xas, NULL); ++ } ++ xas_unlock(&xas); ++ cachefiles_req_put(req); + return ret; + } + +@@ -395,6 +409,7 @@ static int cachefiles_ondemand_send_req(struct cachefiles_object *object, + goto out; + } + ++ refcount_set(&req->ref, 1); + req->object = object; + init_completion(&req->done); + req->msg.opcode = opcode; +@@ -456,7 +471,7 @@ static int cachefiles_ondemand_send_req(struct cachefiles_object *object, + wake_up_all(&cache->daemon_pollwq); + wait_for_completion(&req->done); + ret = req->error; +- kfree(req); ++ cachefiles_req_put(req); + return ret; + out: + /* Reset the object to close state in error handling path. +-- +2.43.0 + diff --git a/queue-6.9/cachefiles-fix-slab-use-after-free-in-cachefiles_ond.patch-26654 b/queue-6.9/cachefiles-fix-slab-use-after-free-in-cachefiles_ond.patch-26654 new file mode 100644 index 00000000000..23cc9fc1ad1 --- /dev/null +++ b/queue-6.9/cachefiles-fix-slab-use-after-free-in-cachefiles_ond.patch-26654 @@ -0,0 +1,142 @@ +From da60c1a799f9e92d369c287838b86116645baae2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 May 2024 19:43:00 +0800 +Subject: cachefiles: fix slab-use-after-free in + cachefiles_ondemand_daemon_read() + +From: Baokun Li + +[ Upstream commit da4a827416066191aafeeccee50a8836a826ba10 ] + +We got the following issue in a fuzz test of randomly issuing the restore +command: + +================================================================== +BUG: KASAN: slab-use-after-free in cachefiles_ondemand_daemon_read+0xb41/0xb60 +Read of size 8 at addr ffff888122e84088 by task ondemand-04-dae/963 + +CPU: 13 PID: 963 Comm: ondemand-04-dae Not tainted 6.8.0-dirty #564 +Call Trace: + kasan_report+0x93/0xc0 + cachefiles_ondemand_daemon_read+0xb41/0xb60 + vfs_read+0x169/0xb50 + ksys_read+0xf5/0x1e0 + +Allocated by task 116: + kmem_cache_alloc+0x140/0x3a0 + cachefiles_lookup_cookie+0x140/0xcd0 + fscache_cookie_state_machine+0x43c/0x1230 + [...] + +Freed by task 792: + kmem_cache_free+0xfe/0x390 + cachefiles_put_object+0x241/0x480 + fscache_cookie_state_machine+0x5c8/0x1230 + [...] +================================================================== + +Following is the process that triggers the issue: + + mount | daemon_thread1 | daemon_thread2 +------------------------------------------------------------ +cachefiles_withdraw_cookie + cachefiles_ondemand_clean_object(object) + cachefiles_ondemand_send_req + REQ_A = kzalloc(sizeof(*req) + data_len) + wait_for_completion(&REQ_A->done) + + cachefiles_daemon_read + cachefiles_ondemand_daemon_read + REQ_A = cachefiles_ondemand_select_req + msg->object_id = req->object->ondemand->ondemand_id + ------ restore ------ + cachefiles_ondemand_restore + xas_for_each(&xas, req, ULONG_MAX) + xas_set_mark(&xas, CACHEFILES_REQ_NEW) + + cachefiles_daemon_read + cachefiles_ondemand_daemon_read + REQ_A = cachefiles_ondemand_select_req + copy_to_user(_buffer, msg, n) + xa_erase(&cache->reqs, id) + complete(&REQ_A->done) + ------ close(fd) ------ + cachefiles_ondemand_fd_release + cachefiles_put_object + cachefiles_put_object + kmem_cache_free(cachefiles_object_jar, object) + REQ_A->object->ondemand->ondemand_id + // object UAF !!! + +When we see the request within xa_lock, req->object must not have been +freed yet, so grab the reference count of object before xa_unlock to +avoid the above issue. + +Fixes: 0a7e54c1959c ("cachefiles: resend an open request if the read request's object is closed") +Signed-off-by: Baokun Li +Link: https://lore.kernel.org/r/20240522114308.2402121-5-libaokun@huaweicloud.com +Acked-by: Jeff Layton +Reviewed-by: Jia Zhu +Reviewed-by: Jingbo Xu +Signed-off-by: Christian Brauner +Signed-off-by: Sasha Levin +--- + fs/cachefiles/ondemand.c | 3 +++ + include/trace/events/cachefiles.h | 6 +++++- + 2 files changed, 8 insertions(+), 1 deletion(-) + +diff --git a/fs/cachefiles/ondemand.c b/fs/cachefiles/ondemand.c +index c011fb24d2382..3dd002108a872 100644 +--- a/fs/cachefiles/ondemand.c ++++ b/fs/cachefiles/ondemand.c +@@ -337,6 +337,7 @@ ssize_t cachefiles_ondemand_daemon_read(struct cachefiles_cache *cache, + xas_clear_mark(&xas, CACHEFILES_REQ_NEW); + cache->req_id_next = xas.xa_index + 1; + refcount_inc(&req->ref); ++ cachefiles_grab_object(req->object, cachefiles_obj_get_read_req); + xa_unlock(&cache->reqs); + + id = xas.xa_index; +@@ -357,6 +358,7 @@ ssize_t cachefiles_ondemand_daemon_read(struct cachefiles_cache *cache, + goto err_put_fd; + } + ++ cachefiles_put_object(req->object, cachefiles_obj_put_read_req); + /* CLOSE request has no reply */ + if (msg->opcode == CACHEFILES_OP_CLOSE) { + xa_erase(&cache->reqs, id); +@@ -370,6 +372,7 @@ ssize_t cachefiles_ondemand_daemon_read(struct cachefiles_cache *cache, + if (msg->opcode == CACHEFILES_OP_OPEN) + close_fd(((struct cachefiles_open *)msg->data)->fd); + error: ++ cachefiles_put_object(req->object, cachefiles_obj_put_read_req); + xas_reset(&xas); + xas_lock(&xas); + if (xas_load(&xas) == req) { +diff --git a/include/trace/events/cachefiles.h b/include/trace/events/cachefiles.h +index e3213af847cdf..7d931db02b934 100644 +--- a/include/trace/events/cachefiles.h ++++ b/include/trace/events/cachefiles.h +@@ -33,6 +33,8 @@ enum cachefiles_obj_ref_trace { + cachefiles_obj_see_withdrawal, + cachefiles_obj_get_ondemand_fd, + cachefiles_obj_put_ondemand_fd, ++ cachefiles_obj_get_read_req, ++ cachefiles_obj_put_read_req, + }; + + enum fscache_why_object_killed { +@@ -129,7 +131,9 @@ enum cachefiles_error_trace { + EM(cachefiles_obj_see_withdraw_cookie, "SEE withdraw_cookie") \ + EM(cachefiles_obj_see_withdrawal, "SEE withdrawal") \ + EM(cachefiles_obj_get_ondemand_fd, "GET ondemand_fd") \ +- E_(cachefiles_obj_put_ondemand_fd, "PUT ondemand_fd") ++ EM(cachefiles_obj_put_ondemand_fd, "PUT ondemand_fd") \ ++ EM(cachefiles_obj_get_read_req, "GET read_req") \ ++ E_(cachefiles_obj_put_read_req, "PUT read_req") + + #define cachefiles_coherency_traces \ + EM(cachefiles_coherency_check_aux, "BAD aux ") \ +-- +2.43.0 + diff --git a/queue-6.9/cachefiles-flush-all-requests-after-setting-cachefil.patch b/queue-6.9/cachefiles-flush-all-requests-after-setting-cachefil.patch new file mode 100644 index 00000000000..47f969fd87b --- /dev/null +++ b/queue-6.9/cachefiles-flush-all-requests-after-setting-cachefil.patch @@ -0,0 +1,71 @@ +From 5c89ce24677a374d4a64bd4958bb9f22f59c81ca Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 May 2024 19:43:07 +0800 +Subject: cachefiles: flush all requests after setting CACHEFILES_DEAD + +From: Baokun Li + +[ Upstream commit 85e833cd7243bda7285492b0653c3abb1e2e757b ] + +In ondemand mode, when the daemon is processing an open request, if the +kernel flags the cache as CACHEFILES_DEAD, the cachefiles_daemon_write() +will always return -EIO, so the daemon can't pass the copen to the kernel. +Then the kernel process that is waiting for the copen triggers a hung_task. + +Since the DEAD state is irreversible, it can only be exited by closing +/dev/cachefiles. Therefore, after calling cachefiles_io_error() to mark +the cache as CACHEFILES_DEAD, if in ondemand mode, flush all requests to +avoid the above hungtask. We may still be able to read some of the cached +data before closing the fd of /dev/cachefiles. + +Note that this relies on the patch that adds reference counting to the req, +otherwise it may UAF. + +Fixes: c8383054506c ("cachefiles: notify the user daemon when looking up cookie") +Signed-off-by: Baokun Li +Link: https://lore.kernel.org/r/20240522114308.2402121-12-libaokun@huaweicloud.com +Acked-by: Jeff Layton +Signed-off-by: Christian Brauner +Signed-off-by: Sasha Levin +--- + fs/cachefiles/daemon.c | 2 +- + fs/cachefiles/internal.h | 3 +++ + 2 files changed, 4 insertions(+), 1 deletion(-) + +diff --git a/fs/cachefiles/daemon.c b/fs/cachefiles/daemon.c +index ccb7b707ea4b7..06cdf1a8a16f6 100644 +--- a/fs/cachefiles/daemon.c ++++ b/fs/cachefiles/daemon.c +@@ -133,7 +133,7 @@ static int cachefiles_daemon_open(struct inode *inode, struct file *file) + return 0; + } + +-static void cachefiles_flush_reqs(struct cachefiles_cache *cache) ++void cachefiles_flush_reqs(struct cachefiles_cache *cache) + { + struct xarray *xa = &cache->reqs; + struct cachefiles_req *req; +diff --git a/fs/cachefiles/internal.h b/fs/cachefiles/internal.h +index 45c8bed605383..6845a90cdfcce 100644 +--- a/fs/cachefiles/internal.h ++++ b/fs/cachefiles/internal.h +@@ -188,6 +188,7 @@ extern int cachefiles_has_space(struct cachefiles_cache *cache, + * daemon.c + */ + extern const struct file_operations cachefiles_daemon_fops; ++extern void cachefiles_flush_reqs(struct cachefiles_cache *cache); + extern void cachefiles_get_unbind_pincount(struct cachefiles_cache *cache); + extern void cachefiles_put_unbind_pincount(struct cachefiles_cache *cache); + +@@ -426,6 +427,8 @@ do { \ + pr_err("I/O Error: " FMT"\n", ##__VA_ARGS__); \ + fscache_io_error((___cache)->cache); \ + set_bit(CACHEFILES_DEAD, &(___cache)->flags); \ ++ if (cachefiles_in_ondemand_mode(___cache)) \ ++ cachefiles_flush_reqs(___cache); \ + } while (0) + + #define cachefiles_io_error_obj(object, FMT, ...) \ +-- +2.43.0 + diff --git a/queue-6.9/cachefiles-never-get-a-new-anonymous-fd-if-ondemand_.patch b/queue-6.9/cachefiles-never-get-a-new-anonymous-fd-if-ondemand_.patch new file mode 100644 index 00000000000..ec83299e2f1 --- /dev/null +++ b/queue-6.9/cachefiles-never-get-a-new-anonymous-fd-if-ondemand_.patch @@ -0,0 +1,165 @@ +From 4a2ae6608b7eae78d2e3ec9966b152b7ca62fb1c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 May 2024 19:43:04 +0800 +Subject: cachefiles: never get a new anonymous fd if ondemand_id is valid + +From: Baokun Li + +[ Upstream commit 4988e35e95fc938bdde0e15880fe72042fc86acf ] + +Now every time the daemon reads an open request, it gets a new anonymous fd +and ondemand_id. With the introduction of "restore", it is possible to read +the same open request more than once, and therefore an object can have more +than one anonymous fd. + +If the anonymous fd is not unique, the following concurrencies will result +in an fd leak: + + t1 | t2 | t3 +------------------------------------------------------------ + cachefiles_ondemand_init_object + cachefiles_ondemand_send_req + REQ_A = kzalloc(sizeof(*req) + data_len) + wait_for_completion(&REQ_A->done) + cachefiles_daemon_read + cachefiles_ondemand_daemon_read + REQ_A = cachefiles_ondemand_select_req + cachefiles_ondemand_get_fd + load->fd = fd0 + ondemand_id = object_id0 + ------ restore ------ + cachefiles_ondemand_restore + // restore REQ_A + cachefiles_daemon_read + cachefiles_ondemand_daemon_read + REQ_A = cachefiles_ondemand_select_req + cachefiles_ondemand_get_fd + load->fd = fd1 + ondemand_id = object_id1 + process_open_req(REQ_A) + write(devfd, ("copen %u,%llu", msg->msg_id, size)) + cachefiles_ondemand_copen + xa_erase(&cache->reqs, id) + complete(&REQ_A->done) + kfree(REQ_A) + process_open_req(REQ_A) + // copen fails due to no req + // daemon close(fd1) + cachefiles_ondemand_fd_release + // set object closed + -- umount -- + cachefiles_withdraw_cookie + cachefiles_ondemand_clean_object + cachefiles_ondemand_init_close_req + if (!cachefiles_ondemand_object_is_open(object)) + return -ENOENT; + // The fd0 is not closed until the daemon exits. + +However, the anonymous fd holds the reference count of the object and the +object holds the reference count of the cookie. So even though the cookie +has been relinquished, it will not be unhashed and freed until the daemon +exits. + +In fscache_hash_cookie(), when the same cookie is found in the hash list, +if the cookie is set with the FSCACHE_COOKIE_RELINQUISHED bit, then the new +cookie waits for the old cookie to be unhashed, while the old cookie is +waiting for the leaked fd to be closed, if the daemon does not exit in time +it will trigger a hung task. + +To avoid this, allocate a new anonymous fd only if no anonymous fd has +been allocated (ondemand_id == 0) or if the previously allocated anonymous +fd has been closed (ondemand_id == -1). Moreover, returns an error if +ondemand_id is valid, letting the daemon know that the current userland +restore logic is abnormal and needs to be checked. + +Fixes: c8383054506c ("cachefiles: notify the user daemon when looking up cookie") +Signed-off-by: Baokun Li +Link: https://lore.kernel.org/r/20240522114308.2402121-9-libaokun@huaweicloud.com +Acked-by: Jeff Layton +Signed-off-by: Christian Brauner +Signed-off-by: Sasha Levin +--- + fs/cachefiles/ondemand.c | 34 ++++++++++++++++++++++++++++------ + 1 file changed, 28 insertions(+), 6 deletions(-) + +diff --git a/fs/cachefiles/ondemand.c b/fs/cachefiles/ondemand.c +index c8389bb118f5b..dbcd4161ea3a1 100644 +--- a/fs/cachefiles/ondemand.c ++++ b/fs/cachefiles/ondemand.c +@@ -14,11 +14,18 @@ static int cachefiles_ondemand_fd_release(struct inode *inode, + struct file *file) + { + struct cachefiles_object *object = file->private_data; +- struct cachefiles_cache *cache = object->volume->cache; +- struct cachefiles_ondemand_info *info = object->ondemand; ++ struct cachefiles_cache *cache; ++ struct cachefiles_ondemand_info *info; + int object_id; + struct cachefiles_req *req; +- XA_STATE(xas, &cache->reqs, 0); ++ XA_STATE(xas, NULL, 0); ++ ++ if (!object) ++ return 0; ++ ++ info = object->ondemand; ++ cache = object->volume->cache; ++ xas.xa = &cache->reqs; + + xa_lock(&cache->reqs); + spin_lock(&info->lock); +@@ -275,22 +282,39 @@ static int cachefiles_ondemand_get_fd(struct cachefiles_req *req) + goto err_put_fd; + } + ++ spin_lock(&object->ondemand->lock); ++ if (object->ondemand->ondemand_id > 0) { ++ spin_unlock(&object->ondemand->lock); ++ /* Pair with check in cachefiles_ondemand_fd_release(). */ ++ file->private_data = NULL; ++ ret = -EEXIST; ++ goto err_put_file; ++ } ++ + file->f_mode |= FMODE_PWRITE | FMODE_LSEEK; + fd_install(fd, file); + + load = (void *)req->msg.data; + load->fd = fd; + object->ondemand->ondemand_id = object_id; ++ spin_unlock(&object->ondemand->lock); + + cachefiles_get_unbind_pincount(cache); + trace_cachefiles_ondemand_open(object, &req->msg, load); + return 0; + ++err_put_file: ++ fput(file); + err_put_fd: + put_unused_fd(fd); + err_free_id: + xa_erase(&cache->ondemand_ids, object_id); + err: ++ spin_lock(&object->ondemand->lock); ++ /* Avoid marking an opened object as closed. */ ++ if (object->ondemand->ondemand_id <= 0) ++ cachefiles_ondemand_set_object_close(object); ++ spin_unlock(&object->ondemand->lock); + cachefiles_put_object(object, cachefiles_obj_put_ondemand_fd); + return ret; + } +@@ -373,10 +397,8 @@ ssize_t cachefiles_ondemand_daemon_read(struct cachefiles_cache *cache, + + if (msg->opcode == CACHEFILES_OP_OPEN) { + ret = cachefiles_ondemand_get_fd(req); +- if (ret) { +- cachefiles_ondemand_set_object_close(req->object); ++ if (ret) + goto out; +- } + } + + msg->msg_id = xas.xa_index; +-- +2.43.0 + diff --git a/queue-6.9/cachefiles-remove-err_put_fd-label-in-cachefiles_ond.patch b/queue-6.9/cachefiles-remove-err_put_fd-label-in-cachefiles_ond.patch new file mode 100644 index 00000000000..b110a2b4c4b --- /dev/null +++ b/queue-6.9/cachefiles-remove-err_put_fd-label-in-cachefiles_ond.patch @@ -0,0 +1,108 @@ +From cad9ddac3303dd901631002ce72419969319f074 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 May 2024 19:43:01 +0800 +Subject: cachefiles: remove err_put_fd label in + cachefiles_ondemand_daemon_read() + +From: Baokun Li + +[ Upstream commit 3e6d704f02aa4c50c7bc5fe91a4401df249a137b ] + +The err_put_fd label is only used once, so remove it to make the code +more readable. In addition, the logic for deleting error request and +CLOSE request is merged to simplify the code. + +Signed-off-by: Baokun Li +Link: https://lore.kernel.org/r/20240522114308.2402121-6-libaokun@huaweicloud.com +Acked-by: Jeff Layton +Reviewed-by: Jia Zhu +Reviewed-by: Gao Xiang +Reviewed-by: Jingbo Xu +Signed-off-by: Christian Brauner +Stable-dep-of: 4988e35e95fc ("cachefiles: never get a new anonymous fd if ondemand_id is valid") +Signed-off-by: Sasha Levin +--- + fs/cachefiles/ondemand.c | 45 ++++++++++++++-------------------------- + 1 file changed, 16 insertions(+), 29 deletions(-) + +diff --git a/fs/cachefiles/ondemand.c b/fs/cachefiles/ondemand.c +index 7b667ddc84ca5..c8389bb118f5b 100644 +--- a/fs/cachefiles/ondemand.c ++++ b/fs/cachefiles/ondemand.c +@@ -337,7 +337,6 @@ ssize_t cachefiles_ondemand_daemon_read(struct cachefiles_cache *cache, + { + struct cachefiles_req *req; + struct cachefiles_msg *msg; +- unsigned long id = 0; + size_t n; + int ret = 0; + XA_STATE(xas, &cache->reqs, cache->req_id_next); +@@ -372,49 +371,37 @@ ssize_t cachefiles_ondemand_daemon_read(struct cachefiles_cache *cache, + cachefiles_grab_object(req->object, cachefiles_obj_get_read_req); + xa_unlock(&cache->reqs); + +- id = xas.xa_index; +- + if (msg->opcode == CACHEFILES_OP_OPEN) { + ret = cachefiles_ondemand_get_fd(req); + if (ret) { + cachefiles_ondemand_set_object_close(req->object); +- goto error; ++ goto out; + } + } + +- msg->msg_id = id; ++ msg->msg_id = xas.xa_index; + msg->object_id = req->object->ondemand->ondemand_id; + + if (copy_to_user(_buffer, msg, n) != 0) { + ret = -EFAULT; +- goto err_put_fd; +- } +- +- cachefiles_put_object(req->object, cachefiles_obj_put_read_req); +- /* CLOSE request has no reply */ +- if (msg->opcode == CACHEFILES_OP_CLOSE) { +- xa_erase(&cache->reqs, id); +- complete(&req->done); ++ if (msg->opcode == CACHEFILES_OP_OPEN) ++ close_fd(((struct cachefiles_open *)msg->data)->fd); + } +- +- cachefiles_req_put(req); +- return n; +- +-err_put_fd: +- if (msg->opcode == CACHEFILES_OP_OPEN) +- close_fd(((struct cachefiles_open *)msg->data)->fd); +-error: ++out: + cachefiles_put_object(req->object, cachefiles_obj_put_read_req); +- xas_reset(&xas); +- xas_lock(&xas); +- if (xas_load(&xas) == req) { +- req->error = ret; +- complete(&req->done); +- xas_store(&xas, NULL); ++ /* Remove error request and CLOSE request has no reply */ ++ if (ret || msg->opcode == CACHEFILES_OP_CLOSE) { ++ xas_reset(&xas); ++ xas_lock(&xas); ++ if (xas_load(&xas) == req) { ++ req->error = ret; ++ complete(&req->done); ++ xas_store(&xas, NULL); ++ } ++ xas_unlock(&xas); + } +- xas_unlock(&xas); + cachefiles_req_put(req); +- return ret; ++ return ret ? ret : n; + } + + typedef int (*init_req_fn)(struct cachefiles_req *req, void *private); +-- +2.43.0 + diff --git a/queue-6.9/cachefiles-remove-requests-from-xarray-during-flushi.patch b/queue-6.9/cachefiles-remove-requests-from-xarray-during-flushi.patch new file mode 100644 index 00000000000..c75c3dee7f4 --- /dev/null +++ b/queue-6.9/cachefiles-remove-requests-from-xarray-during-flushi.patch @@ -0,0 +1,62 @@ +From 4bb8edc7bd6c798084a8d43ced490552b34b39ad Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 May 2024 19:42:58 +0800 +Subject: cachefiles: remove requests from xarray during flushing requests + +From: Baokun Li + +[ Upstream commit 0fc75c5940fa634d84e64c93bfc388e1274ed013 ] + +Even with CACHEFILES_DEAD set, we can still read the requests, so in the +following concurrency the request may be used after it has been freed: + + mount | daemon_thread1 | daemon_thread2 +------------------------------------------------------------ + cachefiles_ondemand_init_object + cachefiles_ondemand_send_req + REQ_A = kzalloc(sizeof(*req) + data_len) + wait_for_completion(&REQ_A->done) + cachefiles_daemon_read + cachefiles_ondemand_daemon_read + // close dev fd + cachefiles_flush_reqs + complete(&REQ_A->done) + kfree(REQ_A) + xa_lock(&cache->reqs); + cachefiles_ondemand_select_req + req->msg.opcode != CACHEFILES_OP_READ + // req use-after-free !!! + xa_unlock(&cache->reqs); + xa_destroy(&cache->reqs) + +Hence remove requests from cache->reqs when flushing them to avoid +accessing freed requests. + +Fixes: c8383054506c ("cachefiles: notify the user daemon when looking up cookie") +Signed-off-by: Baokun Li +Link: https://lore.kernel.org/r/20240522114308.2402121-3-libaokun@huaweicloud.com +Acked-by: Jeff Layton +Reviewed-by: Jia Zhu +Reviewed-by: Gao Xiang +Reviewed-by: Jingbo Xu +Signed-off-by: Christian Brauner +Signed-off-by: Sasha Levin +--- + fs/cachefiles/daemon.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/fs/cachefiles/daemon.c b/fs/cachefiles/daemon.c +index 6465e25742309..ccb7b707ea4b7 100644 +--- a/fs/cachefiles/daemon.c ++++ b/fs/cachefiles/daemon.c +@@ -159,6 +159,7 @@ static void cachefiles_flush_reqs(struct cachefiles_cache *cache) + xa_for_each(xa, index, req) { + req->error = -EIO; + complete(&req->done); ++ __xa_erase(xa, index); + } + xa_unlock(xa); + +-- +2.43.0 + diff --git a/queue-6.9/clk-sifive-do-not-register-clkdevs-for-prci-clocks.patch b/queue-6.9/clk-sifive-do-not-register-clkdevs-for-prci-clocks.patch new file mode 100644 index 00000000000..92ff86bc550 --- /dev/null +++ b/queue-6.9/clk-sifive-do-not-register-clkdevs-for-prci-clocks.patch @@ -0,0 +1,62 @@ +From bda1b0b3accb1390316e41f1f60091470dc77442 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 27 May 2024 17:14:12 -0700 +Subject: clk: sifive: Do not register clkdevs for PRCI clocks + +From: Samuel Holland + +[ Upstream commit 2607133196c35f31892ee199ce7ffa717bea4ad1 ] + +These clkdevs were unnecessary, because systems using this driver always +look up clocks using the devicetree. And as Russell King points out[1], +since the provided device name was truncated, lookups via clkdev would +never match. + +Recently, commit 8d532528ff6a ("clkdev: report over-sized strings when +creating clkdev entries") caused clkdev registration to fail due to the +truncation, and this now prevents the driver from probing. Fix the +driver by removing the clkdev registration. + +Link: https://lore.kernel.org/linux-clk/ZkfYqj+OcAxd9O2t@shell.armlinux.org.uk/ [1] +Fixes: 30b8e27e3b58 ("clk: sifive: add a driver for the SiFive FU540 PRCI IP block") +Fixes: 8d532528ff6a ("clkdev: report over-sized strings when creating clkdev entries") +Reported-by: Guenter Roeck +Closes: https://lore.kernel.org/linux-clk/7eda7621-0dde-4153-89e4-172e4c095d01@roeck-us.net/ +Suggested-by: Russell King +Signed-off-by: Samuel Holland +Link: https://lore.kernel.org/r/20240528001432.1200403-1-samuel.holland@sifive.com +Signed-off-by: Stephen Boyd +Signed-off-by: Sasha Levin +--- + drivers/clk/sifive/sifive-prci.c | 8 -------- + 1 file changed, 8 deletions(-) + +diff --git a/drivers/clk/sifive/sifive-prci.c b/drivers/clk/sifive/sifive-prci.c +index 25b8e1a80ddce..b32a59fe55e74 100644 +--- a/drivers/clk/sifive/sifive-prci.c ++++ b/drivers/clk/sifive/sifive-prci.c +@@ -4,7 +4,6 @@ + * Copyright (C) 2020 Zong Li + */ + +-#include + #include + #include + #include +@@ -537,13 +536,6 @@ static int __prci_register_clocks(struct device *dev, struct __prci_data *pd, + return r; + } + +- r = clk_hw_register_clkdev(&pic->hw, pic->name, dev_name(dev)); +- if (r) { +- dev_warn(dev, "Failed to register clkdev for %s: %d\n", +- init.name, r); +- return r; +- } +- + pd->hw_clks.hws[i] = &pic->hw; + } + +-- +2.43.0 + diff --git a/queue-6.9/cxl-region-fix-memregion-leaks-in-devm_cxl_add_regio.patch b/queue-6.9/cxl-region-fix-memregion-leaks-in-devm_cxl_add_regio.patch new file mode 100644 index 00000000000..1a1eaba12bd --- /dev/null +++ b/queue-6.9/cxl-region-fix-memregion-leaks-in-devm_cxl_add_regio.patch @@ -0,0 +1,61 @@ +From db989e1404d5ddc3d03cdcfdc3346a164c275b23 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 May 2024 13:34:21 +0800 +Subject: cxl/region: Fix memregion leaks in devm_cxl_add_region() + +From: Li Zhijian + +[ Upstream commit 49ba7b515c4c0719b866d16f068e62d16a8a3dd1 ] + +Move the mode verification to __create_region() before allocating the +memregion to avoid the memregion leaks. + +Fixes: 6e099264185d ("cxl/region: Add volatile region creation support") +Signed-off-by: Li Zhijian +Reviewed-by: Dan Williams +Link: https://lore.kernel.org/r/20240507053421.456439-1-lizhijian@fujitsu.com +Signed-off-by: Dave Jiang +Signed-off-by: Sasha Levin +--- + drivers/cxl/core/region.c | 18 +++++++++--------- + 1 file changed, 9 insertions(+), 9 deletions(-) + +diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c +index 812b2948b6c65..18b95149640b6 100644 +--- a/drivers/cxl/core/region.c ++++ b/drivers/cxl/core/region.c +@@ -2352,15 +2352,6 @@ static struct cxl_region *devm_cxl_add_region(struct cxl_root_decoder *cxlrd, + struct device *dev; + int rc; + +- switch (mode) { +- case CXL_DECODER_RAM: +- case CXL_DECODER_PMEM: +- break; +- default: +- dev_err(&cxlrd->cxlsd.cxld.dev, "unsupported mode %d\n", mode); +- return ERR_PTR(-EINVAL); +- } +- + cxlr = cxl_region_alloc(cxlrd, id); + if (IS_ERR(cxlr)) + return cxlr; +@@ -2415,6 +2406,15 @@ static struct cxl_region *__create_region(struct cxl_root_decoder *cxlrd, + { + int rc; + ++ switch (mode) { ++ case CXL_DECODER_RAM: ++ case CXL_DECODER_PMEM: ++ break; ++ default: ++ dev_err(&cxlrd->cxlsd.cxld.dev, "unsupported mode %d\n", mode); ++ return ERR_PTR(-EINVAL); ++ } ++ + rc = memregion_alloc(GFP_KERNEL); + if (rc < 0) + return ERR_PTR(rc); +-- +2.43.0 + diff --git a/queue-6.9/cxl-test-add-missing-vmalloc.h-for-tools-testing-cxl.patch b/queue-6.9/cxl-test-add-missing-vmalloc.h-for-tools-testing-cxl.patch new file mode 100644 index 00000000000..00189fd05d1 --- /dev/null +++ b/queue-6.9/cxl-test-add-missing-vmalloc.h-for-tools-testing-cxl.patch @@ -0,0 +1,55 @@ +From 2d72e7a1980eb0fc937449f56053483c4e3669fb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 28 May 2024 15:55:51 -0700 +Subject: cxl/test: Add missing vmalloc.h for tools/testing/cxl/test/mem.c +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Dave Jiang + +[ Upstream commit d55510527153d17a3af8cc2df69c04f95ae1350d ] + +tools/testing/cxl/test/mem.c uses vmalloc() and vfree() but does not +include linux/vmalloc.h. Kernel v6.10 made changes that causes the +currently included headers not depend on vmalloc.h and therefore +mem.c can no longer compile. Add linux/vmalloc.h to fix compile +issue. + + CC [M] tools/testing/cxl/test/mem.o +tools/testing/cxl/test/mem.c: In function ‘label_area_release’: +tools/testing/cxl/test/mem.c:1428:9: error: implicit declaration of function ‘vfree’; did you mean ‘kvfree’? [-Werror=implicit-function-declaration] + 1428 | vfree(lsa); + | ^~~~~ + | kvfree +tools/testing/cxl/test/mem.c: In function ‘cxl_mock_mem_probe’: +tools/testing/cxl/test/mem.c:1466:22: error: implicit declaration of function ‘vmalloc’; did you mean ‘kmalloc’? [-Werror=implicit-function-declaration] + 1466 | mdata->lsa = vmalloc(LSA_SIZE); + | ^~~~~~~ + | kmalloc + +Fixes: 7d3eb23c4ccf ("tools/testing/cxl: Introduce a mock memory device + driver") +Reviewed-by: Dan Williams +Reviewed-by: Alison Schofield +Link: https://lore.kernel.org/r/20240528225551.1025977-1-dave.jiang@intel.com +Signed-off-by: Dave Jiang +Signed-off-by: Sasha Levin +--- + tools/testing/cxl/test/mem.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/tools/testing/cxl/test/mem.c b/tools/testing/cxl/test/mem.c +index 35ee41e435ab3..0d0ca63de8629 100644 +--- a/tools/testing/cxl/test/mem.c ++++ b/tools/testing/cxl/test/mem.c +@@ -3,6 +3,7 @@ + + #include + #include ++#include + #include + #include + #include +-- +2.43.0 + diff --git a/queue-6.9/drm-bridge-panel-fix-runtime-warning-on-panel-bridge.patch b/queue-6.9/drm-bridge-panel-fix-runtime-warning-on-panel-bridge.patch new file mode 100644 index 00000000000..3c2cc8e7b4a --- /dev/null +++ b/queue-6.9/drm-bridge-panel-fix-runtime-warning-on-panel-bridge.patch @@ -0,0 +1,51 @@ +From f5dba82c2c124351f2faa058a44ecdf9d99233ed Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Jun 2024 11:27:39 +0100 +Subject: drm/bridge/panel: Fix runtime warning on panel bridge release + +From: Adam Miotk + +[ Upstream commit ce62600c4dbee8d43b02277669dd91785a9b81d9 ] + +Device managed panel bridge wrappers are created by calling to +drm_panel_bridge_add_typed() and registering a release handler for +clean-up when the device gets unbound. + +Since the memory for this bridge is also managed and linked to the panel +device, the release function should not try to free that memory. +Moreover, the call to devm_kfree() inside drm_panel_bridge_remove() will +fail in this case and emit a warning because the panel bridge resource +is no longer on the device resources list (it has been removed from +there before the call to release handlers). + +Fixes: 67022227ffb1 ("drm/bridge: Add a devm_ allocator for panel bridge.") +Signed-off-by: Adam Miotk +Signed-off-by: Maxime Ripard +Link: https://patchwork.freedesktop.org/patch/msgid/20240610102739.139852-1-adam.miotk@arm.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/bridge/panel.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c +index 7f41525f7a6e6..3d6e8f096a5d4 100644 +--- a/drivers/gpu/drm/bridge/panel.c ++++ b/drivers/gpu/drm/bridge/panel.c +@@ -358,9 +358,12 @@ EXPORT_SYMBOL(drm_panel_bridge_set_orientation); + + static void devm_drm_panel_bridge_release(struct device *dev, void *res) + { +- struct drm_bridge **bridge = res; ++ struct drm_bridge *bridge = *(struct drm_bridge **)res; + +- drm_panel_bridge_remove(*bridge); ++ if (!bridge) ++ return; ++ ++ drm_bridge_remove(bridge); + } + + /** +-- +2.43.0 + diff --git a/queue-6.9/drm-komeda-check-for-error-valued-pointer.patch b/queue-6.9/drm-komeda-check-for-error-valued-pointer.patch new file mode 100644 index 00000000000..322653c924b --- /dev/null +++ b/queue-6.9/drm-komeda-check-for-error-valued-pointer.patch @@ -0,0 +1,37 @@ +From 009ba652e353c69b1dc66fda69aa2c56f93dc1ae Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Jun 2024 11:20:56 +0100 +Subject: drm/komeda: check for error-valued pointer + +From: Amjad Ouled-Ameur + +[ Upstream commit b880018edd3a577e50366338194dee9b899947e0 ] + +komeda_pipeline_get_state() may return an error-valued pointer, thus +check the pointer for negative or null value before dereferencing. + +Fixes: 502932a03fce ("drm/komeda: Add the initial scaler support for CORE") +Signed-off-by: Amjad Ouled-Ameur +Signed-off-by: Maxime Ripard +Link: https://patchwork.freedesktop.org/patch/msgid/20240610102056.40406-1-amjad.ouled-ameur@arm.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c +index f3e744172673c..f4e76b46ca327 100644 +--- a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c ++++ b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c +@@ -259,7 +259,7 @@ komeda_component_get_avail_scaler(struct komeda_component *c, + u32 avail_scalers; + + pipe_st = komeda_pipeline_get_state(c->pipeline, state); +- if (!pipe_st) ++ if (IS_ERR_OR_NULL(pipe_st)) + return NULL; + + avail_scalers = (pipe_st->active_comps & KOMEDA_PIPELINE_SCALERS) ^ +-- +2.43.0 + diff --git a/queue-6.9/drm-nouveau-don-t-attempt-to-schedule-hpd_work-on-he.patch b/queue-6.9/drm-nouveau-don-t-attempt-to-schedule-hpd_work-on-he.patch new file mode 100644 index 00000000000..d1e260cb739 --- /dev/null +++ b/queue-6.9/drm-nouveau-don-t-attempt-to-schedule-hpd_work-on-he.patch @@ -0,0 +1,101 @@ +From aff76250e5eec42356554e824ff303c4fe910ff9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Jun 2024 15:09:32 -0700 +Subject: drm/nouveau: don't attempt to schedule hpd_work on headless cards + +From: Vasily Khoruzhick + +[ Upstream commit b96a225377b6602299a03d2ce3c289b68cd41bb7 ] + +If the card doesn't have display hardware, hpd_work and hpd_lock are +left uninitialized which causes BUG when attempting to schedule hpd_work +on runtime PM resume. + +Fix it by adding headless flag to DRM and skip any hpd if it's set. + +Fixes: ae1aadb1eb8d ("nouveau: don't fail driver load if no display hw present.") +Link: https://gitlab.freedesktop.org/drm/nouveau/-/issues/337 +Signed-off-by: Vasily Khoruzhick +Reviewed-by: Ben Skeggs +Signed-off-by: Danilo Krummrich +Link: https://patchwork.freedesktop.org/patch/msgid/20240607221032.25918-1-anarsoul@gmail.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/nouveau/dispnv04/disp.c | 2 +- + drivers/gpu/drm/nouveau/dispnv50/disp.c | 2 +- + drivers/gpu/drm/nouveau/nouveau_display.c | 6 +++++- + drivers/gpu/drm/nouveau/nouveau_drv.h | 1 + + 4 files changed, 8 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/nouveau/dispnv04/disp.c b/drivers/gpu/drm/nouveau/dispnv04/disp.c +index 13705c5f14973..4b7497a8755cd 100644 +--- a/drivers/gpu/drm/nouveau/dispnv04/disp.c ++++ b/drivers/gpu/drm/nouveau/dispnv04/disp.c +@@ -68,7 +68,7 @@ nv04_display_fini(struct drm_device *dev, bool runtime, bool suspend) + if (nv_two_heads(dev)) + NVWriteCRTC(dev, 1, NV_PCRTC_INTR_EN_0, 0); + +- if (!runtime) ++ if (!runtime && !drm->headless) + cancel_work_sync(&drm->hpd_work); + + if (!suspend) +diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c +index 0c3d88ad0b0ea..88151209033d5 100644 +--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c ++++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c +@@ -2680,7 +2680,7 @@ nv50_display_fini(struct drm_device *dev, bool runtime, bool suspend) + nv50_mstm_fini(nouveau_encoder(encoder)); + } + +- if (!runtime) ++ if (!runtime && !drm->headless) + cancel_work_sync(&drm->hpd_work); + } + +diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c +index f28f9a8574586..60c32244211d0 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_display.c ++++ b/drivers/gpu/drm/nouveau/nouveau_display.c +@@ -450,6 +450,9 @@ nouveau_display_hpd_resume(struct drm_device *dev) + { + struct nouveau_drm *drm = nouveau_drm(dev); + ++ if (drm->headless) ++ return; ++ + spin_lock_irq(&drm->hpd_lock); + drm->hpd_pending = ~0; + spin_unlock_irq(&drm->hpd_lock); +@@ -635,7 +638,7 @@ nouveau_display_fini(struct drm_device *dev, bool suspend, bool runtime) + } + drm_connector_list_iter_end(&conn_iter); + +- if (!runtime) ++ if (!runtime && !drm->headless) + cancel_work_sync(&drm->hpd_work); + + drm_kms_helper_poll_disable(dev); +@@ -729,6 +732,7 @@ nouveau_display_create(struct drm_device *dev) + /* no display hw */ + if (ret == -ENODEV) { + ret = 0; ++ drm->headless = true; + goto disp_create_err; + } + +diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h +index e239c6bf4afa4..25fca98a20bcd 100644 +--- a/drivers/gpu/drm/nouveau/nouveau_drv.h ++++ b/drivers/gpu/drm/nouveau/nouveau_drv.h +@@ -276,6 +276,7 @@ struct nouveau_drm { + /* modesetting */ + struct nvbios vbios; + struct nouveau_display *display; ++ bool headless; + struct work_struct hpd_work; + spinlock_t hpd_lock; + u32 hpd_pending; +-- +2.43.0 + diff --git a/queue-6.9/drm-panel-sitronix-st7789v-add-check-for-of_drm_get_.patch b/queue-6.9/drm-panel-sitronix-st7789v-add-check-for-of_drm_get_.patch new file mode 100644 index 00000000000..0c6240d0da6 --- /dev/null +++ b/queue-6.9/drm-panel-sitronix-st7789v-add-check-for-of_drm_get_.patch @@ -0,0 +1,43 @@ +From b348cfdab081896f35df7197ca74201dc9968f8d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 28 May 2024 11:08:32 +0800 +Subject: drm/panel: sitronix-st7789v: Add check for + of_drm_get_panel_orientation + +From: Chen Ni + +[ Upstream commit 629f2b4e05225e53125aaf7ff0b87d5d53897128 ] + +Add check for the return value of of_drm_get_panel_orientation() and +return the error if it fails in order to catch the error. + +Fixes: b27c0f6d208d ("drm/panel: sitronix-st7789v: add panel orientation support") +Signed-off-by: Chen Ni +Reviewed-by: Michael Riesch +Acked-by: Jessica Zhang +Link: https://lore.kernel.org/r/20240528030832.2529471-1-nichen@iscas.ac.cn +Signed-off-by: Neil Armstrong +Link: https://patchwork.freedesktop.org/patch/msgid/20240528030832.2529471-1-nichen@iscas.ac.cn +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/panel/panel-sitronix-st7789v.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/panel/panel-sitronix-st7789v.c b/drivers/gpu/drm/panel/panel-sitronix-st7789v.c +index e8f385b9c6182..28bfc48a91272 100644 +--- a/drivers/gpu/drm/panel/panel-sitronix-st7789v.c ++++ b/drivers/gpu/drm/panel/panel-sitronix-st7789v.c +@@ -643,7 +643,9 @@ static int st7789v_probe(struct spi_device *spi) + if (ret) + return dev_err_probe(dev, ret, "Failed to get backlight\n"); + +- of_drm_get_panel_orientation(spi->dev.of_node, &ctx->orientation); ++ ret = of_drm_get_panel_orientation(spi->dev.of_node, &ctx->orientation); ++ if (ret) ++ return dev_err_probe(&spi->dev, ret, "Failed to get orientation\n"); + + drm_panel_add(&ctx->panel); + +-- +2.43.0 + diff --git a/queue-6.9/drm-vmwgfx-3d-disabled-should-not-effect-stdu-memory.patch b/queue-6.9/drm-vmwgfx-3d-disabled-should-not-effect-stdu-memory.patch new file mode 100644 index 00000000000..fa3d85c5d6b --- /dev/null +++ b/queue-6.9/drm-vmwgfx-3d-disabled-should-not-effect-stdu-memory.patch @@ -0,0 +1,45 @@ +From 79a81cd5606e64b031b993fc6c50c6125d55e694 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 May 2024 13:47:18 -0500 +Subject: drm/vmwgfx: 3D disabled should not effect STDU memory limits + +From: Ian Forbes + +[ Upstream commit fb5e19d2dd03eb995ccd468d599b2337f7f66555 ] + +This limit became a hard cap starting with the change referenced below. +Surface creation on the device will fail if the requested size is larger +than this limit so altering the value arbitrarily will expose modes that +are too large for the device's hard limits. + +Fixes: 7ebb47c9f9ab ("drm/vmwgfx: Read new register for GB memory when available") + +Signed-off-by: Ian Forbes +Signed-off-by: Zack Rusin +Link: https://patchwork.freedesktop.org/patch/msgid/20240521184720.767-3-ian.forbes@broadcom.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 7 ------- + 1 file changed, 7 deletions(-) + +diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +index 58fb40c93100a..bea576434e475 100644 +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +@@ -956,13 +956,6 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id) + vmw_read(dev_priv, + SVGA_REG_SUGGESTED_GBOBJECT_MEM_SIZE_KB); + +- /* +- * Workaround for low memory 2D VMs to compensate for the +- * allocation taken by fbdev +- */ +- if (!(dev_priv->capabilities & SVGA_CAP_3D)) +- mem_size *= 3; +- + dev_priv->max_mob_pages = mem_size * 1024 / PAGE_SIZE; + dev_priv->max_primary_mem = + vmw_read(dev_priv, SVGA_REG_MAX_PRIMARY_MEM); +-- +2.43.0 + diff --git a/queue-6.9/drm-vmwgfx-don-t-memcmp-equivalent-pointers.patch b/queue-6.9/drm-vmwgfx-don-t-memcmp-equivalent-pointers.patch new file mode 100644 index 00000000000..cb054134df0 --- /dev/null +++ b/queue-6.9/drm-vmwgfx-don-t-memcmp-equivalent-pointers.patch @@ -0,0 +1,38 @@ +From f02ae7e74969f25ae50832286d8d31c823a5881c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 28 Mar 2024 14:07:16 -0500 +Subject: drm/vmwgfx: Don't memcmp equivalent pointers + +From: Ian Forbes + +[ Upstream commit 5703fc058efdafcdd6b70776ee562478f0753acb ] + +These pointers are frequently the same and memcmp does not compare the +pointers before comparing their contents so this was wasting cycles +comparing 16 KiB of memory which will always be equal. + +Fixes: bb6780aa5a1d ("drm/vmwgfx: Diff cursors when using cmds") +Signed-off-by: Ian Forbes +Signed-off-by: Zack Rusin +Link: https://patchwork.freedesktop.org/patch/msgid/20240328190716.27367-1-ian.forbes@broadcom.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +index 42fcf4698aba9..11755d143e657 100644 +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +@@ -216,7 +216,7 @@ static bool vmw_du_cursor_plane_has_changed(struct vmw_plane_state *old_vps, + new_image = vmw_du_cursor_plane_acquire_image(new_vps); + + changed = false; +- if (old_image && new_image) ++ if (old_image && new_image && old_image != new_image) + changed = memcmp(old_image, new_image, size) != 0; + + return changed; +-- +2.43.0 + diff --git a/queue-6.9/drm-vmwgfx-filter-modes-which-exceed-graphics-memory.patch b/queue-6.9/drm-vmwgfx-filter-modes-which-exceed-graphics-memory.patch new file mode 100644 index 00000000000..fdb5fc02fd3 --- /dev/null +++ b/queue-6.9/drm-vmwgfx-filter-modes-which-exceed-graphics-memory.patch @@ -0,0 +1,106 @@ +From 8810c9a327eb795c4e832528fcc23ad6286163c5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 May 2024 13:47:17 -0500 +Subject: drm/vmwgfx: Filter modes which exceed graphics memory + +From: Ian Forbes + +[ Upstream commit 426826933109093503e7ef15d49348fc5ab505fe ] + +SVGA requires individual surfaces to fit within graphics memory +(max_mob_pages) which means that modes with a final buffer size that would +exceed graphics memory must be pruned otherwise creation will fail. + +Additionally llvmpipe requires its buffer height and width to be a multiple +of its tile size which is 64. As a result we have to anticipate that +llvmpipe will round up the mode size passed to it by the compositor when +it creates buffers and filter modes where this rounding exceeds graphics +memory. + +This fixes an issue where VMs with low graphics memory (< 64MiB) configured +with high resolution mode boot to a black screen because surface creation +fails. + +Fixes: d947d1b71deb ("drm/vmwgfx: Add and connect connector helper function") +Signed-off-by: Ian Forbes +Signed-off-by: Zack Rusin +Link: https://patchwork.freedesktop.org/patch/msgid/20240521184720.767-2-ian.forbes@broadcom.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | 45 ++++++++++++++++++++++++++-- + 1 file changed, 43 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c +index 3c8414a13dbad..dbc44ecbd1f4a 100644 +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c +@@ -41,7 +41,14 @@ + #define vmw_connector_to_stdu(x) \ + container_of(x, struct vmw_screen_target_display_unit, base.connector) + +- ++/* ++ * Some renderers such as llvmpipe will align the width and height of their ++ * buffers to match their tile size. We need to keep this in mind when exposing ++ * modes to userspace so that this possible over-allocation will not exceed ++ * graphics memory. 64x64 pixels seems to be a reasonable upper bound for the ++ * tile size of current renderers. ++ */ ++#define GPU_TILE_SIZE 64 + + enum stdu_content_type { + SAME_AS_DISPLAY = 0, +@@ -830,7 +837,41 @@ static void vmw_stdu_connector_destroy(struct drm_connector *connector) + vmw_stdu_destroy(vmw_connector_to_stdu(connector)); + } + ++static enum drm_mode_status ++vmw_stdu_connector_mode_valid(struct drm_connector *connector, ++ struct drm_display_mode *mode) ++{ ++ enum drm_mode_status ret; ++ struct drm_device *dev = connector->dev; ++ struct vmw_private *dev_priv = vmw_priv(dev); ++ u64 assumed_cpp = dev_priv->assume_16bpp ? 2 : 4; ++ /* Align width and height to account for GPU tile over-alignment */ ++ u64 required_mem = ALIGN(mode->hdisplay, GPU_TILE_SIZE) * ++ ALIGN(mode->vdisplay, GPU_TILE_SIZE) * ++ assumed_cpp; ++ required_mem = ALIGN(required_mem, PAGE_SIZE); ++ ++ ret = drm_mode_validate_size(mode, dev_priv->stdu_max_width, ++ dev_priv->stdu_max_height); ++ if (ret != MODE_OK) ++ return ret; + ++ ret = drm_mode_validate_size(mode, dev_priv->texture_max_width, ++ dev_priv->texture_max_height); ++ if (ret != MODE_OK) ++ return ret; ++ ++ if (required_mem > dev_priv->max_primary_mem) ++ return MODE_MEM; ++ ++ if (required_mem > dev_priv->max_mob_pages * PAGE_SIZE) ++ return MODE_MEM; ++ ++ if (required_mem > dev_priv->max_mob_size) ++ return MODE_MEM; ++ ++ return MODE_OK; ++} + + static const struct drm_connector_funcs vmw_stdu_connector_funcs = { + .dpms = vmw_du_connector_dpms, +@@ -846,7 +887,7 @@ static const struct drm_connector_funcs vmw_stdu_connector_funcs = { + static const struct + drm_connector_helper_funcs vmw_stdu_connector_helper_funcs = { + .get_modes = vmw_connector_get_modes, +- .mode_valid = vmw_connector_mode_valid ++ .mode_valid = vmw_stdu_connector_mode_valid + }; + + +-- +2.43.0 + diff --git a/queue-6.9/drm-vmwgfx-remove-stdu-logic-from-generic-mode_valid.patch b/queue-6.9/drm-vmwgfx-remove-stdu-logic-from-generic-mode_valid.patch new file mode 100644 index 00000000000..57602380d9c --- /dev/null +++ b/queue-6.9/drm-vmwgfx-remove-stdu-logic-from-generic-mode_valid.patch @@ -0,0 +1,93 @@ +From d6545549caeb2bc2731f7e81b44d714a45d8ae10 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 May 2024 13:47:19 -0500 +Subject: drm/vmwgfx: Remove STDU logic from generic mode_valid function + +From: Ian Forbes + +[ Upstream commit dde1de06bd7248fd83c4ce5cf0dbe9e4e95bbb91 ] + +STDU has its own mode_valid function now so this logic can be removed from +the generic version. + +Fixes: 935f795045a6 ("drm/vmwgfx: Refactor drm connector probing for display modes") + +Signed-off-by: Ian Forbes +Signed-off-by: Zack Rusin +Link: https://patchwork.freedesktop.org/patch/msgid/20240521184720.767-4-ian.forbes@broadcom.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 3 --- + drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 26 +++++++++----------------- + 2 files changed, 9 insertions(+), 20 deletions(-) + +diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +index b019a1a1787af..c1430e55474cb 100644 +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +@@ -1066,9 +1066,6 @@ void vmw_kms_cursor_snoop(struct vmw_surface *srf, + int vmw_kms_write_svga(struct vmw_private *vmw_priv, + unsigned width, unsigned height, unsigned pitch, + unsigned bpp, unsigned depth); +-bool vmw_kms_validate_mode_vram(struct vmw_private *dev_priv, +- uint32_t pitch, +- uint32_t height); + int vmw_kms_present(struct vmw_private *dev_priv, + struct drm_file *file_priv, + struct vmw_framebuffer *vfb, +diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +index 84ae4e10a2ebe..42fcf4698aba9 100644 +--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c ++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +@@ -2157,13 +2157,12 @@ int vmw_kms_write_svga(struct vmw_private *vmw_priv, + return 0; + } + ++static + bool vmw_kms_validate_mode_vram(struct vmw_private *dev_priv, +- uint32_t pitch, +- uint32_t height) ++ u64 pitch, ++ u64 height) + { +- return ((u64) pitch * (u64) height) < (u64) +- ((dev_priv->active_display_unit == vmw_du_screen_target) ? +- dev_priv->max_primary_mem : dev_priv->vram_size); ++ return (pitch * height) < (u64)dev_priv->vram_size; + } + + /** +@@ -2859,25 +2858,18 @@ int vmw_du_helper_plane_update(struct vmw_du_update_plane *update) + enum drm_mode_status vmw_connector_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) + { ++ enum drm_mode_status ret; + struct drm_device *dev = connector->dev; + struct vmw_private *dev_priv = vmw_priv(dev); +- u32 max_width = dev_priv->texture_max_width; +- u32 max_height = dev_priv->texture_max_height; + u32 assumed_cpp = 4; + + if (dev_priv->assume_16bpp) + assumed_cpp = 2; + +- if (dev_priv->active_display_unit == vmw_du_screen_target) { +- max_width = min(dev_priv->stdu_max_width, max_width); +- max_height = min(dev_priv->stdu_max_height, max_height); +- } +- +- if (max_width < mode->hdisplay) +- return MODE_BAD_HVALUE; +- +- if (max_height < mode->vdisplay) +- return MODE_BAD_VVALUE; ++ ret = drm_mode_validate_size(mode, dev_priv->texture_max_width, ++ dev_priv->texture_max_height); ++ if (ret != MODE_OK) ++ return ret; + + if (!vmw_kms_validate_mode_vram(dev_priv, + mode->hdisplay * assumed_cpp, +-- +2.43.0 + diff --git a/queue-6.9/drm-xe-flush-engine-buffers-before-signalling-user-f.patch b/queue-6.9/drm-xe-flush-engine-buffers-before-signalling-user-f.patch new file mode 100644 index 00000000000..e2254a508ca --- /dev/null +++ b/queue-6.9/drm-xe-flush-engine-buffers-before-signalling-user-f.patch @@ -0,0 +1,82 @@ +From 543ffae6440f5952b82ac44e72e76d50ef98e0e6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Jun 2024 09:29:48 +0200 +Subject: drm/xe: flush engine buffers before signalling user fence on all + engines +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Andrzej Hajda + +[ Upstream commit b5e3a9b83f352a737b77a01734a6661d1130ed49 ] + +Tests show that user fence signalling requires kind of write barrier, +otherwise not all writes performed by the workload will be available +to userspace. It is already done for render and compute, we need it +also for the rest: video, gsc, copy. + +Fixes: dd08ebf6c352 ("drm/xe: Introduce a new DRM driver for Intel GPUs") +Signed-off-by: Andrzej Hajda +Reviewed-by: Thomas Hellström +Signed-off-by: Matthew Brost +Link: https://patchwork.freedesktop.org/patch/msgid/20240605-fix_user_fence_posted-v3-2-06e7932f784a@intel.com +(cherry picked from commit 3ad7d18c5dad75ed38098c7cc3bc9594b4701399) +Signed-off-by: Thomas Hellström +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_ring_ops.c | 18 ++++++++++++++++-- + 1 file changed, 16 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/xe/xe_ring_ops.c b/drivers/gpu/drm/xe/xe_ring_ops.c +index 5b2b37b598130..820c8d73c464f 100644 +--- a/drivers/gpu/drm/xe/xe_ring_ops.c ++++ b/drivers/gpu/drm/xe/xe_ring_ops.c +@@ -79,6 +79,16 @@ static int emit_store_imm_ggtt(u32 addr, u32 value, u32 *dw, int i) + return i; + } + ++static int emit_flush_dw(u32 *dw, int i) ++{ ++ dw[i++] = MI_FLUSH_DW | MI_FLUSH_IMM_DW; ++ dw[i++] = 0; ++ dw[i++] = 0; ++ dw[i++] = 0; ++ ++ return i; ++} ++ + static int emit_flush_imm_ggtt(u32 addr, u32 value, bool invalidate_tlb, + u32 *dw, int i) + { +@@ -233,10 +243,12 @@ static void __emit_job_gen12_simple(struct xe_sched_job *job, struct xe_lrc *lrc + + i = emit_bb_start(batch_addr, ppgtt_flag, dw, i); + +- if (job->user_fence.used) ++ if (job->user_fence.used) { ++ i = emit_flush_dw(dw, i); + i = emit_store_imm_ppgtt_posted(job->user_fence.addr, + job->user_fence.value, + dw, i); ++ } + + i = emit_flush_imm_ggtt(xe_lrc_seqno_ggtt_addr(lrc), seqno, false, dw, i); + +@@ -292,10 +304,12 @@ static void __emit_job_gen12_video(struct xe_sched_job *job, struct xe_lrc *lrc, + + i = emit_bb_start(batch_addr, ppgtt_flag, dw, i); + +- if (job->user_fence.used) ++ if (job->user_fence.used) { ++ i = emit_flush_dw(dw, i); + i = emit_store_imm_ppgtt_posted(job->user_fence.addr, + job->user_fence.value, + dw, i); ++ } + + i = emit_flush_imm_ggtt(xe_lrc_seqno_ggtt_addr(lrc), seqno, false, dw, i); + +-- +2.43.0 + diff --git a/queue-6.9/drm-xe-move-disable_c6-call.patch b/queue-6.9/drm-xe-move-disable_c6-call.patch new file mode 100644 index 00000000000..efdf023bafb --- /dev/null +++ b/queue-6.9/drm-xe-move-disable_c6-call.patch @@ -0,0 +1,73 @@ +From b93b7b3401964fb88d3b97b5fd9899a870aef3e6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Jun 2024 15:38:42 +0530 +Subject: drm/xe: move disable_c6 call +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Riana Tauro + +[ Upstream commit 2470b141bfae2b9695b5b6823e3b978b22d33dde ] + +disable c6 called in guc_pc_fini_hw is unreachable. + +GuC PC init returns earlier if skip_guc_pc is true and never +registers the finish call thus making disable_c6 unreachable. + +move this call to gt idle. + +v2: rebase +v3: add fixes tag (Himal) + +Fixes: 975e4a3795d4 ("drm/xe: Manually setup C6 when skip_guc_pc is set") +Signed-off-by: Riana Tauro +Reviewed-by: Rodrigo Vivi +Link: https://patchwork.freedesktop.org/patch/msgid/20240606100842.956072-3-riana.tauro@intel.com +Signed-off-by: Rodrigo Vivi +(cherry picked from commit 6800e63cf97bae62bca56d8e691544540d945f53) +Signed-off-by: Thomas Hellström +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_gt_idle.c | 7 +++++++ + drivers/gpu/drm/xe/xe_guc_pc.c | 6 ------ + 2 files changed, 7 insertions(+), 6 deletions(-) + +diff --git a/drivers/gpu/drm/xe/xe_gt_idle.c b/drivers/gpu/drm/xe/xe_gt_idle.c +index 1521b3d9933c7..e7a39ad7adba0 100644 +--- a/drivers/gpu/drm/xe/xe_gt_idle.c ++++ b/drivers/gpu/drm/xe/xe_gt_idle.c +@@ -126,6 +126,13 @@ static const struct attribute *gt_idle_attrs[] = { + static void gt_idle_sysfs_fini(struct drm_device *drm, void *arg) + { + struct kobject *kobj = arg; ++ struct xe_gt *gt = kobj_to_gt(kobj->parent); ++ ++ if (gt_to_xe(gt)->info.skip_guc_pc) { ++ XE_WARN_ON(xe_force_wake_get(gt_to_fw(gt), XE_FW_GT)); ++ xe_gt_idle_disable_c6(gt); ++ xe_force_wake_put(gt_to_fw(gt), XE_FW_GT); ++ } + + sysfs_remove_files(kobj, gt_idle_attrs); + kobject_put(kobj); +diff --git a/drivers/gpu/drm/xe/xe_guc_pc.c b/drivers/gpu/drm/xe/xe_guc_pc.c +index f4b031b8d9deb..dd9d65f923da7 100644 +--- a/drivers/gpu/drm/xe/xe_guc_pc.c ++++ b/drivers/gpu/drm/xe/xe_guc_pc.c +@@ -920,12 +920,6 @@ int xe_guc_pc_stop(struct xe_guc_pc *pc) + static void xe_guc_pc_fini(struct drm_device *drm, void *arg) + { + struct xe_guc_pc *pc = arg; +- struct xe_device *xe = pc_to_xe(pc); +- +- if (xe->info.skip_guc_pc) { +- xe_gt_idle_disable_c6(pc_to_gt(pc)); +- return; +- } + + xe_force_wake_get(gt_to_fw(pc_to_gt(pc)), XE_FORCEWAKE_ALL); + XE_WARN_ON(xe_guc_pc_gucrc_disable(pc)); +-- +2.43.0 + diff --git a/queue-6.9/drm-xe-remove-mem_access-from-guc_pc-calls.patch b/queue-6.9/drm-xe-remove-mem_access-from-guc_pc-calls.patch new file mode 100644 index 00000000000..67e05371f13 --- /dev/null +++ b/queue-6.9/drm-xe-remove-mem_access-from-guc_pc-calls.patch @@ -0,0 +1,282 @@ +From 7f93a42fe8688ccb9c6c66c49980a2b4c60be8be Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 22 Feb 2024 11:39:29 -0500 +Subject: drm/xe: Remove mem_access from guc_pc calls + +From: Rodrigo Vivi + +[ Upstream commit 1e941c9881ec20f6d0173bcd344a605bb89cb121 ] + +We are now protected by init, sysfs, or removal and don't +need these mem_access protections around GuC_PC anymore. + +Reviewed-by: Matthew Auld +Signed-off-by: Rodrigo Vivi +Link: https://patchwork.freedesktop.org/patch/msgid/20240222163937.138342-6-rodrigo.vivi@intel.com +Stable-dep-of: 2470b141bfae ("drm/xe: move disable_c6 call") +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_guc_pc.c | 64 ++++++---------------------------- + 1 file changed, 10 insertions(+), 54 deletions(-) + +diff --git a/drivers/gpu/drm/xe/xe_guc_pc.c b/drivers/gpu/drm/xe/xe_guc_pc.c +index 2839d685631bc..f4b031b8d9deb 100644 +--- a/drivers/gpu/drm/xe/xe_guc_pc.c ++++ b/drivers/gpu/drm/xe/xe_guc_pc.c +@@ -381,8 +381,6 @@ u32 xe_guc_pc_get_act_freq(struct xe_guc_pc *pc) + struct xe_device *xe = gt_to_xe(gt); + u32 freq; + +- xe_device_mem_access_get(gt_to_xe(gt)); +- + /* When in RC6, actual frequency reported will be 0. */ + if (GRAPHICS_VERx100(xe) >= 1270) { + freq = xe_mmio_read32(gt, MTL_MIRROR_TARGET_WP1); +@@ -394,8 +392,6 @@ u32 xe_guc_pc_get_act_freq(struct xe_guc_pc *pc) + + freq = decode_freq(freq); + +- xe_device_mem_access_put(gt_to_xe(gt)); +- + return freq; + } + +@@ -412,14 +408,13 @@ int xe_guc_pc_get_cur_freq(struct xe_guc_pc *pc, u32 *freq) + struct xe_gt *gt = pc_to_gt(pc); + int ret; + +- xe_device_mem_access_get(gt_to_xe(gt)); + /* + * GuC SLPC plays with cur freq request when GuCRC is enabled + * Block RC6 for a more reliable read. + */ + ret = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL); + if (ret) +- goto out; ++ return ret; + + *freq = xe_mmio_read32(gt, RPNSWREQ); + +@@ -427,9 +422,7 @@ int xe_guc_pc_get_cur_freq(struct xe_guc_pc *pc, u32 *freq) + *freq = decode_freq(*freq); + + XE_WARN_ON(xe_force_wake_put(gt_to_fw(gt), XE_FORCEWAKE_ALL)); +-out: +- xe_device_mem_access_put(gt_to_xe(gt)); +- return ret; ++ return 0; + } + + /** +@@ -451,12 +444,7 @@ u32 xe_guc_pc_get_rp0_freq(struct xe_guc_pc *pc) + */ + u32 xe_guc_pc_get_rpe_freq(struct xe_guc_pc *pc) + { +- struct xe_gt *gt = pc_to_gt(pc); +- struct xe_device *xe = gt_to_xe(gt); +- +- xe_device_mem_access_get(xe); + pc_update_rp_values(pc); +- xe_device_mem_access_put(xe); + + return pc->rpe_freq; + } +@@ -485,7 +473,6 @@ int xe_guc_pc_get_min_freq(struct xe_guc_pc *pc, u32 *freq) + struct xe_gt *gt = pc_to_gt(pc); + int ret; + +- xe_device_mem_access_get(pc_to_xe(pc)); + mutex_lock(&pc->freq_lock); + if (!pc->freq_ready) { + /* Might be in the middle of a gt reset */ +@@ -511,7 +498,6 @@ int xe_guc_pc_get_min_freq(struct xe_guc_pc *pc, u32 *freq) + XE_WARN_ON(xe_force_wake_put(gt_to_fw(gt), XE_FORCEWAKE_ALL)); + out: + mutex_unlock(&pc->freq_lock); +- xe_device_mem_access_put(pc_to_xe(pc)); + return ret; + } + +@@ -528,7 +514,6 @@ int xe_guc_pc_set_min_freq(struct xe_guc_pc *pc, u32 freq) + { + int ret; + +- xe_device_mem_access_get(pc_to_xe(pc)); + mutex_lock(&pc->freq_lock); + if (!pc->freq_ready) { + /* Might be in the middle of a gt reset */ +@@ -544,8 +529,6 @@ int xe_guc_pc_set_min_freq(struct xe_guc_pc *pc, u32 freq) + + out: + mutex_unlock(&pc->freq_lock); +- xe_device_mem_access_put(pc_to_xe(pc)); +- + return ret; + } + +@@ -561,7 +544,6 @@ int xe_guc_pc_get_max_freq(struct xe_guc_pc *pc, u32 *freq) + { + int ret; + +- xe_device_mem_access_get(pc_to_xe(pc)); + mutex_lock(&pc->freq_lock); + if (!pc->freq_ready) { + /* Might be in the middle of a gt reset */ +@@ -577,7 +559,6 @@ int xe_guc_pc_get_max_freq(struct xe_guc_pc *pc, u32 *freq) + + out: + mutex_unlock(&pc->freq_lock); +- xe_device_mem_access_put(pc_to_xe(pc)); + return ret; + } + +@@ -594,7 +575,6 @@ int xe_guc_pc_set_max_freq(struct xe_guc_pc *pc, u32 freq) + { + int ret; + +- xe_device_mem_access_get(pc_to_xe(pc)); + mutex_lock(&pc->freq_lock); + if (!pc->freq_ready) { + /* Might be in the middle of a gt reset */ +@@ -610,7 +590,6 @@ int xe_guc_pc_set_max_freq(struct xe_guc_pc *pc, u32 freq) + + out: + mutex_unlock(&pc->freq_lock); +- xe_device_mem_access_put(pc_to_xe(pc)); + return ret; + } + +@@ -623,8 +602,6 @@ enum xe_gt_idle_state xe_guc_pc_c_status(struct xe_guc_pc *pc) + struct xe_gt *gt = pc_to_gt(pc); + u32 reg, gt_c_state; + +- xe_device_mem_access_get(gt_to_xe(gt)); +- + if (GRAPHICS_VERx100(gt_to_xe(gt)) >= 1270) { + reg = xe_mmio_read32(gt, MTL_MIRROR_TARGET_WP1); + gt_c_state = REG_FIELD_GET(MTL_CC_MASK, reg); +@@ -633,8 +610,6 @@ enum xe_gt_idle_state xe_guc_pc_c_status(struct xe_guc_pc *pc) + gt_c_state = REG_FIELD_GET(RCN_MASK, reg); + } + +- xe_device_mem_access_put(gt_to_xe(gt)); +- + switch (gt_c_state) { + case GT_C6: + return GT_IDLE_C6; +@@ -654,9 +629,7 @@ u64 xe_guc_pc_rc6_residency(struct xe_guc_pc *pc) + struct xe_gt *gt = pc_to_gt(pc); + u32 reg; + +- xe_device_mem_access_get(gt_to_xe(gt)); + reg = xe_mmio_read32(gt, GT_GFX_RC6); +- xe_device_mem_access_put(gt_to_xe(gt)); + + return reg; + } +@@ -670,9 +643,7 @@ u64 xe_guc_pc_mc6_residency(struct xe_guc_pc *pc) + struct xe_gt *gt = pc_to_gt(pc); + u64 reg; + +- xe_device_mem_access_get(gt_to_xe(gt)); + reg = xe_mmio_read32(gt, MTL_MEDIA_MC6); +- xe_device_mem_access_put(gt_to_xe(gt)); + + return reg; + } +@@ -801,23 +772,19 @@ int xe_guc_pc_gucrc_disable(struct xe_guc_pc *pc) + if (xe->info.skip_guc_pc) + return 0; + +- xe_device_mem_access_get(pc_to_xe(pc)); +- + ret = pc_action_setup_gucrc(pc, XE_GUCRC_HOST_CONTROL); + if (ret) +- goto out; ++ return ret; + + ret = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL); + if (ret) +- goto out; ++ return ret; + + xe_gt_idle_disable_c6(gt); + + XE_WARN_ON(xe_force_wake_put(gt_to_fw(gt), XE_FORCEWAKE_ALL)); + +-out: +- xe_device_mem_access_put(pc_to_xe(pc)); +- return ret; ++ return 0; + } + + static void pc_init_pcode_freq(struct xe_guc_pc *pc) +@@ -870,11 +837,9 @@ int xe_guc_pc_start(struct xe_guc_pc *pc) + + xe_gt_assert(gt, xe_device_uc_enabled(xe)); + +- xe_device_mem_access_get(pc_to_xe(pc)); +- + ret = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL); + if (ret) +- goto out_fail_force_wake; ++ return ret; + + if (xe->info.skip_guc_pc) { + if (xe->info.platform != XE_PVC) +@@ -914,8 +879,6 @@ int xe_guc_pc_start(struct xe_guc_pc *pc) + + out: + XE_WARN_ON(xe_force_wake_put(gt_to_fw(gt), XE_FORCEWAKE_ALL)); +-out_fail_force_wake: +- xe_device_mem_access_put(pc_to_xe(pc)); + return ret; + } + +@@ -928,12 +891,9 @@ int xe_guc_pc_stop(struct xe_guc_pc *pc) + struct xe_device *xe = pc_to_xe(pc); + int ret; + +- xe_device_mem_access_get(pc_to_xe(pc)); +- + if (xe->info.skip_guc_pc) { + xe_gt_idle_disable_c6(pc_to_gt(pc)); +- ret = 0; +- goto out; ++ return 0; + } + + mutex_lock(&pc->freq_lock); +@@ -942,16 +902,14 @@ int xe_guc_pc_stop(struct xe_guc_pc *pc) + + ret = pc_action_shutdown(pc); + if (ret) +- goto out; ++ return ret; + + if (wait_for_pc_state(pc, SLPC_GLOBAL_STATE_NOT_RUNNING)) { + drm_err(&pc_to_xe(pc)->drm, "GuC PC Shutdown failed\n"); +- ret = -EIO; ++ return -EIO; + } + +-out: +- xe_device_mem_access_put(pc_to_xe(pc)); +- return ret; ++ return 0; + } + + /** +@@ -965,9 +923,7 @@ static void xe_guc_pc_fini(struct drm_device *drm, void *arg) + struct xe_device *xe = pc_to_xe(pc); + + if (xe->info.skip_guc_pc) { +- xe_device_mem_access_get(xe); + xe_gt_idle_disable_c6(pc_to_gt(pc)); +- xe_device_mem_access_put(xe); + return; + } + +-- +2.43.0 + diff --git a/queue-6.9/drm-xe-xe_gt_idle-use-gt-forcewake-domain-assertion.patch b/queue-6.9/drm-xe-xe_gt_idle-use-gt-forcewake-domain-assertion.patch new file mode 100644 index 00000000000..c917de0f6e6 --- /dev/null +++ b/queue-6.9/drm-xe-xe_gt_idle-use-gt-forcewake-domain-assertion.patch @@ -0,0 +1,47 @@ +From 2781512ba87bcbe69efa796bb7e8ca18b79aa2aa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Jun 2024 15:38:41 +0530 +Subject: drm/xe/xe_gt_idle: use GT forcewake domain assertion +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Riana Tauro + +[ Upstream commit 7c877115da4196fa108dcfefd49f5a9b67b8d8ca ] + +The rc6 registers used in disable_c6 function belong +to the GT forcewake domain. Hence change the forcewake +assertion to check GT forcewake domain. + +v2: add fixes tag (Himal) + +Fixes: 975e4a3795d4 ("drm/xe: Manually setup C6 when skip_guc_pc is set") +Signed-off-by: Riana Tauro +Reviewed-by: Rodrigo Vivi +Reviewed-by: Himal Prasad Ghimiray +Link: https://patchwork.freedesktop.org/patch/msgid/20240606100842.956072-2-riana.tauro@intel.com +Signed-off-by: Rodrigo Vivi +(cherry picked from commit 21b708554648177a0078962c31629bce31ef5d83) +Signed-off-by: Thomas Hellström +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_gt_idle.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/xe/xe_gt_idle.c b/drivers/gpu/drm/xe/xe_gt_idle.c +index 9fcae65b64699..1521b3d9933c7 100644 +--- a/drivers/gpu/drm/xe/xe_gt_idle.c ++++ b/drivers/gpu/drm/xe/xe_gt_idle.c +@@ -184,7 +184,7 @@ void xe_gt_idle_enable_c6(struct xe_gt *gt) + void xe_gt_idle_disable_c6(struct xe_gt *gt) + { + xe_device_assert_mem_access(gt_to_xe(gt)); +- xe_force_wake_assert_held(gt_to_fw(gt), XE_FORCEWAKE_ALL); ++ xe_force_wake_assert_held(gt_to_fw(gt), XE_FW_GT); + + xe_mmio_write32(gt, PG_ENABLE, 0); + xe_mmio_write32(gt, RC_CONTROL, 0); +-- +2.43.0 + diff --git a/queue-6.9/geneve-fix-incorrect-inner-network-header-offset-whe.patch b/queue-6.9/geneve-fix-incorrect-inner-network-header-offset-whe.patch new file mode 100644 index 00000000000..7c4eb96e4ff --- /dev/null +++ b/queue-6.9/geneve-fix-incorrect-inner-network-header-offset-whe.patch @@ -0,0 +1,106 @@ +From 9b0024583ae8818730e452490a4f25aa8e4025d2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Jun 2024 23:32:48 +0300 +Subject: geneve: Fix incorrect inner network header offset when + innerprotoinherit is set + +From: Gal Pressman + +[ Upstream commit c6ae073f5903f6c6439d0ac855836a4da5c0a701 ] + +When innerprotoinherit is set, the tunneled packets do not have an inner +Ethernet header. +Change 'maclen' to not always assume the header length is ETH_HLEN, as +there might not be a MAC header. + +This resolves issues with drivers (e.g. mlx5, in +mlx5e_tx_tunnel_accel()) who rely on the skb inner network header offset +to be correct, and use it for TX offloads. + +Fixes: d8a6213d70ac ("geneve: fix header validation in geneve[6]_xmit_skb") +Signed-off-by: Gal Pressman +Signed-off-by: Tariq Toukan +Reviewed-by: Wojciech Drewek +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/geneve.c | 10 ++++++---- + include/net/ip_tunnels.h | 5 +++-- + 2 files changed, 9 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c +index 6c2835086b57e..76053d2c15958 100644 +--- a/drivers/net/geneve.c ++++ b/drivers/net/geneve.c +@@ -811,6 +811,7 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev, + struct geneve_dev *geneve, + const struct ip_tunnel_info *info) + { ++ bool inner_proto_inherit = geneve->cfg.inner_proto_inherit; + bool xnet = !net_eq(geneve->net, dev_net(geneve->dev)); + struct geneve_sock *gs4 = rcu_dereference(geneve->sock4); + const struct ip_tunnel_key *key = &info->key; +@@ -822,7 +823,7 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev, + __be16 sport; + int err; + +- if (!skb_vlan_inet_prepare(skb)) ++ if (!skb_vlan_inet_prepare(skb, inner_proto_inherit)) + return -EINVAL; + + if (!gs4) +@@ -903,7 +904,7 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev, + } + + err = geneve_build_skb(&rt->dst, skb, info, xnet, sizeof(struct iphdr), +- geneve->cfg.inner_proto_inherit); ++ inner_proto_inherit); + if (unlikely(err)) + return err; + +@@ -919,6 +920,7 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev, + struct geneve_dev *geneve, + const struct ip_tunnel_info *info) + { ++ bool inner_proto_inherit = geneve->cfg.inner_proto_inherit; + bool xnet = !net_eq(geneve->net, dev_net(geneve->dev)); + struct geneve_sock *gs6 = rcu_dereference(geneve->sock6); + const struct ip_tunnel_key *key = &info->key; +@@ -929,7 +931,7 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev, + __be16 sport; + int err; + +- if (!skb_vlan_inet_prepare(skb)) ++ if (!skb_vlan_inet_prepare(skb, inner_proto_inherit)) + return -EINVAL; + + if (!gs6) +@@ -991,7 +993,7 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev, + ttl = ttl ? : ip6_dst_hoplimit(dst); + } + err = geneve_build_skb(dst, skb, info, xnet, sizeof(struct ipv6hdr), +- geneve->cfg.inner_proto_inherit); ++ inner_proto_inherit); + if (unlikely(err)) + return err; + +diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h +index c286cc2e766ee..cc666da626517 100644 +--- a/include/net/ip_tunnels.h ++++ b/include/net/ip_tunnels.h +@@ -363,9 +363,10 @@ static inline bool pskb_inet_may_pull(struct sk_buff *skb) + + /* Variant of pskb_inet_may_pull(). + */ +-static inline bool skb_vlan_inet_prepare(struct sk_buff *skb) ++static inline bool skb_vlan_inet_prepare(struct sk_buff *skb, ++ bool inner_proto_inherit) + { +- int nhlen = 0, maclen = ETH_HLEN; ++ int nhlen = 0, maclen = inner_proto_inherit ? 0 : ETH_HLEN; + __be16 type = skb->protocol; + + /* Essentially this is skb_protocol(skb, true) +-- +2.43.0 + diff --git a/queue-6.9/gpio-tqmx86-fix-broken-irq_type_edge_both-interrupt-.patch b/queue-6.9/gpio-tqmx86-fix-broken-irq_type_edge_both-interrupt-.patch new file mode 100644 index 00000000000..80394ce6071 --- /dev/null +++ b/queue-6.9/gpio-tqmx86-fix-broken-irq_type_edge_both-interrupt-.patch @@ -0,0 +1,114 @@ +From 37f78d6eacaf67c287c3401c173758b3030dfdba Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 30 May 2024 12:20:02 +0200 +Subject: gpio: tqmx86: fix broken IRQ_TYPE_EDGE_BOTH interrupt type + +From: Matthias Schiffer + +[ Upstream commit 90dd7de4ef7ba584823dfbeba834c2919a4bb55b ] + +The TQMx86 GPIO controller only supports falling and rising edge +triggers, but not both. Fix this by implementing a software both-edge +mode that toggles the edge type after every interrupt. + +Fixes: b868db94a6a7 ("gpio: tqmx86: Add GPIO from for this IO controller") +Co-developed-by: Gregor Herburger +Signed-off-by: Gregor Herburger +Signed-off-by: Matthias Schiffer +Link: https://lore.kernel.org/r/515324f0491c4d44f4ef49f170354aca002d81ef.1717063994.git.matthias.schiffer@ew.tq-group.com +Signed-off-by: Bartosz Golaszewski +Signed-off-by: Sasha Levin +--- + drivers/gpio/gpio-tqmx86.c | 46 ++++++++++++++++++++++++++++++++++---- + 1 file changed, 42 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpio/gpio-tqmx86.c b/drivers/gpio/gpio-tqmx86.c +index 7e428c872a257..f2e7e8754d95d 100644 +--- a/drivers/gpio/gpio-tqmx86.c ++++ b/drivers/gpio/gpio-tqmx86.c +@@ -32,6 +32,10 @@ + #define TQMX86_GPII_NONE 0 + #define TQMX86_GPII_FALLING BIT(0) + #define TQMX86_GPII_RISING BIT(1) ++/* Stored in irq_type as a trigger type, but not actually valid as a register ++ * value, so the name doesn't use "GPII" ++ */ ++#define TQMX86_INT_BOTH (BIT(0) | BIT(1)) + #define TQMX86_GPII_MASK (BIT(0) | BIT(1)) + #define TQMX86_GPII_BITS 2 + /* Stored in irq_type with GPII bits */ +@@ -113,9 +117,15 @@ static void tqmx86_gpio_irq_config(struct tqmx86_gpio_data *gpio, int offset) + { + u8 type = TQMX86_GPII_NONE, gpiic; + +- if (gpio->irq_type[offset] & TQMX86_INT_UNMASKED) ++ if (gpio->irq_type[offset] & TQMX86_INT_UNMASKED) { + type = gpio->irq_type[offset] & TQMX86_GPII_MASK; + ++ if (type == TQMX86_INT_BOTH) ++ type = tqmx86_gpio_get(&gpio->chip, offset + TQMX86_NGPO) ++ ? TQMX86_GPII_FALLING ++ : TQMX86_GPII_RISING; ++ } ++ + gpiic = tqmx86_gpio_read(gpio, TQMX86_GPIIC); + gpiic &= ~(TQMX86_GPII_MASK << (offset * TQMX86_GPII_BITS)); + gpiic |= type << (offset * TQMX86_GPII_BITS); +@@ -169,7 +179,7 @@ static int tqmx86_gpio_irq_set_type(struct irq_data *data, unsigned int type) + new_type = TQMX86_GPII_FALLING; + break; + case IRQ_TYPE_EDGE_BOTH: +- new_type = TQMX86_GPII_FALLING | TQMX86_GPII_RISING; ++ new_type = TQMX86_INT_BOTH; + break; + default: + return -EINVAL; /* not supported */ +@@ -189,8 +199,8 @@ static void tqmx86_gpio_irq_handler(struct irq_desc *desc) + struct gpio_chip *chip = irq_desc_get_handler_data(desc); + struct tqmx86_gpio_data *gpio = gpiochip_get_data(chip); + struct irq_chip *irq_chip = irq_desc_get_chip(desc); +- unsigned long irq_bits; +- int i = 0; ++ unsigned long irq_bits, flags; ++ int i; + u8 irq_status; + + chained_irq_enter(irq_chip, desc); +@@ -199,6 +209,34 @@ static void tqmx86_gpio_irq_handler(struct irq_desc *desc) + tqmx86_gpio_write(gpio, irq_status, TQMX86_GPIIS); + + irq_bits = irq_status; ++ ++ raw_spin_lock_irqsave(&gpio->spinlock, flags); ++ for_each_set_bit(i, &irq_bits, TQMX86_NGPI) { ++ /* ++ * Edge-both triggers are implemented by flipping the edge ++ * trigger after each interrupt, as the controller only supports ++ * either rising or falling edge triggers, but not both. ++ * ++ * Internally, the TQMx86 GPIO controller has separate status ++ * registers for rising and falling edge interrupts. GPIIC ++ * configures which bits from which register are visible in the ++ * interrupt status register GPIIS and defines what triggers the ++ * parent IRQ line. Writing to GPIIS always clears both rising ++ * and falling interrupt flags internally, regardless of the ++ * currently configured trigger. ++ * ++ * In consequence, we can cleanly implement the edge-both ++ * trigger in software by first clearing the interrupt and then ++ * setting the new trigger based on the current GPIO input in ++ * tqmx86_gpio_irq_config() - even if an edge arrives between ++ * reading the input and setting the trigger, we will have a new ++ * interrupt pending. ++ */ ++ if ((gpio->irq_type[i] & TQMX86_GPII_MASK) == TQMX86_INT_BOTH) ++ tqmx86_gpio_irq_config(gpio, i); ++ } ++ raw_spin_unlock_irqrestore(&gpio->spinlock, flags); ++ + for_each_set_bit(i, &irq_bits, TQMX86_NGPI) + generic_handle_domain_irq(gpio->chip.irq.domain, + i + TQMX86_NGPO); +-- +2.43.0 + diff --git a/queue-6.9/gpio-tqmx86-fix-typo-in-kconfig-label.patch b/queue-6.9/gpio-tqmx86-fix-typo-in-kconfig-label.patch new file mode 100644 index 00000000000..7842ed6f9c2 --- /dev/null +++ b/queue-6.9/gpio-tqmx86-fix-typo-in-kconfig-label.patch @@ -0,0 +1,38 @@ +From 343cd357c3e74eac5d653d9374008b27042c4583 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 30 May 2024 12:19:59 +0200 +Subject: gpio: tqmx86: fix typo in Kconfig label + +From: Gregor Herburger + +[ Upstream commit 8c219e52ca4d9a67cd6a7074e91bf29b55edc075 ] + +Fix description for GPIO_TQMX86 from QTMX86 to TQMx86. + +Fixes: b868db94a6a7 ("gpio: tqmx86: Add GPIO from for this IO controller") +Signed-off-by: Gregor Herburger +Signed-off-by: Matthias Schiffer +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/e0e38c9944ad6d281d9a662a45d289b88edc808e.1717063994.git.matthias.schiffer@ew.tq-group.com +Signed-off-by: Bartosz Golaszewski +Signed-off-by: Sasha Levin +--- + drivers/gpio/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig +index b50d0b4708497..cbfcfefdb5da1 100644 +--- a/drivers/gpio/Kconfig ++++ b/drivers/gpio/Kconfig +@@ -1549,7 +1549,7 @@ config GPIO_TPS68470 + are "output only" GPIOs. + + config GPIO_TQMX86 +- tristate "TQ-Systems QTMX86 GPIO" ++ tristate "TQ-Systems TQMx86 GPIO" + depends on MFD_TQMX86 || COMPILE_TEST + depends on HAS_IOPORT_MAP + select GPIOLIB_IRQCHIP +-- +2.43.0 + diff --git a/queue-6.9/gpio-tqmx86-introduce-shadow-register-for-gpio-outpu.patch b/queue-6.9/gpio-tqmx86-introduce-shadow-register-for-gpio-outpu.patch new file mode 100644 index 00000000000..e20dbe63eb9 --- /dev/null +++ b/queue-6.9/gpio-tqmx86-introduce-shadow-register-for-gpio-outpu.patch @@ -0,0 +1,89 @@ +From 4d5a334da5e1f79b0de26cf59e30aff79ea93e7f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 30 May 2024 12:20:00 +0200 +Subject: gpio: tqmx86: introduce shadow register for GPIO output value + +From: Matthias Schiffer + +[ Upstream commit 9d6a811b522ba558bcb4ec01d12e72a0af8e9f6e ] + +The TQMx86 GPIO controller uses the same register address for input and +output data. Reading the register will always return current inputs +rather than the previously set outputs (regardless of the current +direction setting). Therefore, using a RMW pattern does not make sense +when setting output values. Instead, the previously set output register +value needs to be stored as a shadow register. + +As there is no reliable way to get the current output values from the +hardware, also initialize all channels to 0, to ensure that stored and +actual output values match. This should usually not have any effect in +practise, as the TQMx86 UEFI sets all outputs to 0 during boot. + +Also prepare for extension of the driver to more than 8 GPIOs by using +DECLARE_BITMAP. + +Fixes: b868db94a6a7 ("gpio: tqmx86: Add GPIO from for this IO controller") +Signed-off-by: Matthias Schiffer +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/d0555933becd45fa92a85675d26e4d59343ddc01.1717063994.git.matthias.schiffer@ew.tq-group.com +Signed-off-by: Bartosz Golaszewski +Signed-off-by: Sasha Levin +--- + drivers/gpio/gpio-tqmx86.c | 18 +++++++++++------- + 1 file changed, 11 insertions(+), 7 deletions(-) + +diff --git a/drivers/gpio/gpio-tqmx86.c b/drivers/gpio/gpio-tqmx86.c +index 3a28c1f273c39..b7e2dbbdc4ebe 100644 +--- a/drivers/gpio/gpio-tqmx86.c ++++ b/drivers/gpio/gpio-tqmx86.c +@@ -6,6 +6,7 @@ + * Vadim V.Vlasov + */ + ++#include + #include + #include + #include +@@ -38,6 +39,7 @@ struct tqmx86_gpio_data { + void __iomem *io_base; + int irq; + raw_spinlock_t spinlock; ++ DECLARE_BITMAP(output, TQMX86_NGPIO); + u8 irq_type[TQMX86_NGPI]; + }; + +@@ -64,15 +66,10 @@ static void tqmx86_gpio_set(struct gpio_chip *chip, unsigned int offset, + { + struct tqmx86_gpio_data *gpio = gpiochip_get_data(chip); + unsigned long flags; +- u8 val; + + raw_spin_lock_irqsave(&gpio->spinlock, flags); +- val = tqmx86_gpio_read(gpio, TQMX86_GPIOD); +- if (value) +- val |= BIT(offset); +- else +- val &= ~BIT(offset); +- tqmx86_gpio_write(gpio, val, TQMX86_GPIOD); ++ __assign_bit(offset, gpio->output, value); ++ tqmx86_gpio_write(gpio, bitmap_get_value8(gpio->output, 0), TQMX86_GPIOD); + raw_spin_unlock_irqrestore(&gpio->spinlock, flags); + } + +@@ -277,6 +274,13 @@ static int tqmx86_gpio_probe(struct platform_device *pdev) + + tqmx86_gpio_write(gpio, (u8)~TQMX86_DIR_INPUT_MASK, TQMX86_GPIODD); + ++ /* ++ * Reading the previous output state is not possible with TQMx86 hardware. ++ * Initialize all outputs to 0 to have a defined state that matches the ++ * shadow register. ++ */ ++ tqmx86_gpio_write(gpio, 0, TQMX86_GPIOD); ++ + chip = &gpio->chip; + chip->label = "gpio-tqmx86"; + chip->owner = THIS_MODULE; +-- +2.43.0 + diff --git a/queue-6.9/gpio-tqmx86-store-irq-trigger-type-and-unmask-status.patch b/queue-6.9/gpio-tqmx86-store-irq-trigger-type-and-unmask-status.patch new file mode 100644 index 00000000000..484f3af1ff3 --- /dev/null +++ b/queue-6.9/gpio-tqmx86-store-irq-trigger-type-and-unmask-status.patch @@ -0,0 +1,137 @@ +From fbbba8f0d1315f0d441b51cd22cb1876e5719fb7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 30 May 2024 12:20:01 +0200 +Subject: gpio: tqmx86: store IRQ trigger type and unmask status separately + +From: Matthias Schiffer + +[ Upstream commit 08af509efdf8dad08e972b48de0e2c2a7919ea8b ] + +irq_set_type() should not implicitly unmask the IRQ. + +All accesses to the interrupt configuration register are moved to a new +helper tqmx86_gpio_irq_config(). We also introduce the new rule that +accessing irq_type must happen while locked, which will become +significant for fixing EDGE_BOTH handling. + +Fixes: b868db94a6a7 ("gpio: tqmx86: Add GPIO from for this IO controller") +Signed-off-by: Matthias Schiffer +Link: https://lore.kernel.org/r/6aa4f207f77cb58ef64ffb947e91949b0f753ccd.1717063994.git.matthias.schiffer@ew.tq-group.com +Signed-off-by: Bartosz Golaszewski +Signed-off-by: Sasha Levin +--- + drivers/gpio/gpio-tqmx86.c | 48 ++++++++++++++++++++++---------------- + 1 file changed, 28 insertions(+), 20 deletions(-) + +diff --git a/drivers/gpio/gpio-tqmx86.c b/drivers/gpio/gpio-tqmx86.c +index b7e2dbbdc4ebe..7e428c872a257 100644 +--- a/drivers/gpio/gpio-tqmx86.c ++++ b/drivers/gpio/gpio-tqmx86.c +@@ -29,15 +29,19 @@ + #define TQMX86_GPIIC 3 /* GPI Interrupt Configuration Register */ + #define TQMX86_GPIIS 4 /* GPI Interrupt Status Register */ + ++#define TQMX86_GPII_NONE 0 + #define TQMX86_GPII_FALLING BIT(0) + #define TQMX86_GPII_RISING BIT(1) + #define TQMX86_GPII_MASK (BIT(0) | BIT(1)) + #define TQMX86_GPII_BITS 2 ++/* Stored in irq_type with GPII bits */ ++#define TQMX86_INT_UNMASKED BIT(2) + + struct tqmx86_gpio_data { + struct gpio_chip chip; + void __iomem *io_base; + int irq; ++ /* Lock must be held for accessing output and irq_type fields */ + raw_spinlock_t spinlock; + DECLARE_BITMAP(output, TQMX86_NGPIO); + u8 irq_type[TQMX86_NGPI]; +@@ -104,21 +108,32 @@ static int tqmx86_gpio_get_direction(struct gpio_chip *chip, + return GPIO_LINE_DIRECTION_OUT; + } + ++static void tqmx86_gpio_irq_config(struct tqmx86_gpio_data *gpio, int offset) ++ __must_hold(&gpio->spinlock) ++{ ++ u8 type = TQMX86_GPII_NONE, gpiic; ++ ++ if (gpio->irq_type[offset] & TQMX86_INT_UNMASKED) ++ type = gpio->irq_type[offset] & TQMX86_GPII_MASK; ++ ++ gpiic = tqmx86_gpio_read(gpio, TQMX86_GPIIC); ++ gpiic &= ~(TQMX86_GPII_MASK << (offset * TQMX86_GPII_BITS)); ++ gpiic |= type << (offset * TQMX86_GPII_BITS); ++ tqmx86_gpio_write(gpio, gpiic, TQMX86_GPIIC); ++} ++ + static void tqmx86_gpio_irq_mask(struct irq_data *data) + { + unsigned int offset = (data->hwirq - TQMX86_NGPO); + struct tqmx86_gpio_data *gpio = gpiochip_get_data( + irq_data_get_irq_chip_data(data)); + unsigned long flags; +- u8 gpiic, mask; +- +- mask = TQMX86_GPII_MASK << (offset * TQMX86_GPII_BITS); + + raw_spin_lock_irqsave(&gpio->spinlock, flags); +- gpiic = tqmx86_gpio_read(gpio, TQMX86_GPIIC); +- gpiic &= ~mask; +- tqmx86_gpio_write(gpio, gpiic, TQMX86_GPIIC); ++ gpio->irq_type[offset] &= ~TQMX86_INT_UNMASKED; ++ tqmx86_gpio_irq_config(gpio, offset); + raw_spin_unlock_irqrestore(&gpio->spinlock, flags); ++ + gpiochip_disable_irq(&gpio->chip, irqd_to_hwirq(data)); + } + +@@ -128,16 +143,12 @@ static void tqmx86_gpio_irq_unmask(struct irq_data *data) + struct tqmx86_gpio_data *gpio = gpiochip_get_data( + irq_data_get_irq_chip_data(data)); + unsigned long flags; +- u8 gpiic, mask; +- +- mask = TQMX86_GPII_MASK << (offset * TQMX86_GPII_BITS); + + gpiochip_enable_irq(&gpio->chip, irqd_to_hwirq(data)); ++ + raw_spin_lock_irqsave(&gpio->spinlock, flags); +- gpiic = tqmx86_gpio_read(gpio, TQMX86_GPIIC); +- gpiic &= ~mask; +- gpiic |= gpio->irq_type[offset] << (offset * TQMX86_GPII_BITS); +- tqmx86_gpio_write(gpio, gpiic, TQMX86_GPIIC); ++ gpio->irq_type[offset] |= TQMX86_INT_UNMASKED; ++ tqmx86_gpio_irq_config(gpio, offset); + raw_spin_unlock_irqrestore(&gpio->spinlock, flags); + } + +@@ -148,7 +159,7 @@ static int tqmx86_gpio_irq_set_type(struct irq_data *data, unsigned int type) + unsigned int offset = (data->hwirq - TQMX86_NGPO); + unsigned int edge_type = type & IRQF_TRIGGER_MASK; + unsigned long flags; +- u8 new_type, gpiic; ++ u8 new_type; + + switch (edge_type) { + case IRQ_TYPE_EDGE_RISING: +@@ -164,13 +175,10 @@ static int tqmx86_gpio_irq_set_type(struct irq_data *data, unsigned int type) + return -EINVAL; /* not supported */ + } + +- gpio->irq_type[offset] = new_type; +- + raw_spin_lock_irqsave(&gpio->spinlock, flags); +- gpiic = tqmx86_gpio_read(gpio, TQMX86_GPIIC); +- gpiic &= ~((TQMX86_GPII_MASK) << (offset * TQMX86_GPII_BITS)); +- gpiic |= new_type << (offset * TQMX86_GPII_BITS); +- tqmx86_gpio_write(gpio, gpiic, TQMX86_GPIIC); ++ gpio->irq_type[offset] &= ~TQMX86_GPII_MASK; ++ gpio->irq_type[offset] |= new_type; ++ tqmx86_gpio_irq_config(gpio, offset); + raw_spin_unlock_irqrestore(&gpio->spinlock, flags); + + return 0; +-- +2.43.0 + diff --git a/queue-6.9/gve-ignore-nonrelevant-gso-type-bits-when-processing.patch b/queue-6.9/gve-ignore-nonrelevant-gso-type-bits-when-processing.patch new file mode 100644 index 00000000000..83fd563bb5e --- /dev/null +++ b/queue-6.9/gve-ignore-nonrelevant-gso-type-bits-when-processing.patch @@ -0,0 +1,86 @@ +From 06433658bafdaf20048c577f4df26dbf822860e8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Jun 2024 15:57:18 -0700 +Subject: gve: ignore nonrelevant GSO type bits when processing TSO headers + +From: Joshua Washington + +[ Upstream commit 1b9f756344416e02b41439bf2324b26aa25e141c ] + +TSO currently fails when the skb's gso_type field has more than one bit +set. + +TSO packets can be passed from userspace using PF_PACKET, TUNTAP and a +few others, using virtio_net_hdr (e.g., PACKET_VNET_HDR). This includes +virtualization, such as QEMU, a real use-case. + +The gso_type and gso_size fields as passed from userspace in +virtio_net_hdr are not trusted blindly by the kernel. It adds gso_type +|= SKB_GSO_DODGY to force the packet to enter the software GSO stack +for verification. + +This issue might similarly come up when the CWR bit is set in the TCP +header for congestion control, causing the SKB_GSO_TCP_ECN gso_type bit +to be set. + +Fixes: a57e5de476be ("gve: DQO: Add TX path") +Signed-off-by: Joshua Washington +Reviewed-by: Praveen Kaligineedi +Reviewed-by: Harshitha Ramamurthy +Reviewed-by: Willem de Bruijn +Suggested-by: Eric Dumazet +Acked-by: Andrei Vagin + +v2 - Remove unnecessary comments, remove line break between fixes tag +and signoffs. + +v3 - Add back unrelated empty line removal. + +Link: https://lore.kernel.org/r/20240610225729.2985343-1-joshwash@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/google/gve/gve_tx_dqo.c | 20 +++++--------------- + 1 file changed, 5 insertions(+), 15 deletions(-) + +diff --git a/drivers/net/ethernet/google/gve/gve_tx_dqo.c b/drivers/net/ethernet/google/gve/gve_tx_dqo.c +index bc34b6cd3a3e5..917a79a47e19c 100644 +--- a/drivers/net/ethernet/google/gve/gve_tx_dqo.c ++++ b/drivers/net/ethernet/google/gve/gve_tx_dqo.c +@@ -555,28 +555,18 @@ static int gve_prep_tso(struct sk_buff *skb) + if (unlikely(skb_shinfo(skb)->gso_size < GVE_TX_MIN_TSO_MSS_DQO)) + return -1; + ++ if (!(skb_shinfo(skb)->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6))) ++ return -EINVAL; ++ + /* Needed because we will modify header. */ + err = skb_cow_head(skb, 0); + if (err < 0) + return err; + + tcp = tcp_hdr(skb); +- +- /* Remove payload length from checksum. */ + paylen = skb->len - skb_transport_offset(skb); +- +- switch (skb_shinfo(skb)->gso_type) { +- case SKB_GSO_TCPV4: +- case SKB_GSO_TCPV6: +- csum_replace_by_diff(&tcp->check, +- (__force __wsum)htonl(paylen)); +- +- /* Compute length of segmentation header. */ +- header_len = skb_tcp_all_headers(skb); +- break; +- default: +- return -EINVAL; +- } ++ csum_replace_by_diff(&tcp->check, (__force __wsum)htonl(paylen)); ++ header_len = skb_tcp_all_headers(skb); + + if (unlikely(header_len > GVE_TX_MAX_HDR_SIZE_DQO)) + return -EINVAL; +-- +2.43.0 + diff --git a/queue-6.9/hid-core-remove-unnecessary-warn_on-in-implement.patch b/queue-6.9/hid-core-remove-unnecessary-warn_on-in-implement.patch new file mode 100644 index 00000000000..6bfb8e196ff --- /dev/null +++ b/queue-6.9/hid-core-remove-unnecessary-warn_on-in-implement.patch @@ -0,0 +1,67 @@ +From 65475965076f09e4c94a8e5e54d77818c4cf1a51 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 May 2024 07:19:14 -0700 +Subject: HID: core: remove unnecessary WARN_ON() in implement() + +From: Nikita Zhandarovich + +[ Upstream commit 4aa2dcfbad538adf7becd0034a3754e1bd01b2b5 ] + +Syzkaller hit a warning [1] in a call to implement() when trying +to write a value into a field of smaller size in an output report. + +Since implement() already has a warn message printed out with the +help of hid_warn() and value in question gets trimmed with: + ... + value &= m; + ... +WARN_ON may be considered superfluous. Remove it to suppress future +syzkaller triggers. + +[1] +WARNING: CPU: 0 PID: 5084 at drivers/hid/hid-core.c:1451 implement drivers/hid/hid-core.c:1451 [inline] +WARNING: CPU: 0 PID: 5084 at drivers/hid/hid-core.c:1451 hid_output_report+0x548/0x760 drivers/hid/hid-core.c:1863 +Modules linked in: +CPU: 0 PID: 5084 Comm: syz-executor424 Not tainted 6.9.0-rc7-syzkaller-00183-gcf87f46fd34d #0 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 04/02/2024 +RIP: 0010:implement drivers/hid/hid-core.c:1451 [inline] +RIP: 0010:hid_output_report+0x548/0x760 drivers/hid/hid-core.c:1863 +... +Call Trace: + + __usbhid_submit_report drivers/hid/usbhid/hid-core.c:591 [inline] + usbhid_submit_report+0x43d/0x9e0 drivers/hid/usbhid/hid-core.c:636 + hiddev_ioctl+0x138b/0x1f00 drivers/hid/usbhid/hiddev.c:726 + vfs_ioctl fs/ioctl.c:51 [inline] + __do_sys_ioctl fs/ioctl.c:904 [inline] + __se_sys_ioctl+0xfc/0x170 fs/ioctl.c:890 + do_syscall_x64 arch/x86/entry/common.c:52 [inline] + do_syscall_64+0xf5/0x240 arch/x86/entry/common.c:83 + entry_SYSCALL_64_after_hwframe+0x77/0x7f +... + +Fixes: 95d1c8951e5b ("HID: simplify implement() a bit") +Reported-by: +Suggested-by: Alan Stern +Signed-off-by: Nikita Zhandarovich +Signed-off-by: Jiri Kosina +Signed-off-by: Sasha Levin +--- + drivers/hid/hid-core.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c +index de7a477d66656..751a73ae7de75 100644 +--- a/drivers/hid/hid-core.c ++++ b/drivers/hid/hid-core.c +@@ -1448,7 +1448,6 @@ static void implement(const struct hid_device *hid, u8 *report, + hid_warn(hid, + "%s() called with too large value %d (n: %d)! (%s)\n", + __func__, value, n, current->comm); +- WARN_ON(1); + value &= m; + } + } +-- +2.43.0 + diff --git a/queue-6.9/hid-logitech-dj-fix-memory-leak-in-logi_dj_recv_swit.patch b/queue-6.9/hid-logitech-dj-fix-memory-leak-in-logi_dj_recv_swit.patch new file mode 100644 index 00000000000..37bb5f4075c --- /dev/null +++ b/queue-6.9/hid-logitech-dj-fix-memory-leak-in-logi_dj_recv_swit.patch @@ -0,0 +1,41 @@ +From 3782b06f4771e2372b42dedcce7b21e7b03e8203 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 24 May 2024 15:05:39 +0200 +Subject: HID: logitech-dj: Fix memory leak in logi_dj_recv_switch_to_dj_mode() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: José Expósito + +[ Upstream commit ce3af2ee95170b7d9e15fff6e500d67deab1e7b3 ] + +Fix a memory leak on logi_dj_recv_send_report() error path. + +Fixes: 6f20d3261265 ("HID: logitech-dj: Fix error handling in logi_dj_recv_switch_to_dj_mode()") +Signed-off-by: José Expósito +Signed-off-by: Jiri Kosina +Signed-off-by: Sasha Levin +--- + drivers/hid/hid-logitech-dj.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c +index 3c3c497b6b911..37958edec55f5 100644 +--- a/drivers/hid/hid-logitech-dj.c ++++ b/drivers/hid/hid-logitech-dj.c +@@ -1284,8 +1284,10 @@ static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev, + */ + msleep(50); + +- if (retval) ++ if (retval) { ++ kfree(dj_report); + return retval; ++ } + } + + /* +-- +2.43.0 + diff --git a/queue-6.9/hid-nvidia-shield-add-missing-check-for-input_ff_cre.patch b/queue-6.9/hid-nvidia-shield-add-missing-check-for-input_ff_cre.patch new file mode 100644 index 00000000000..16b2ed530d4 --- /dev/null +++ b/queue-6.9/hid-nvidia-shield-add-missing-check-for-input_ff_cre.patch @@ -0,0 +1,39 @@ +From d598dc7abcfa90f5e09abae173da1613e97729c1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 May 2024 11:30:51 +0800 +Subject: HID: nvidia-shield: Add missing check for input_ff_create_memless + +From: Chen Ni + +[ Upstream commit 0a3f9f7fc59feb8a91a2793b8b60977895c72365 ] + +Add check for the return value of input_ff_create_memless() and return +the error if it fails in order to catch the error. + +Fixes: 09308562d4af ("HID: nvidia-shield: Initial driver implementation with Thunderstrike support") +Signed-off-by: Chen Ni +Reviewed-by: Rahul Rameshbabu +Signed-off-by: Jiri Kosina +Signed-off-by: Sasha Levin +--- + drivers/hid/hid-nvidia-shield.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/hid/hid-nvidia-shield.c b/drivers/hid/hid-nvidia-shield.c +index 58b15750dbb0a..ff9078ad19611 100644 +--- a/drivers/hid/hid-nvidia-shield.c ++++ b/drivers/hid/hid-nvidia-shield.c +@@ -283,7 +283,9 @@ static struct input_dev *shield_haptics_create( + return haptics; + + input_set_capability(haptics, EV_FF, FF_RUMBLE); +- input_ff_create_memless(haptics, NULL, play_effect); ++ ret = input_ff_create_memless(haptics, NULL, play_effect); ++ if (ret) ++ goto err; + + ret = input_register_device(haptics); + if (ret) +-- +2.43.0 + diff --git a/queue-6.9/io_uring-io-wq-avoid-garbage-value-of-match-in-io_wq.patch b/queue-6.9/io_uring-io-wq-avoid-garbage-value-of-match-in-io_wq.patch new file mode 100644 index 00000000000..9b7cf13ef70 --- /dev/null +++ b/queue-6.9/io_uring-io-wq-avoid-garbage-value-of-match-in-io_wq.patch @@ -0,0 +1,58 @@ +From 6db762446e024e0ea2815d08cc7cb78b78dbfc9c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Jun 2024 20:12:43 +0800 +Subject: io_uring/io-wq: avoid garbage value of 'match' in io_wq_enqueue() + +From: Su Hui + +[ Upstream commit 91215f70ea8541e9011c0b48f8b59b9e0ce6953b ] + +Clang static checker (scan-build) warning: +o_uring/io-wq.c:line 1051, column 3 +The expression is an uninitialized value. The computed value will +also be garbage. + +'match.nr_pending' is used in io_acct_cancel_pending_work(), but it is +not fully initialized. Change the order of assignment for 'match' to fix +this problem. + +Fixes: 42abc95f05bf ("io-wq: decouple work_list protection from the big wqe->lock") +Signed-off-by: Su Hui +Link: https://lore.kernel.org/r/20240604121242.2661244-1-suhui@nfschina.com +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + io_uring/io-wq.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/io_uring/io-wq.c b/io_uring/io-wq.c +index 4a07742349048..8a99aabcac2c3 100644 +--- a/io_uring/io-wq.c ++++ b/io_uring/io-wq.c +@@ -929,7 +929,11 @@ void io_wq_enqueue(struct io_wq *wq, struct io_wq_work *work) + { + struct io_wq_acct *acct = io_work_get_acct(wq, work); + unsigned long work_flags = work->flags; +- struct io_cb_cancel_data match; ++ struct io_cb_cancel_data match = { ++ .fn = io_wq_work_match_item, ++ .data = work, ++ .cancel_all = false, ++ }; + bool do_create; + + /* +@@ -967,10 +971,6 @@ void io_wq_enqueue(struct io_wq *wq, struct io_wq_work *work) + raw_spin_unlock(&wq->lock); + + /* fatal condition, failed to create the first worker */ +- match.fn = io_wq_work_match_item, +- match.data = work, +- match.cancel_all = false, +- + io_acct_cancel_pending_work(wq, acct, &match); + } + } +-- +2.43.0 + diff --git a/queue-6.9/io_uring-io-wq-use-set_bit-and-test_bit-at-worker-fl.patch b/queue-6.9/io_uring-io-wq-use-set_bit-and-test_bit-at-worker-fl.patch new file mode 100644 index 00000000000..6d8e5f258a6 --- /dev/null +++ b/queue-6.9/io_uring-io-wq-use-set_bit-and-test_bit-at-worker-fl.patch @@ -0,0 +1,209 @@ +From ed15d9ea67a9be3ca458ee642933ebb89ea4d197 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 May 2024 10:00:01 -0700 +Subject: io_uring/io-wq: Use set_bit() and test_bit() at worker->flags + +From: Breno Leitao + +[ Upstream commit 8a565304927fbd28c9f028c492b5c1714002cbab ] + +Utilize set_bit() and test_bit() on worker->flags within io_uring/io-wq +to address potential data races. + +The structure io_worker->flags may be accessed through various data +paths, leading to concurrency issues. When KCSAN is enabled, it reveals +data races occurring in io_worker_handle_work and +io_wq_activate_free_worker functions. + + BUG: KCSAN: data-race in io_worker_handle_work / io_wq_activate_free_worker + write to 0xffff8885c4246404 of 4 bytes by task 49071 on cpu 28: + io_worker_handle_work (io_uring/io-wq.c:434 io_uring/io-wq.c:569) + io_wq_worker (io_uring/io-wq.c:?) + + + read to 0xffff8885c4246404 of 4 bytes by task 49024 on cpu 5: + io_wq_activate_free_worker (io_uring/io-wq.c:? io_uring/io-wq.c:285) + io_wq_enqueue (io_uring/io-wq.c:947) + io_queue_iowq (io_uring/io_uring.c:524) + io_req_task_submit (io_uring/io_uring.c:1511) + io_handle_tw_list (io_uring/io_uring.c:1198) + + +Line numbers against commit 18daea77cca6 ("Merge tag 'for-linus' of +git://git.kernel.org/pub/scm/virt/kvm/kvm"). + +These races involve writes and reads to the same memory location by +different tasks running on different CPUs. To mitigate this, refactor +the code to use atomic operations such as set_bit(), test_bit(), and +clear_bit() instead of basic "and" and "or" operations. This ensures +thread-safe manipulation of worker flags. + +Also, move `create_index` to avoid holes in the structure. + +Signed-off-by: Breno Leitao +Link: https://lore.kernel.org/r/20240507170002.2269003-1-leitao@debian.org +Signed-off-by: Jens Axboe +Stable-dep-of: 91215f70ea85 ("io_uring/io-wq: avoid garbage value of 'match' in io_wq_enqueue()") +Signed-off-by: Sasha Levin +--- + io_uring/io-wq.c | 47 ++++++++++++++++++++++++----------------------- + 1 file changed, 24 insertions(+), 23 deletions(-) + +diff --git a/io_uring/io-wq.c b/io_uring/io-wq.c +index 318ed067dbf64..4a07742349048 100644 +--- a/io_uring/io-wq.c ++++ b/io_uring/io-wq.c +@@ -25,10 +25,10 @@ + #define WORKER_IDLE_TIMEOUT (5 * HZ) + + enum { +- IO_WORKER_F_UP = 1, /* up and active */ +- IO_WORKER_F_RUNNING = 2, /* account as running */ +- IO_WORKER_F_FREE = 4, /* worker on free list */ +- IO_WORKER_F_BOUND = 8, /* is doing bounded work */ ++ IO_WORKER_F_UP = 0, /* up and active */ ++ IO_WORKER_F_RUNNING = 1, /* account as running */ ++ IO_WORKER_F_FREE = 2, /* worker on free list */ ++ IO_WORKER_F_BOUND = 3, /* is doing bounded work */ + }; + + enum { +@@ -44,7 +44,8 @@ enum { + */ + struct io_worker { + refcount_t ref; +- unsigned flags; ++ int create_index; ++ unsigned long flags; + struct hlist_nulls_node nulls_node; + struct list_head all_list; + struct task_struct *task; +@@ -58,7 +59,6 @@ struct io_worker { + + unsigned long create_state; + struct callback_head create_work; +- int create_index; + + union { + struct rcu_head rcu; +@@ -165,7 +165,7 @@ static inline struct io_wq_acct *io_work_get_acct(struct io_wq *wq, + + static inline struct io_wq_acct *io_wq_get_acct(struct io_worker *worker) + { +- return io_get_acct(worker->wq, worker->flags & IO_WORKER_F_BOUND); ++ return io_get_acct(worker->wq, test_bit(IO_WORKER_F_BOUND, &worker->flags)); + } + + static void io_worker_ref_put(struct io_wq *wq) +@@ -225,7 +225,7 @@ static void io_worker_exit(struct io_worker *worker) + wait_for_completion(&worker->ref_done); + + raw_spin_lock(&wq->lock); +- if (worker->flags & IO_WORKER_F_FREE) ++ if (test_bit(IO_WORKER_F_FREE, &worker->flags)) + hlist_nulls_del_rcu(&worker->nulls_node); + list_del_rcu(&worker->all_list); + raw_spin_unlock(&wq->lock); +@@ -410,7 +410,7 @@ static void io_wq_dec_running(struct io_worker *worker) + struct io_wq_acct *acct = io_wq_get_acct(worker); + struct io_wq *wq = worker->wq; + +- if (!(worker->flags & IO_WORKER_F_UP)) ++ if (!test_bit(IO_WORKER_F_UP, &worker->flags)) + return; + + if (!atomic_dec_and_test(&acct->nr_running)) +@@ -430,8 +430,8 @@ static void io_wq_dec_running(struct io_worker *worker) + */ + static void __io_worker_busy(struct io_wq *wq, struct io_worker *worker) + { +- if (worker->flags & IO_WORKER_F_FREE) { +- worker->flags &= ~IO_WORKER_F_FREE; ++ if (test_bit(IO_WORKER_F_FREE, &worker->flags)) { ++ clear_bit(IO_WORKER_F_FREE, &worker->flags); + raw_spin_lock(&wq->lock); + hlist_nulls_del_init_rcu(&worker->nulls_node); + raw_spin_unlock(&wq->lock); +@@ -444,8 +444,8 @@ static void __io_worker_busy(struct io_wq *wq, struct io_worker *worker) + static void __io_worker_idle(struct io_wq *wq, struct io_worker *worker) + __must_hold(wq->lock) + { +- if (!(worker->flags & IO_WORKER_F_FREE)) { +- worker->flags |= IO_WORKER_F_FREE; ++ if (!test_bit(IO_WORKER_F_FREE, &worker->flags)) { ++ set_bit(IO_WORKER_F_FREE, &worker->flags); + hlist_nulls_add_head_rcu(&worker->nulls_node, &wq->free_list); + } + } +@@ -634,7 +634,8 @@ static int io_wq_worker(void *data) + bool exit_mask = false, last_timeout = false; + char buf[TASK_COMM_LEN]; + +- worker->flags |= (IO_WORKER_F_UP | IO_WORKER_F_RUNNING); ++ set_mask_bits(&worker->flags, 0, ++ BIT(IO_WORKER_F_UP) | BIT(IO_WORKER_F_RUNNING)); + + snprintf(buf, sizeof(buf), "iou-wrk-%d", wq->task->pid); + set_task_comm(current, buf); +@@ -698,11 +699,11 @@ void io_wq_worker_running(struct task_struct *tsk) + + if (!worker) + return; +- if (!(worker->flags & IO_WORKER_F_UP)) ++ if (!test_bit(IO_WORKER_F_UP, &worker->flags)) + return; +- if (worker->flags & IO_WORKER_F_RUNNING) ++ if (test_bit(IO_WORKER_F_RUNNING, &worker->flags)) + return; +- worker->flags |= IO_WORKER_F_RUNNING; ++ set_bit(IO_WORKER_F_RUNNING, &worker->flags); + io_wq_inc_running(worker); + } + +@@ -716,12 +717,12 @@ void io_wq_worker_sleeping(struct task_struct *tsk) + + if (!worker) + return; +- if (!(worker->flags & IO_WORKER_F_UP)) ++ if (!test_bit(IO_WORKER_F_UP, &worker->flags)) + return; +- if (!(worker->flags & IO_WORKER_F_RUNNING)) ++ if (!test_bit(IO_WORKER_F_RUNNING, &worker->flags)) + return; + +- worker->flags &= ~IO_WORKER_F_RUNNING; ++ clear_bit(IO_WORKER_F_RUNNING, &worker->flags); + io_wq_dec_running(worker); + } + +@@ -735,7 +736,7 @@ static void io_init_new_worker(struct io_wq *wq, struct io_worker *worker, + raw_spin_lock(&wq->lock); + hlist_nulls_add_head_rcu(&worker->nulls_node, &wq->free_list); + list_add_tail_rcu(&worker->all_list, &wq->all_list); +- worker->flags |= IO_WORKER_F_FREE; ++ set_bit(IO_WORKER_F_FREE, &worker->flags); + raw_spin_unlock(&wq->lock); + wake_up_new_task(tsk); + } +@@ -841,7 +842,7 @@ static bool create_io_worker(struct io_wq *wq, int index) + init_completion(&worker->ref_done); + + if (index == IO_WQ_ACCT_BOUND) +- worker->flags |= IO_WORKER_F_BOUND; ++ set_bit(IO_WORKER_F_BOUND, &worker->flags); + + tsk = create_io_thread(io_wq_worker, worker, NUMA_NO_NODE); + if (!IS_ERR(tsk)) { +@@ -927,8 +928,8 @@ static bool io_wq_work_match_item(struct io_wq_work *work, void *data) + void io_wq_enqueue(struct io_wq *wq, struct io_wq_work *work) + { + struct io_wq_acct *acct = io_work_get_acct(wq, work); ++ unsigned long work_flags = work->flags; + struct io_cb_cancel_data match; +- unsigned work_flags = work->flags; + bool do_create; + + /* +-- +2.43.0 + diff --git a/queue-6.9/iommu-amd-fix-sysfs-leak-in-iommu-init.patch b/queue-6.9/iommu-amd-fix-sysfs-leak-in-iommu-init.patch new file mode 100644 index 00000000000..c4276a754b1 --- /dev/null +++ b/queue-6.9/iommu-amd-fix-sysfs-leak-in-iommu-init.patch @@ -0,0 +1,47 @@ +From d80baabbe9fdf82bd878c4044cffd1bd8df0de8a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 May 2024 08:42:20 +0800 +Subject: iommu/amd: Fix sysfs leak in iommu init + +From: Kun(llfl) + +[ Upstream commit a295ec52c8624883885396fde7b4df1a179627c3 ] + +During the iommu initialization, iommu_init_pci() adds sysfs nodes. +However, these nodes aren't remove in free_iommu_resources() subsequently. + +Fixes: 39ab9555c241 ("iommu: Add sysfs bindings for struct iommu_device") +Signed-off-by: Kun(llfl) +Reviewed-by: Suravee Suthikulpanit +Link: https://lore.kernel.org/r/c8e0d11c6ab1ee48299c288009cf9c5dae07b42d.1715215003.git.llfl@linux.alibaba.com +Signed-off-by: Joerg Roedel +Signed-off-by: Sasha Levin +--- + drivers/iommu/amd/init.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c +index f440ca440d924..e740dc54c4685 100644 +--- a/drivers/iommu/amd/init.c ++++ b/drivers/iommu/amd/init.c +@@ -1678,8 +1678,17 @@ static void __init free_pci_segments(void) + } + } + ++static void __init free_sysfs(struct amd_iommu *iommu) ++{ ++ if (iommu->iommu.dev) { ++ iommu_device_unregister(&iommu->iommu); ++ iommu_device_sysfs_remove(&iommu->iommu); ++ } ++} ++ + static void __init free_iommu_one(struct amd_iommu *iommu) + { ++ free_sysfs(iommu); + free_cwwb_sem(iommu); + free_command_buffer(iommu); + free_event_buffer(iommu); +-- +2.43.0 + diff --git a/queue-6.9/iommu-return-right-value-in-iommu_sva_bind_device.patch b/queue-6.9/iommu-return-right-value-in-iommu_sva_bind_device.patch new file mode 100644 index 00000000000..2415c86a07d --- /dev/null +++ b/queue-6.9/iommu-return-right-value-in-iommu_sva_bind_device.patch @@ -0,0 +1,49 @@ +From c8b0be57c13921e048b2ed5a5bc6874713daf78c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 28 May 2024 12:25:28 +0800 +Subject: iommu: Return right value in iommu_sva_bind_device() + +From: Lu Baolu + +[ Upstream commit 89e8a2366e3bce584b6c01549d5019c5cda1205e ] + +iommu_sva_bind_device() should return either a sva bond handle or an +ERR_PTR value in error cases. Existing drivers (idxd and uacce) only +check the return value with IS_ERR(). This could potentially lead to +a kernel NULL pointer dereference issue if the function returns NULL +instead of an error pointer. + +In reality, this doesn't cause any problems because iommu_sva_bind_device() +only returns NULL when the kernel is not configured with CONFIG_IOMMU_SVA. +In this case, iommu_dev_enable_feature(dev, IOMMU_DEV_FEAT_SVA) will +return an error, and the device drivers won't call iommu_sva_bind_device() +at all. + +Fixes: 26b25a2b98e4 ("iommu: Bind process address spaces to devices") +Signed-off-by: Lu Baolu +Reviewed-by: Jean-Philippe Brucker +Reviewed-by: Kevin Tian +Reviewed-by: Vasant Hegde +Link: https://lore.kernel.org/r/20240528042528.71396-1-baolu.lu@linux.intel.com +Signed-off-by: Joerg Roedel +Signed-off-by: Sasha Levin +--- + include/linux/iommu.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/include/linux/iommu.h b/include/linux/iommu.h +index 2e925b5eba534..3b67d59a36bf9 100644 +--- a/include/linux/iommu.h ++++ b/include/linux/iommu.h +@@ -1537,7 +1537,7 @@ struct iommu_domain *iommu_sva_domain_alloc(struct device *dev, + static inline struct iommu_sva * + iommu_sva_bind_device(struct device *dev, struct mm_struct *mm) + { +- return NULL; ++ return ERR_PTR(-ENODEV); + } + + static inline void iommu_sva_unbind_device(struct iommu_sva *handle) +-- +2.43.0 + diff --git a/queue-6.9/ionic-fix-use-after-netif_napi_del.patch b/queue-6.9/ionic-fix-use-after-netif_napi_del.patch new file mode 100644 index 00000000000..753e80a60df --- /dev/null +++ b/queue-6.9/ionic-fix-use-after-netif_napi_del.patch @@ -0,0 +1,97 @@ +From 81aef6f934b221d1521673874a15b11da595af1c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Jun 2024 06:04:46 +0000 +Subject: ionic: fix use after netif_napi_del() + +From: Taehee Yoo + +[ Upstream commit 79f18a41dd056115d685f3b0a419c7cd40055e13 ] + +When queues are started, netif_napi_add() and napi_enable() are called. +If there are 4 queues and only 3 queues are used for the current +configuration, only 3 queues' napi should be registered and enabled. +The ionic_qcq_enable() checks whether the .poll pointer is not NULL for +enabling only the using queue' napi. Unused queues' napi will not be +registered by netif_napi_add(), so the .poll pointer indicates NULL. +But it couldn't distinguish whether the napi was unregistered or not +because netif_napi_del() doesn't reset the .poll pointer to NULL. +So, ionic_qcq_enable() calls napi_enable() for the queue, which was +unregistered by netif_napi_del(). + +Reproducer: + ethtool -L rx 1 tx 1 combined 0 + ethtool -L rx 0 tx 0 combined 1 + ethtool -L rx 0 tx 0 combined 4 + +Splat looks like: +kernel BUG at net/core/dev.c:6666! +Oops: invalid opcode: 0000 [#1] PREEMPT SMP NOPTI +CPU: 3 PID: 1057 Comm: kworker/3:3 Not tainted 6.10.0-rc2+ #16 +Workqueue: events ionic_lif_deferred_work [ionic] +RIP: 0010:napi_enable+0x3b/0x40 +Code: 48 89 c2 48 83 e2 f6 80 b9 61 09 00 00 00 74 0d 48 83 bf 60 01 00 00 00 74 03 80 ce 01 f0 4f +RSP: 0018:ffffb6ed83227d48 EFLAGS: 00010246 +RAX: 0000000000000000 RBX: ffff97560cda0828 RCX: 0000000000000029 +RDX: 0000000000000001 RSI: 0000000000000000 RDI: ffff97560cda0a28 +RBP: ffffb6ed83227d50 R08: 0000000000000400 R09: 0000000000000001 +R10: 0000000000000001 R11: 0000000000000001 R12: 0000000000000000 +R13: ffff97560ce3c1a0 R14: 0000000000000000 R15: ffff975613ba0a20 +FS: 0000000000000000(0000) GS:ffff975d5f780000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 00007f8f734ee200 CR3: 0000000103e50000 CR4: 00000000007506f0 +PKRU: 55555554 +Call Trace: + + ? die+0x33/0x90 + ? do_trap+0xd9/0x100 + ? napi_enable+0x3b/0x40 + ? do_error_trap+0x83/0xb0 + ? napi_enable+0x3b/0x40 + ? napi_enable+0x3b/0x40 + ? exc_invalid_op+0x4e/0x70 + ? napi_enable+0x3b/0x40 + ? asm_exc_invalid_op+0x16/0x20 + ? napi_enable+0x3b/0x40 + ionic_qcq_enable+0xb7/0x180 [ionic 59bdfc8a035436e1c4224ff7d10789e3f14643f8] + ionic_start_queues+0xc4/0x290 [ionic 59bdfc8a035436e1c4224ff7d10789e3f14643f8] + ionic_link_status_check+0x11c/0x170 [ionic 59bdfc8a035436e1c4224ff7d10789e3f14643f8] + ionic_lif_deferred_work+0x129/0x280 [ionic 59bdfc8a035436e1c4224ff7d10789e3f14643f8] + process_one_work+0x145/0x360 + worker_thread+0x2bb/0x3d0 + ? __pfx_worker_thread+0x10/0x10 + kthread+0xcc/0x100 + ? __pfx_kthread+0x10/0x10 + ret_from_fork+0x2d/0x50 + ? __pfx_kthread+0x10/0x10 + ret_from_fork_asm+0x1a/0x30 + +Fixes: 0f3154e6bcb3 ("ionic: Add Tx and Rx handling") +Signed-off-by: Taehee Yoo +Reviewed-by: Brett Creeley +Reviewed-by: Shannon Nelson +Link: https://lore.kernel.org/r/20240612060446.1754392-1-ap420073@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/pensando/ionic/ionic_lif.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c +index 7f0c6cdc375e3..0cd819bc4ae35 100644 +--- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c ++++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c +@@ -304,10 +304,8 @@ static int ionic_qcq_enable(struct ionic_qcq *qcq) + if (ret) + return ret; + +- if (qcq->napi.poll) +- napi_enable(&qcq->napi); +- + if (qcq->flags & IONIC_QCQ_F_INTR) { ++ napi_enable(&qcq->napi); + irq_set_affinity_hint(qcq->intr.vector, + &qcq->intr.affinity_mask); + ionic_intr_mask(idev->intr_ctrl, qcq->intr.index, +-- +2.43.0 + diff --git a/queue-6.9/kselftest-alsa-ensure-_gnu_source-is-defined.patch b/queue-6.9/kselftest-alsa-ensure-_gnu_source-is-defined.patch new file mode 100644 index 00000000000..65d6e453ff8 --- /dev/null +++ b/queue-6.9/kselftest-alsa-ensure-_gnu_source-is-defined.patch @@ -0,0 +1,39 @@ +From 5a2051b78d3f06dca81bfd6338039949f284216d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 May 2024 16:27:33 +0100 +Subject: kselftest/alsa: Ensure _GNU_SOURCE is defined + +From: Mark Brown + +[ Upstream commit 2032e61e24fe9fe55d6c7a34fb5506c911b3e280 ] + +The pcmtest driver tests use the kselftest harness which requires that +_GNU_SOURCE is defined but nothing causes it to be defined. Since the +KHDR_INCLUDES Makefile variable has had the required define added let's +use that, this should provide some futureproofing. + +Fixes: daef47b89efd ("selftests: Compile kselftest headers with -D_GNU_SOURCE") +Signed-off-by: Mark Brown +Reviewed-by: Muhammad Usama Anjum +Signed-off-by: Shuah Khan +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/alsa/Makefile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/testing/selftests/alsa/Makefile b/tools/testing/selftests/alsa/Makefile +index 5af9ba8a4645b..c1ce39874e2b5 100644 +--- a/tools/testing/selftests/alsa/Makefile ++++ b/tools/testing/selftests/alsa/Makefile +@@ -1,7 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + # + +-CFLAGS += $(shell pkg-config --cflags alsa) ++CFLAGS += $(shell pkg-config --cflags alsa) $(KHDR_INCLUDES) + LDLIBS += $(shell pkg-config --libs alsa) + ifeq ($(LDLIBS),) + LDLIBS += -lasound +-- +2.43.0 + diff --git a/queue-6.9/liquidio-adjust-a-null-pointer-handling-path-in-lio_.patch b/queue-6.9/liquidio-adjust-a-null-pointer-handling-path-in-lio_.patch new file mode 100644 index 00000000000..59df1e8f1d5 --- /dev/null +++ b/queue-6.9/liquidio-adjust-a-null-pointer-handling-path-in-lio_.patch @@ -0,0 +1,69 @@ +From bbc096912968f6a13b3c661cf1ab5b3a25e19ce5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Jun 2024 13:11:35 +0300 +Subject: liquidio: Adjust a NULL pointer handling path in + lio_vf_rep_copy_packet + +From: Aleksandr Mishin + +[ Upstream commit c44711b78608c98a3e6b49ce91678cd0917d5349 ] + +In lio_vf_rep_copy_packet() pg_info->page is compared to a NULL value, +but then it is unconditionally passed to skb_add_rx_frag() which looks +strange and could lead to null pointer dereference. + +lio_vf_rep_copy_packet() call trace looks like: + octeon_droq_process_packets + octeon_droq_fast_process_packets + octeon_droq_dispatch_pkt + octeon_create_recv_info + ...search in the dispatch_list... + ->disp_fn(rdisp->rinfo, ...) + lio_vf_rep_pkt_recv(struct octeon_recv_info *recv_info, ...) +In this path there is no code which sets pg_info->page to NULL. +So this check looks unneeded and doesn't solve potential problem. +But I guess the author had reason to add a check and I have no such card +and can't do real test. +In addition, the code in the function liquidio_push_packet() in +liquidio/lio_core.c does exactly the same. + +Based on this, I consider the most acceptable compromise solution to +adjust this issue by moving skb_add_rx_frag() into conditional scope. + +Found by Linux Verification Center (linuxtesting.org) with SVACE. + +Fixes: 1f233f327913 ("liquidio: switchdev support for LiquidIO NIC") +Signed-off-by: Aleksandr Mishin +Reviewed-by: Simon Horman +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/cavium/liquidio/lio_vf_rep.c | 11 +++++------ + 1 file changed, 5 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/ethernet/cavium/liquidio/lio_vf_rep.c b/drivers/net/ethernet/cavium/liquidio/lio_vf_rep.c +index aa6c0dfb6f1ca..e26b4ed33dc83 100644 +--- a/drivers/net/ethernet/cavium/liquidio/lio_vf_rep.c ++++ b/drivers/net/ethernet/cavium/liquidio/lio_vf_rep.c +@@ -272,13 +272,12 @@ lio_vf_rep_copy_packet(struct octeon_device *oct, + pg_info->page_offset; + memcpy(skb->data, va, MIN_SKB_SIZE); + skb_put(skb, MIN_SKB_SIZE); ++ skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, ++ pg_info->page, ++ pg_info->page_offset + MIN_SKB_SIZE, ++ len - MIN_SKB_SIZE, ++ LIO_RXBUFFER_SZ); + } +- +- skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, +- pg_info->page, +- pg_info->page_offset + MIN_SKB_SIZE, +- len - MIN_SKB_SIZE, +- LIO_RXBUFFER_SZ); + } else { + struct octeon_skb_page_info *pg_info = + ((struct octeon_skb_page_info *)(skb->cb)); +-- +2.43.0 + diff --git a/queue-6.9/modpost-do-not-warn-about-missing-module_description.patch b/queue-6.9/modpost-do-not-warn-about-missing-module_description.patch new file mode 100644 index 00000000000..087ea5f54ef --- /dev/null +++ b/queue-6.9/modpost-do-not-warn-about-missing-module_description.patch @@ -0,0 +1,44 @@ +From 01193dcd104bc9501ac3708dcc60bd552ee93766 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Jun 2024 03:36:12 +0900 +Subject: modpost: do not warn about missing MODULE_DESCRIPTION() for vmlinux.o + +From: Masahiro Yamada + +[ Upstream commit 9185afeac2a3dcce8300a5684291a43c2838cfd6 ] + +Building with W=1 incorrectly emits the following warning: + + WARNING: modpost: missing MODULE_DESCRIPTION() in vmlinux.o + +This check should apply only to modules. + +Fixes: 1fffe7a34c89 ("script: modpost: emit a warning when the description is missing") +Signed-off-by: Masahiro Yamada +Reviewed-by: Vincenzo Palazzo +Signed-off-by: Sasha Levin +--- + scripts/mod/modpost.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c +index 2f5b91da5afa9..c27c762e68807 100644 +--- a/scripts/mod/modpost.c ++++ b/scripts/mod/modpost.c +@@ -1652,10 +1652,11 @@ static void read_symbols(const char *modname) + namespace = get_next_modinfo(&info, "import_ns", + namespace); + } ++ ++ if (extra_warn && !get_modinfo(&info, "description")) ++ warn("missing MODULE_DESCRIPTION() in %s\n", modname); + } + +- if (extra_warn && !get_modinfo(&info, "description")) +- warn("missing MODULE_DESCRIPTION() in %s\n", modname); + for (sym = info.symtab_start; sym < info.symtab_stop; sym++) { + symname = remove_dot(info.strtab + sym->st_name); + +-- +2.43.0 + diff --git a/queue-6.9/net-bridge-mst-fix-suspicious-rcu-usage-in-br_mst_se.patch b/queue-6.9/net-bridge-mst-fix-suspicious-rcu-usage-in-br_mst_se.patch new file mode 100644 index 00000000000..6096dd11290 --- /dev/null +++ b/queue-6.9/net-bridge-mst-fix-suspicious-rcu-usage-in-br_mst_se.patch @@ -0,0 +1,40 @@ +From d6ad38f77cb948f08b869df249a4eef17f01aefa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Jun 2024 13:36:54 +0300 +Subject: net: bridge: mst: fix suspicious rcu usage in br_mst_set_state + +From: Nikolay Aleksandrov + +[ Upstream commit 546ceb1dfdac866648ec959cbc71d9525bd73462 ] + +I converted br_mst_set_state to RCU to avoid a vlan use-after-free +but forgot to change the vlan group dereference helper. Switch to vlan +group RCU deref helper to fix the suspicious rcu usage warning. + +Fixes: 3a7c1661ae13 ("net: bridge: mst: fix vlan use-after-free") +Reported-by: syzbot+9bbe2de1bc9d470eb5fe@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=9bbe2de1bc9d470eb5fe +Signed-off-by: Nikolay Aleksandrov +Link: https://lore.kernel.org/r/20240609103654.914987-3-razor@blackwall.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/bridge/br_mst.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/bridge/br_mst.c b/net/bridge/br_mst.c +index 1de72816b0fb2..1820f09ff59ce 100644 +--- a/net/bridge/br_mst.c ++++ b/net/bridge/br_mst.c +@@ -102,7 +102,7 @@ int br_mst_set_state(struct net_bridge_port *p, u16 msti, u8 state, + int err = 0; + + rcu_read_lock(); +- vg = nbp_vlan_group(p); ++ vg = nbp_vlan_group_rcu(p); + if (!vg) + goto out; + +-- +2.43.0 + diff --git a/queue-6.9/net-bridge-mst-pass-vlan-group-directly-to-br_mst_vl.patch b/queue-6.9/net-bridge-mst-pass-vlan-group-directly-to-br_mst_vl.patch new file mode 100644 index 00000000000..3a56e4a457e --- /dev/null +++ b/queue-6.9/net-bridge-mst-pass-vlan-group-directly-to-br_mst_vl.patch @@ -0,0 +1,72 @@ +From 5b598e6ac7401933df0db1ca05e9dc2fb70b8e13 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Jun 2024 13:36:53 +0300 +Subject: net: bridge: mst: pass vlan group directly to br_mst_vlan_set_state + +From: Nikolay Aleksandrov + +[ Upstream commit 36c92936e868601fa1f43da6758cf55805043509 ] + +Pass the already obtained vlan group pointer to br_mst_vlan_set_state() +instead of dereferencing it again. Each caller has already correctly +dereferenced it for their context. This change is required for the +following suspicious RCU dereference fix. No functional changes +intended. + +Fixes: 3a7c1661ae13 ("net: bridge: mst: fix vlan use-after-free") +Reported-by: syzbot+9bbe2de1bc9d470eb5fe@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=9bbe2de1bc9d470eb5fe +Signed-off-by: Nikolay Aleksandrov +Link: https://lore.kernel.org/r/20240609103654.914987-2-razor@blackwall.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/bridge/br_mst.c | 11 +++++------ + 1 file changed, 5 insertions(+), 6 deletions(-) + +diff --git a/net/bridge/br_mst.c b/net/bridge/br_mst.c +index 3c66141d34d62..1de72816b0fb2 100644 +--- a/net/bridge/br_mst.c ++++ b/net/bridge/br_mst.c +@@ -73,11 +73,10 @@ int br_mst_get_state(const struct net_device *dev, u16 msti, u8 *state) + } + EXPORT_SYMBOL_GPL(br_mst_get_state); + +-static void br_mst_vlan_set_state(struct net_bridge_port *p, struct net_bridge_vlan *v, ++static void br_mst_vlan_set_state(struct net_bridge_vlan_group *vg, ++ struct net_bridge_vlan *v, + u8 state) + { +- struct net_bridge_vlan_group *vg = nbp_vlan_group(p); +- + if (br_vlan_get_state(v) == state) + return; + +@@ -121,7 +120,7 @@ int br_mst_set_state(struct net_bridge_port *p, u16 msti, u8 state, + if (v->brvlan->msti != msti) + continue; + +- br_mst_vlan_set_state(p, v, state); ++ br_mst_vlan_set_state(vg, v, state); + } + + out: +@@ -140,13 +139,13 @@ static void br_mst_vlan_sync_state(struct net_bridge_vlan *pv, u16 msti) + * it. + */ + if (v != pv && v->brvlan->msti == msti) { +- br_mst_vlan_set_state(pv->port, pv, v->state); ++ br_mst_vlan_set_state(vg, pv, v->state); + return; + } + } + + /* Otherwise, start out in a new MSTI with all ports disabled. */ +- return br_mst_vlan_set_state(pv->port, pv, BR_STATE_DISABLED); ++ return br_mst_vlan_set_state(vg, pv, BR_STATE_DISABLED); + } + + int br_mst_vlan_set_msti(struct net_bridge_vlan *mv, u16 msti) +-- +2.43.0 + diff --git a/queue-6.9/net-change-proto-and-proto_ops-accept-type.patch b/queue-6.9/net-change-proto-and-proto_ops-accept-type.patch new file mode 100644 index 00000000000..95a768c72d6 --- /dev/null +++ b/queue-6.9/net-change-proto-and-proto_ops-accept-type.patch @@ -0,0 +1,1026 @@ +From 1c9995693f2f9207e4371e04c265705f29c0d575 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 May 2024 09:20:08 -0600 +Subject: net: change proto and proto_ops accept type + +From: Jens Axboe + +[ Upstream commit 92ef0fd55ac80dfc2e4654edfe5d1ddfa6e070fe ] + +Rather than pass in flags, error pointer, and whether this is a kernel +invocation or not, add a struct proto_accept_arg struct as the argument. +This then holds all of these arguments, and prepares accept for being +able to pass back more information. + +No functional changes in this patch. + +Acked-by: Jakub Kicinski +Signed-off-by: Jens Axboe +Stable-dep-of: 1b536948e805 ("af_unix: Annotate data-race of sk->sk_state in unix_accept().") +Signed-off-by: Sasha Levin +--- + crypto/af_alg.c | 11 ++++++----- + crypto/algif_hash.c | 10 +++++----- + drivers/xen/pvcalls-back.c | 6 +++++- + fs/ocfs2/cluster/tcp.c | 5 ++++- + include/crypto/if_alg.h | 3 ++- + include/linux/net.h | 4 +++- + include/net/inet_common.h | 4 ++-- + include/net/inet_connection_sock.h | 2 +- + include/net/sock.h | 12 +++++++++--- + net/atm/svc.c | 8 ++++---- + net/ax25/af_ax25.c | 6 +++--- + net/bluetooth/iso.c | 4 ++-- + net/bluetooth/l2cap_sock.c | 4 ++-- + net/bluetooth/rfcomm/sock.c | 6 +++--- + net/bluetooth/sco.c | 4 ++-- + net/core/sock.c | 4 ++-- + net/ipv4/af_inet.c | 10 +++++----- + net/ipv4/inet_connection_sock.c | 6 +++--- + net/iucv/af_iucv.c | 4 ++-- + net/llc/af_llc.c | 7 +++---- + net/mptcp/protocol.c | 11 +++++------ + net/netrom/af_netrom.c | 6 +++--- + net/nfc/llcp_sock.c | 4 ++-- + net/phonet/pep.c | 12 ++++++------ + net/phonet/socket.c | 7 +++---- + net/rds/tcp_listen.c | 6 +++++- + net/rose/af_rose.c | 6 +++--- + net/sctp/socket.c | 8 ++++---- + net/smc/af_smc.c | 6 +++--- + net/socket.c | 13 ++++++++++--- + net/tipc/socket.c | 13 +++++-------- + net/unix/af_unix.c | 21 ++++++++++----------- + net/vmw_vsock/af_vsock.c | 6 +++--- + net/x25/af_x25.c | 4 ++-- + 34 files changed, 132 insertions(+), 111 deletions(-) + +diff --git a/crypto/af_alg.c b/crypto/af_alg.c +index 68cc9290cabe9..598bf46691706 100644 +--- a/crypto/af_alg.c ++++ b/crypto/af_alg.c +@@ -407,7 +407,8 @@ static int alg_setsockopt(struct socket *sock, int level, int optname, + return err; + } + +-int af_alg_accept(struct sock *sk, struct socket *newsock, bool kern) ++int af_alg_accept(struct sock *sk, struct socket *newsock, ++ struct proto_accept_arg *arg) + { + struct alg_sock *ask = alg_sk(sk); + const struct af_alg_type *type; +@@ -422,7 +423,7 @@ int af_alg_accept(struct sock *sk, struct socket *newsock, bool kern) + if (!type) + goto unlock; + +- sk2 = sk_alloc(sock_net(sk), PF_ALG, GFP_KERNEL, &alg_proto, kern); ++ sk2 = sk_alloc(sock_net(sk), PF_ALG, GFP_KERNEL, &alg_proto, arg->kern); + err = -ENOMEM; + if (!sk2) + goto unlock; +@@ -468,10 +469,10 @@ int af_alg_accept(struct sock *sk, struct socket *newsock, bool kern) + } + EXPORT_SYMBOL_GPL(af_alg_accept); + +-static int alg_accept(struct socket *sock, struct socket *newsock, int flags, +- bool kern) ++static int alg_accept(struct socket *sock, struct socket *newsock, ++ struct proto_accept_arg *arg) + { +- return af_alg_accept(sock->sk, newsock, kern); ++ return af_alg_accept(sock->sk, newsock, arg); + } + + static const struct proto_ops alg_proto_ops = { +diff --git a/crypto/algif_hash.c b/crypto/algif_hash.c +index e24c829d7a015..7c7394d46a235 100644 +--- a/crypto/algif_hash.c ++++ b/crypto/algif_hash.c +@@ -223,8 +223,8 @@ static int hash_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, + return err ?: len; + } + +-static int hash_accept(struct socket *sock, struct socket *newsock, int flags, +- bool kern) ++static int hash_accept(struct socket *sock, struct socket *newsock, ++ struct proto_accept_arg *arg) + { + struct sock *sk = sock->sk; + struct alg_sock *ask = alg_sk(sk); +@@ -252,7 +252,7 @@ static int hash_accept(struct socket *sock, struct socket *newsock, int flags, + if (err) + goto out_free_state; + +- err = af_alg_accept(ask->parent, newsock, kern); ++ err = af_alg_accept(ask->parent, newsock, arg); + if (err) + goto out_free_state; + +@@ -355,7 +355,7 @@ static int hash_recvmsg_nokey(struct socket *sock, struct msghdr *msg, + } + + static int hash_accept_nokey(struct socket *sock, struct socket *newsock, +- int flags, bool kern) ++ struct proto_accept_arg *arg) + { + int err; + +@@ -363,7 +363,7 @@ static int hash_accept_nokey(struct socket *sock, struct socket *newsock, + if (err) + return err; + +- return hash_accept(sock, newsock, flags, kern); ++ return hash_accept(sock, newsock, arg); + } + + static struct proto_ops algif_hash_ops_nokey = { +diff --git a/drivers/xen/pvcalls-back.c b/drivers/xen/pvcalls-back.c +index d52593466a792..fd7ed65e0197d 100644 +--- a/drivers/xen/pvcalls-back.c ++++ b/drivers/xen/pvcalls-back.c +@@ -517,6 +517,10 @@ static void __pvcalls_back_accept(struct work_struct *work) + { + struct sockpass_mapping *mappass = container_of( + work, struct sockpass_mapping, register_work); ++ struct proto_accept_arg arg = { ++ .flags = O_NONBLOCK, ++ .kern = true, ++ }; + struct sock_mapping *map; + struct pvcalls_ioworker *iow; + struct pvcalls_fedata *fedata; +@@ -548,7 +552,7 @@ static void __pvcalls_back_accept(struct work_struct *work) + sock->type = mappass->sock->type; + sock->ops = mappass->sock->ops; + +- ret = inet_accept(mappass->sock, sock, O_NONBLOCK, true); ++ ret = inet_accept(mappass->sock, sock, &arg); + if (ret == -EAGAIN) { + sock_release(sock); + return; +diff --git a/fs/ocfs2/cluster/tcp.c b/fs/ocfs2/cluster/tcp.c +index 960080753d3bd..2b8fa3e782fb6 100644 +--- a/fs/ocfs2/cluster/tcp.c ++++ b/fs/ocfs2/cluster/tcp.c +@@ -1784,6 +1784,9 @@ static int o2net_accept_one(struct socket *sock, int *more) + struct o2nm_node *node = NULL; + struct o2nm_node *local_node = NULL; + struct o2net_sock_container *sc = NULL; ++ struct proto_accept_arg arg = { ++ .flags = O_NONBLOCK, ++ }; + struct o2net_node *nn; + unsigned int nofs_flag; + +@@ -1802,7 +1805,7 @@ static int o2net_accept_one(struct socket *sock, int *more) + + new_sock->type = sock->type; + new_sock->ops = sock->ops; +- ret = sock->ops->accept(sock, new_sock, O_NONBLOCK, false); ++ ret = sock->ops->accept(sock, new_sock, &arg); + if (ret < 0) + goto out; + +diff --git a/include/crypto/if_alg.h b/include/crypto/if_alg.h +index 78ecaf5db04c6..f7b3b93f3a49a 100644 +--- a/include/crypto/if_alg.h ++++ b/include/crypto/if_alg.h +@@ -166,7 +166,8 @@ int af_alg_unregister_type(const struct af_alg_type *type); + + int af_alg_release(struct socket *sock); + void af_alg_release_parent(struct sock *sk); +-int af_alg_accept(struct sock *sk, struct socket *newsock, bool kern); ++int af_alg_accept(struct sock *sk, struct socket *newsock, ++ struct proto_accept_arg *arg); + + void af_alg_free_sg(struct af_alg_sgl *sgl); + +diff --git a/include/linux/net.h b/include/linux/net.h +index 15df6d5f27a7b..688320b79fcc6 100644 +--- a/include/linux/net.h ++++ b/include/linux/net.h +@@ -153,6 +153,7 @@ struct sockaddr; + struct msghdr; + struct module; + struct sk_buff; ++struct proto_accept_arg; + typedef int (*sk_read_actor_t)(read_descriptor_t *, struct sk_buff *, + unsigned int, size_t); + typedef int (*skb_read_actor_t)(struct sock *, struct sk_buff *); +@@ -171,7 +172,8 @@ struct proto_ops { + int (*socketpair)(struct socket *sock1, + struct socket *sock2); + int (*accept) (struct socket *sock, +- struct socket *newsock, int flags, bool kern); ++ struct socket *newsock, ++ struct proto_accept_arg *arg); + int (*getname) (struct socket *sock, + struct sockaddr *addr, + int peer); +diff --git a/include/net/inet_common.h b/include/net/inet_common.h +index f50a644d87a98..c17a6585d0b0b 100644 +--- a/include/net/inet_common.h ++++ b/include/net/inet_common.h +@@ -29,8 +29,8 @@ int __inet_stream_connect(struct socket *sock, struct sockaddr *uaddr, + int addr_len, int flags, int is_sendmsg); + int inet_dgram_connect(struct socket *sock, struct sockaddr *uaddr, + int addr_len, int flags); +-int inet_accept(struct socket *sock, struct socket *newsock, int flags, +- bool kern); ++int inet_accept(struct socket *sock, struct socket *newsock, ++ struct proto_accept_arg *arg); + void __inet_accept(struct socket *sock, struct socket *newsock, + struct sock *newsk); + int inet_send_prepare(struct sock *sk); +diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h +index ccf171f7eb60d..aa435d90f12f9 100644 +--- a/include/net/inet_connection_sock.h ++++ b/include/net/inet_connection_sock.h +@@ -253,7 +253,7 @@ inet_csk_rto_backoff(const struct inet_connection_sock *icsk, + return (unsigned long)min_t(u64, when, max_when); + } + +-struct sock *inet_csk_accept(struct sock *sk, int flags, int *err, bool kern); ++struct sock *inet_csk_accept(struct sock *sk, struct proto_accept_arg *arg); + + int inet_csk_get_port(struct sock *sk, unsigned short snum); + +diff --git a/include/net/sock.h b/include/net/sock.h +index 944f71a8ab223..774ee477e6572 100644 +--- a/include/net/sock.h ++++ b/include/net/sock.h +@@ -1194,6 +1194,12 @@ static inline void sk_prot_clear_nulls(struct sock *sk, int size) + size - offsetof(struct sock, sk_node.pprev)); + } + ++struct proto_accept_arg { ++ int flags; ++ int err; ++ bool kern; ++}; ++ + /* Networking protocol blocks we attach to sockets. + * socket layer -> transport layer interface + */ +@@ -1208,8 +1214,8 @@ struct proto { + int addr_len); + int (*disconnect)(struct sock *sk, int flags); + +- struct sock * (*accept)(struct sock *sk, int flags, int *err, +- bool kern); ++ struct sock * (*accept)(struct sock *sk, ++ struct proto_accept_arg *arg); + + int (*ioctl)(struct sock *sk, int cmd, + int *karg); +@@ -1882,7 +1888,7 @@ int sock_cmsg_send(struct sock *sk, struct msghdr *msg, + int sock_no_bind(struct socket *, struct sockaddr *, int); + int sock_no_connect(struct socket *, struct sockaddr *, int, int); + int sock_no_socketpair(struct socket *, struct socket *); +-int sock_no_accept(struct socket *, struct socket *, int, bool); ++int sock_no_accept(struct socket *, struct socket *, struct proto_accept_arg *); + int sock_no_getname(struct socket *, struct sockaddr *, int); + int sock_no_ioctl(struct socket *, unsigned int, unsigned long); + int sock_no_listen(struct socket *, int); +diff --git a/net/atm/svc.c b/net/atm/svc.c +index 36a814f1fbd16..f8137ae693b08 100644 +--- a/net/atm/svc.c ++++ b/net/atm/svc.c +@@ -324,8 +324,8 @@ static int svc_listen(struct socket *sock, int backlog) + return error; + } + +-static int svc_accept(struct socket *sock, struct socket *newsock, int flags, +- bool kern) ++static int svc_accept(struct socket *sock, struct socket *newsock, ++ struct proto_accept_arg *arg) + { + struct sock *sk = sock->sk; + struct sk_buff *skb; +@@ -336,7 +336,7 @@ static int svc_accept(struct socket *sock, struct socket *newsock, int flags, + + lock_sock(sk); + +- error = svc_create(sock_net(sk), newsock, 0, kern); ++ error = svc_create(sock_net(sk), newsock, 0, arg->kern); + if (error) + goto out; + +@@ -355,7 +355,7 @@ static int svc_accept(struct socket *sock, struct socket *newsock, int flags, + error = -sk->sk_err; + break; + } +- if (flags & O_NONBLOCK) { ++ if (arg->flags & O_NONBLOCK) { + error = -EAGAIN; + break; + } +diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c +index 5fff5930e4deb..d6f9fae06a9d8 100644 +--- a/net/ax25/af_ax25.c ++++ b/net/ax25/af_ax25.c +@@ -1373,8 +1373,8 @@ static int __must_check ax25_connect(struct socket *sock, + return err; + } + +-static int ax25_accept(struct socket *sock, struct socket *newsock, int flags, +- bool kern) ++static int ax25_accept(struct socket *sock, struct socket *newsock, ++ struct proto_accept_arg *arg) + { + struct sk_buff *skb; + struct sock *newsk; +@@ -1411,7 +1411,7 @@ static int ax25_accept(struct socket *sock, struct socket *newsock, int flags, + if (skb) + break; + +- if (flags & O_NONBLOCK) { ++ if (arg->flags & O_NONBLOCK) { + err = -EWOULDBLOCK; + break; + } +diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c +index 00c0d8413c638..cc055b952ce69 100644 +--- a/net/bluetooth/iso.c ++++ b/net/bluetooth/iso.c +@@ -1159,7 +1159,7 @@ static int iso_sock_listen(struct socket *sock, int backlog) + } + + static int iso_sock_accept(struct socket *sock, struct socket *newsock, +- int flags, bool kern) ++ struct proto_accept_arg *arg) + { + DEFINE_WAIT_FUNC(wait, woken_wake_function); + struct sock *sk = sock->sk, *ch; +@@ -1168,7 +1168,7 @@ static int iso_sock_accept(struct socket *sock, struct socket *newsock, + + lock_sock(sk); + +- timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK); ++ timeo = sock_rcvtimeo(sk, arg->flags & O_NONBLOCK); + + BT_DBG("sk %p timeo %ld", sk, timeo); + +diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c +index 8645461d45e81..6db60946c627c 100644 +--- a/net/bluetooth/l2cap_sock.c ++++ b/net/bluetooth/l2cap_sock.c +@@ -327,7 +327,7 @@ static int l2cap_sock_listen(struct socket *sock, int backlog) + } + + static int l2cap_sock_accept(struct socket *sock, struct socket *newsock, +- int flags, bool kern) ++ struct proto_accept_arg *arg) + { + DEFINE_WAIT_FUNC(wait, woken_wake_function); + struct sock *sk = sock->sk, *nsk; +@@ -336,7 +336,7 @@ static int l2cap_sock_accept(struct socket *sock, struct socket *newsock, + + lock_sock_nested(sk, L2CAP_NESTING_PARENT); + +- timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK); ++ timeo = sock_rcvtimeo(sk, arg->flags & O_NONBLOCK); + + BT_DBG("sk %p timeo %ld", sk, timeo); + +diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c +index 29aa07e9db9d7..37d63d768afb8 100644 +--- a/net/bluetooth/rfcomm/sock.c ++++ b/net/bluetooth/rfcomm/sock.c +@@ -468,8 +468,8 @@ static int rfcomm_sock_listen(struct socket *sock, int backlog) + return err; + } + +-static int rfcomm_sock_accept(struct socket *sock, struct socket *newsock, int flags, +- bool kern) ++static int rfcomm_sock_accept(struct socket *sock, struct socket *newsock, ++ struct proto_accept_arg *arg) + { + DEFINE_WAIT_FUNC(wait, woken_wake_function); + struct sock *sk = sock->sk, *nsk; +@@ -483,7 +483,7 @@ static int rfcomm_sock_accept(struct socket *sock, struct socket *newsock, int f + goto done; + } + +- timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK); ++ timeo = sock_rcvtimeo(sk, arg->flags & O_NONBLOCK); + + BT_DBG("sk %p timeo %ld", sk, timeo); + +diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c +index 71d36582d4efa..a5ac160c592eb 100644 +--- a/net/bluetooth/sco.c ++++ b/net/bluetooth/sco.c +@@ -647,7 +647,7 @@ static int sco_sock_listen(struct socket *sock, int backlog) + } + + static int sco_sock_accept(struct socket *sock, struct socket *newsock, +- int flags, bool kern) ++ struct proto_accept_arg *arg) + { + DEFINE_WAIT_FUNC(wait, woken_wake_function); + struct sock *sk = sock->sk, *ch; +@@ -656,7 +656,7 @@ static int sco_sock_accept(struct socket *sock, struct socket *newsock, + + lock_sock(sk); + +- timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK); ++ timeo = sock_rcvtimeo(sk, arg->flags & O_NONBLOCK); + + BT_DBG("sk %p timeo %ld", sk, timeo); + +diff --git a/net/core/sock.c b/net/core/sock.c +index 0963689a59506..5a06715871f4a 100644 +--- a/net/core/sock.c ++++ b/net/core/sock.c +@@ -3242,8 +3242,8 @@ int sock_no_socketpair(struct socket *sock1, struct socket *sock2) + } + EXPORT_SYMBOL(sock_no_socketpair); + +-int sock_no_accept(struct socket *sock, struct socket *newsock, int flags, +- bool kern) ++int sock_no_accept(struct socket *sock, struct socket *newsock, ++ struct proto_accept_arg *arg) + { + return -EOPNOTSUPP; + } +diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c +index 5622ddd3bf55b..c39ccd92172d3 100644 +--- a/net/ipv4/af_inet.c ++++ b/net/ipv4/af_inet.c +@@ -773,16 +773,16 @@ void __inet_accept(struct socket *sock, struct socket *newsock, struct sock *new + * Accept a pending connection. The TCP layer now gives BSD semantics. + */ + +-int inet_accept(struct socket *sock, struct socket *newsock, int flags, +- bool kern) ++int inet_accept(struct socket *sock, struct socket *newsock, ++ struct proto_accept_arg *arg) + { + struct sock *sk1 = sock->sk, *sk2; +- int err = -EINVAL; + + /* IPV6_ADDRFORM can change sk->sk_prot under us. */ +- sk2 = READ_ONCE(sk1->sk_prot)->accept(sk1, flags, &err, kern); ++ arg->err = -EINVAL; ++ sk2 = READ_ONCE(sk1->sk_prot)->accept(sk1, arg); + if (!sk2) +- return err; ++ return arg->err; + + lock_sock(sk2); + __inet_accept(sock, newsock, sk2); +diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c +index 3b38610958ee4..7734d189c66b8 100644 +--- a/net/ipv4/inet_connection_sock.c ++++ b/net/ipv4/inet_connection_sock.c +@@ -661,7 +661,7 @@ static int inet_csk_wait_for_connect(struct sock *sk, long timeo) + /* + * This will accept the next outstanding connection. + */ +-struct sock *inet_csk_accept(struct sock *sk, int flags, int *err, bool kern) ++struct sock *inet_csk_accept(struct sock *sk, struct proto_accept_arg *arg) + { + struct inet_connection_sock *icsk = inet_csk(sk); + struct request_sock_queue *queue = &icsk->icsk_accept_queue; +@@ -680,7 +680,7 @@ struct sock *inet_csk_accept(struct sock *sk, int flags, int *err, bool kern) + + /* Find already established connection */ + if (reqsk_queue_empty(queue)) { +- long timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK); ++ long timeo = sock_rcvtimeo(sk, arg->flags & O_NONBLOCK); + + /* If this is a non blocking socket don't sleep */ + error = -EAGAIN; +@@ -745,7 +745,7 @@ struct sock *inet_csk_accept(struct sock *sk, int flags, int *err, bool kern) + out_err: + newsk = NULL; + req = NULL; +- *err = error; ++ arg->err = error; + goto out; + } + EXPORT_SYMBOL(inet_csk_accept); +diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c +index 7c8c3adcac6e9..089acf6bd36d7 100644 +--- a/net/iucv/af_iucv.c ++++ b/net/iucv/af_iucv.c +@@ -795,7 +795,7 @@ static int iucv_sock_listen(struct socket *sock, int backlog) + + /* Accept a pending connection */ + static int iucv_sock_accept(struct socket *sock, struct socket *newsock, +- int flags, bool kern) ++ struct proto_accept_arg *arg) + { + DECLARE_WAITQUEUE(wait, current); + struct sock *sk = sock->sk, *nsk; +@@ -809,7 +809,7 @@ static int iucv_sock_accept(struct socket *sock, struct socket *newsock, + goto done; + } + +- timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK); ++ timeo = sock_rcvtimeo(sk, arg->flags & O_NONBLOCK); + + /* Wait for an incoming connection */ + add_wait_queue_exclusive(sk_sleep(sk), &wait); +diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c +index fde1140d899ef..4eb52add7103b 100644 +--- a/net/llc/af_llc.c ++++ b/net/llc/af_llc.c +@@ -688,14 +688,13 @@ static void llc_cmsg_rcv(struct msghdr *msg, struct sk_buff *skb) + * llc_ui_accept - accept a new incoming connection. + * @sock: Socket which connections arrive on. + * @newsock: Socket to move incoming connection to. +- * @flags: User specified operational flags. +- * @kern: If the socket is kernel internal ++ * @arg: User specified arguments + * + * Accept a new incoming connection. + * Returns 0 upon success, negative otherwise. + */ +-static int llc_ui_accept(struct socket *sock, struct socket *newsock, int flags, +- bool kern) ++static int llc_ui_accept(struct socket *sock, struct socket *newsock, ++ struct proto_accept_arg *arg) + { + struct sock *sk = sock->sk, *newsk; + struct llc_sock *llc, *newllc; +diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c +index 327dcf06edd47..e4644d50c909e 100644 +--- a/net/mptcp/protocol.c ++++ b/net/mptcp/protocol.c +@@ -3878,11 +3878,10 @@ static int mptcp_listen(struct socket *sock, int backlog) + } + + static int mptcp_stream_accept(struct socket *sock, struct socket *newsock, +- int flags, bool kern) ++ struct proto_accept_arg *arg) + { + struct mptcp_sock *msk = mptcp_sk(sock->sk); + struct sock *ssk, *newsk; +- int err; + + pr_debug("msk=%p", msk); + +@@ -3894,9 +3893,9 @@ static int mptcp_stream_accept(struct socket *sock, struct socket *newsock, + return -EINVAL; + + pr_debug("ssk=%p, listener=%p", ssk, mptcp_subflow_ctx(ssk)); +- newsk = inet_csk_accept(ssk, flags, &err, kern); ++ newsk = inet_csk_accept(ssk, arg); + if (!newsk) +- return err; ++ return arg->err; + + pr_debug("newsk=%p, subflow is mptcp=%d", newsk, sk_is_mptcp(newsk)); + if (sk_is_mptcp(newsk)) { +@@ -3917,7 +3916,7 @@ static int mptcp_stream_accept(struct socket *sock, struct socket *newsock, + newsk = new_mptcp_sock; + MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_MPCAPABLEPASSIVEACK); + +- newsk->sk_kern_sock = kern; ++ newsk->sk_kern_sock = arg->kern; + lock_sock(newsk); + __inet_accept(sock, newsock, newsk); + +@@ -3946,7 +3945,7 @@ static int mptcp_stream_accept(struct socket *sock, struct socket *newsock, + } + } else { + tcpfallback: +- newsk->sk_kern_sock = kern; ++ newsk->sk_kern_sock = arg->kern; + lock_sock(newsk); + __inet_accept(sock, newsock, newsk); + /* we are being invoked after accepting a non-mp-capable +diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c +index 104a80b75477f..6ee148f0e6d04 100644 +--- a/net/netrom/af_netrom.c ++++ b/net/netrom/af_netrom.c +@@ -772,8 +772,8 @@ static int nr_connect(struct socket *sock, struct sockaddr *uaddr, + return err; + } + +-static int nr_accept(struct socket *sock, struct socket *newsock, int flags, +- bool kern) ++static int nr_accept(struct socket *sock, struct socket *newsock, ++ struct proto_accept_arg *arg) + { + struct sk_buff *skb; + struct sock *newsk; +@@ -805,7 +805,7 @@ static int nr_accept(struct socket *sock, struct socket *newsock, int flags, + if (skb) + break; + +- if (flags & O_NONBLOCK) { ++ if (arg->flags & O_NONBLOCK) { + err = -EWOULDBLOCK; + break; + } +diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c +index d5344563e525c..57a2f97004e17 100644 +--- a/net/nfc/llcp_sock.c ++++ b/net/nfc/llcp_sock.c +@@ -447,7 +447,7 @@ struct sock *nfc_llcp_accept_dequeue(struct sock *parent, + } + + static int llcp_sock_accept(struct socket *sock, struct socket *newsock, +- int flags, bool kern) ++ struct proto_accept_arg *arg) + { + DECLARE_WAITQUEUE(wait, current); + struct sock *sk = sock->sk, *new_sk; +@@ -463,7 +463,7 @@ static int llcp_sock_accept(struct socket *sock, struct socket *newsock, + goto error; + } + +- timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK); ++ timeo = sock_rcvtimeo(sk, arg->flags & O_NONBLOCK); + + /* Wait for an incoming connection. */ + add_wait_queue_exclusive(sk_sleep(sk), &wait); +diff --git a/net/phonet/pep.c b/net/phonet/pep.c +index 3dd5f52bc1b58..53a858478e22f 100644 +--- a/net/phonet/pep.c ++++ b/net/phonet/pep.c +@@ -759,8 +759,8 @@ static void pep_sock_close(struct sock *sk, long timeout) + sock_put(sk); + } + +-static struct sock *pep_sock_accept(struct sock *sk, int flags, int *errp, +- bool kern) ++static struct sock *pep_sock_accept(struct sock *sk, ++ struct proto_accept_arg *arg) + { + struct pep_sock *pn = pep_sk(sk), *newpn; + struct sock *newsk = NULL; +@@ -772,8 +772,8 @@ static struct sock *pep_sock_accept(struct sock *sk, int flags, int *errp, + u8 pipe_handle, enabled, n_sb; + u8 aligned = 0; + +- skb = skb_recv_datagram(sk, (flags & O_NONBLOCK) ? MSG_DONTWAIT : 0, +- errp); ++ skb = skb_recv_datagram(sk, (arg->flags & O_NONBLOCK) ? MSG_DONTWAIT : 0, ++ &arg->err); + if (!skb) + return NULL; + +@@ -836,7 +836,7 @@ static struct sock *pep_sock_accept(struct sock *sk, int flags, int *errp, + + /* Create a new to-be-accepted sock */ + newsk = sk_alloc(sock_net(sk), PF_PHONET, GFP_KERNEL, sk->sk_prot, +- kern); ++ arg->kern); + if (!newsk) { + pep_reject_conn(sk, skb, PN_PIPE_ERR_OVERLOAD, GFP_KERNEL); + err = -ENOBUFS; +@@ -878,7 +878,7 @@ static struct sock *pep_sock_accept(struct sock *sk, int flags, int *errp, + drop: + release_sock(sk); + kfree_skb(skb); +- *errp = err; ++ arg->err = err; + return newsk; + } + +diff --git a/net/phonet/socket.c b/net/phonet/socket.c +index 1018340d89a7d..5ce0b3ee5def8 100644 +--- a/net/phonet/socket.c ++++ b/net/phonet/socket.c +@@ -292,18 +292,17 @@ static int pn_socket_connect(struct socket *sock, struct sockaddr *addr, + } + + static int pn_socket_accept(struct socket *sock, struct socket *newsock, +- int flags, bool kern) ++ struct proto_accept_arg *arg) + { + struct sock *sk = sock->sk; + struct sock *newsk; +- int err; + + if (unlikely(sk->sk_state != TCP_LISTEN)) + return -EINVAL; + +- newsk = sk->sk_prot->accept(sk, flags, &err, kern); ++ newsk = sk->sk_prot->accept(sk, arg); + if (!newsk) +- return err; ++ return arg->err; + + lock_sock(newsk); + sock_graft(newsk, newsock); +diff --git a/net/rds/tcp_listen.c b/net/rds/tcp_listen.c +index 05008ce5c4219..d89bd8d0c3545 100644 +--- a/net/rds/tcp_listen.c ++++ b/net/rds/tcp_listen.c +@@ -105,6 +105,10 @@ int rds_tcp_accept_one(struct socket *sock) + int conn_state; + struct rds_conn_path *cp; + struct in6_addr *my_addr, *peer_addr; ++ struct proto_accept_arg arg = { ++ .flags = O_NONBLOCK, ++ .kern = true, ++ }; + #if !IS_ENABLED(CONFIG_IPV6) + struct in6_addr saddr, daddr; + #endif +@@ -119,7 +123,7 @@ int rds_tcp_accept_one(struct socket *sock) + if (ret) + goto out; + +- ret = sock->ops->accept(sock, new_sock, O_NONBLOCK, true); ++ ret = sock->ops->accept(sock, new_sock, &arg); + if (ret < 0) + goto out; + +diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c +index ef81d019b20f4..59050caab65c8 100644 +--- a/net/rose/af_rose.c ++++ b/net/rose/af_rose.c +@@ -919,8 +919,8 @@ static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le + return err; + } + +-static int rose_accept(struct socket *sock, struct socket *newsock, int flags, +- bool kern) ++static int rose_accept(struct socket *sock, struct socket *newsock, ++ struct proto_accept_arg *arg) + { + struct sk_buff *skb; + struct sock *newsk; +@@ -953,7 +953,7 @@ static int rose_accept(struct socket *sock, struct socket *newsock, int flags, + if (skb) + break; + +- if (flags & O_NONBLOCK) { ++ if (arg->flags & O_NONBLOCK) { + err = -EWOULDBLOCK; + break; + } +diff --git a/net/sctp/socket.c b/net/sctp/socket.c +index c67679a41044f..732c67a9ce475 100644 +--- a/net/sctp/socket.c ++++ b/net/sctp/socket.c +@@ -4847,7 +4847,7 @@ static int sctp_disconnect(struct sock *sk, int flags) + * descriptor will be returned from accept() to represent the newly + * formed association. + */ +-static struct sock *sctp_accept(struct sock *sk, int flags, int *err, bool kern) ++static struct sock *sctp_accept(struct sock *sk, struct proto_accept_arg *arg) + { + struct sctp_sock *sp; + struct sctp_endpoint *ep; +@@ -4871,7 +4871,7 @@ static struct sock *sctp_accept(struct sock *sk, int flags, int *err, bool kern) + goto out; + } + +- timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK); ++ timeo = sock_rcvtimeo(sk, arg->flags & O_NONBLOCK); + + error = sctp_wait_for_accept(sk, timeo); + if (error) +@@ -4882,7 +4882,7 @@ static struct sock *sctp_accept(struct sock *sk, int flags, int *err, bool kern) + */ + asoc = list_entry(ep->asocs.next, struct sctp_association, asocs); + +- newsk = sp->pf->create_accept_sk(sk, asoc, kern); ++ newsk = sp->pf->create_accept_sk(sk, asoc, arg->kern); + if (!newsk) { + error = -ENOMEM; + goto out; +@@ -4899,7 +4899,7 @@ static struct sock *sctp_accept(struct sock *sk, int flags, int *err, bool kern) + + out: + release_sock(sk); +- *err = error; ++ arg->err = error; + return newsk; + } + +diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c +index 5f9f3d4c1df5f..ee6d8887c5730 100644 +--- a/net/smc/af_smc.c ++++ b/net/smc/af_smc.c +@@ -2656,7 +2656,7 @@ static int smc_listen(struct socket *sock, int backlog) + } + + static int smc_accept(struct socket *sock, struct socket *new_sock, +- int flags, bool kern) ++ struct proto_accept_arg *arg) + { + struct sock *sk = sock->sk, *nsk; + DECLARE_WAITQUEUE(wait, current); +@@ -2675,7 +2675,7 @@ static int smc_accept(struct socket *sock, struct socket *new_sock, + } + + /* Wait for an incoming connection */ +- timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK); ++ timeo = sock_rcvtimeo(sk, arg->flags & O_NONBLOCK); + add_wait_queue_exclusive(sk_sleep(sk), &wait); + while (!(nsk = smc_accept_dequeue(sk, new_sock))) { + set_current_state(TASK_INTERRUPTIBLE); +@@ -2702,7 +2702,7 @@ static int smc_accept(struct socket *sock, struct socket *new_sock, + if (rc) + goto out; + +- if (lsmc->sockopt_defer_accept && !(flags & O_NONBLOCK)) { ++ if (lsmc->sockopt_defer_accept && !(arg->flags & O_NONBLOCK)) { + /* wait till data arrives on the socket */ + timeo = msecs_to_jiffies(lsmc->sockopt_defer_accept * + MSEC_PER_SEC); +diff --git a/net/socket.c b/net/socket.c +index e5f3af49a8b62..2a78cff7159fe 100644 +--- a/net/socket.c ++++ b/net/socket.c +@@ -1898,6 +1898,9 @@ struct file *do_accept(struct file *file, unsigned file_flags, + struct file *newfile; + int err, len; + struct sockaddr_storage address; ++ struct proto_accept_arg arg = { ++ .flags = file_flags, ++ }; + const struct proto_ops *ops; + + sock = sock_from_file(file); +@@ -1926,8 +1929,8 @@ struct file *do_accept(struct file *file, unsigned file_flags, + if (err) + goto out_fd; + +- err = ops->accept(sock, newsock, sock->file->f_flags | file_flags, +- false); ++ arg.flags |= sock->file->f_flags; ++ err = ops->accept(sock, newsock, &arg); + if (err < 0) + goto out_fd; + +@@ -3580,6 +3583,10 @@ int kernel_accept(struct socket *sock, struct socket **newsock, int flags) + { + struct sock *sk = sock->sk; + const struct proto_ops *ops = READ_ONCE(sock->ops); ++ struct proto_accept_arg arg = { ++ .flags = flags, ++ .kern = true, ++ }; + int err; + + err = sock_create_lite(sk->sk_family, sk->sk_type, sk->sk_protocol, +@@ -3587,7 +3594,7 @@ int kernel_accept(struct socket *sock, struct socket **newsock, int flags) + if (err < 0) + goto done; + +- err = ops->accept(sock, *newsock, flags, true); ++ err = ops->accept(sock, *newsock, &arg); + if (err < 0) { + sock_release(*newsock); + *newsock = NULL; +diff --git a/net/tipc/socket.c b/net/tipc/socket.c +index 7e4135db58163..ed656c0ffe3d0 100644 +--- a/net/tipc/socket.c ++++ b/net/tipc/socket.c +@@ -146,8 +146,6 @@ static void tipc_data_ready(struct sock *sk); + static void tipc_write_space(struct sock *sk); + static void tipc_sock_destruct(struct sock *sk); + static int tipc_release(struct socket *sock); +-static int tipc_accept(struct socket *sock, struct socket *new_sock, int flags, +- bool kern); + static void tipc_sk_timeout(struct timer_list *t); + static int tipc_sk_publish(struct tipc_sock *tsk, struct tipc_uaddr *ua); + static int tipc_sk_withdraw(struct tipc_sock *tsk, struct tipc_uaddr *ua); +@@ -2711,13 +2709,12 @@ static int tipc_wait_for_accept(struct socket *sock, long timeo) + * tipc_accept - wait for connection request + * @sock: listening socket + * @new_sock: new socket that is to be connected +- * @flags: file-related flags associated with socket +- * @kern: caused by kernel or by userspace? ++ * @arg: arguments for accept + * + * Return: 0 on success, errno otherwise + */ +-static int tipc_accept(struct socket *sock, struct socket *new_sock, int flags, +- bool kern) ++static int tipc_accept(struct socket *sock, struct socket *new_sock, ++ struct proto_accept_arg *arg) + { + struct sock *new_sk, *sk = sock->sk; + struct tipc_sock *new_tsock; +@@ -2733,14 +2730,14 @@ static int tipc_accept(struct socket *sock, struct socket *new_sock, int flags, + res = -EINVAL; + goto exit; + } +- timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK); ++ timeo = sock_rcvtimeo(sk, arg->flags & O_NONBLOCK); + res = tipc_wait_for_accept(sock, timeo); + if (res) + goto exit; + + buf = skb_peek(&sk->sk_receive_queue); + +- res = tipc_sk_create(sock_net(sock->sk), new_sock, 0, kern); ++ res = tipc_sk_create(sock_net(sock->sk), new_sock, 0, arg->kern); + if (res) + goto exit; + security_sk_clone(sock->sk, new_sock->sk); +diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c +index a1938ba24a696..417cf4adb4e04 100644 +--- a/net/unix/af_unix.c ++++ b/net/unix/af_unix.c +@@ -749,7 +749,7 @@ static int unix_bind(struct socket *, struct sockaddr *, int); + static int unix_stream_connect(struct socket *, struct sockaddr *, + int addr_len, int flags); + static int unix_socketpair(struct socket *, struct socket *); +-static int unix_accept(struct socket *, struct socket *, int, bool); ++static int unix_accept(struct socket *, struct socket *, struct proto_accept_arg *arg); + static int unix_getname(struct socket *, struct sockaddr *, int); + static __poll_t unix_poll(struct file *, struct socket *, poll_table *); + static __poll_t unix_dgram_poll(struct file *, struct socket *, +@@ -1694,19 +1694,18 @@ static void unix_sock_inherit_flags(const struct socket *old, + set_bit(SOCK_PASSSEC, &new->flags); + } + +-static int unix_accept(struct socket *sock, struct socket *newsock, int flags, +- bool kern) ++static int unix_accept(struct socket *sock, struct socket *newsock, ++ struct proto_accept_arg *arg) + { + struct sock *sk = sock->sk; + struct sk_buff *skb; + struct sock *tsk; +- int err; + +- err = -EOPNOTSUPP; ++ arg->err = -EOPNOTSUPP; + if (sock->type != SOCK_STREAM && sock->type != SOCK_SEQPACKET) + goto out; + +- err = -EINVAL; ++ arg->err = -EINVAL; + if (sk->sk_state != TCP_LISTEN) + goto out; + +@@ -1714,12 +1713,12 @@ static int unix_accept(struct socket *sock, struct socket *newsock, int flags, + * so that no locks are necessary. + */ + +- skb = skb_recv_datagram(sk, (flags & O_NONBLOCK) ? MSG_DONTWAIT : 0, +- &err); ++ skb = skb_recv_datagram(sk, (arg->flags & O_NONBLOCK) ? MSG_DONTWAIT : 0, ++ &arg->err); + if (!skb) { + /* This means receive shutdown. */ +- if (err == 0) +- err = -EINVAL; ++ if (arg->err == 0) ++ arg->err = -EINVAL; + goto out; + } + +@@ -1737,7 +1736,7 @@ static int unix_accept(struct socket *sock, struct socket *newsock, int flags, + return 0; + + out: +- return err; ++ return arg->err; + } + + +diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c +index 54ba7316f8085..4b040285aa78c 100644 +--- a/net/vmw_vsock/af_vsock.c ++++ b/net/vmw_vsock/af_vsock.c +@@ -1500,8 +1500,8 @@ static int vsock_connect(struct socket *sock, struct sockaddr *addr, + return err; + } + +-static int vsock_accept(struct socket *sock, struct socket *newsock, int flags, +- bool kern) ++static int vsock_accept(struct socket *sock, struct socket *newsock, ++ struct proto_accept_arg *arg) + { + struct sock *listener; + int err; +@@ -1528,7 +1528,7 @@ static int vsock_accept(struct socket *sock, struct socket *newsock, int flags, + /* Wait for children sockets to appear; these are the new sockets + * created upon connection establishment. + */ +- timeout = sock_rcvtimeo(listener, flags & O_NONBLOCK); ++ timeout = sock_rcvtimeo(listener, arg->flags & O_NONBLOCK); + prepare_to_wait(sk_sleep(listener), &wait, TASK_INTERRUPTIBLE); + + while ((connected = vsock_dequeue_accept(listener)) == NULL && +diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c +index d18d51412cc00..8dda4178497c9 100644 +--- a/net/x25/af_x25.c ++++ b/net/x25/af_x25.c +@@ -871,8 +871,8 @@ static int x25_wait_for_data(struct sock *sk, long timeout) + return rc; + } + +-static int x25_accept(struct socket *sock, struct socket *newsock, int flags, +- bool kern) ++static int x25_accept(struct socket *sock, struct socket *newsock, ++ struct proto_accept_arg *arg) + { + struct sock *sk = sock->sk; + struct sock *newsk; +-- +2.43.0 + diff --git a/queue-6.9/net-dsa-qca8k-fix-usages-of-device_get_named_child_n.patch b/queue-6.9/net-dsa-qca8k-fix-usages-of-device_get_named_child_n.patch new file mode 100644 index 00000000000..aec72ecf6c6 --- /dev/null +++ b/queue-6.9/net-dsa-qca8k-fix-usages-of-device_get_named_child_n.patch @@ -0,0 +1,71 @@ +From ad65651f09cf975a16848788eb6cab843a7c46bb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Jun 2024 19:13:03 +0300 +Subject: net dsa: qca8k: fix usages of device_get_named_child_node() + +From: Andy Shevchenko + +[ Upstream commit d029edefed39647c797c2710aedd9d31f84c069e ] + +The documentation for device_get_named_child_node() mentions this +important point: + +" +The caller is responsible for calling fwnode_handle_put() on the +returned fwnode pointer. +" + +Add fwnode_handle_put() to avoid leaked references. + +Fixes: 1e264f9d2918 ("net: dsa: qca8k: add LEDs basic support") +Reviewed-by: Simon Horman +Signed-off-by: Andy Shevchenko +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/dsa/qca/qca8k-leds.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/dsa/qca/qca8k-leds.c b/drivers/net/dsa/qca/qca8k-leds.c +index 811ebeeff4ed7..43ac68052baf9 100644 +--- a/drivers/net/dsa/qca/qca8k-leds.c ++++ b/drivers/net/dsa/qca/qca8k-leds.c +@@ -431,8 +431,11 @@ qca8k_parse_port_leds(struct qca8k_priv *priv, struct fwnode_handle *port, int p + init_data.devicename = kasprintf(GFP_KERNEL, "%s:0%d", + priv->internal_mdio_bus->id, + port_num); +- if (!init_data.devicename) ++ if (!init_data.devicename) { ++ fwnode_handle_put(led); ++ fwnode_handle_put(leds); + return -ENOMEM; ++ } + + ret = devm_led_classdev_register_ext(priv->dev, &port_led->cdev, &init_data); + if (ret) +@@ -441,6 +444,7 @@ qca8k_parse_port_leds(struct qca8k_priv *priv, struct fwnode_handle *port, int p + kfree(init_data.devicename); + } + ++ fwnode_handle_put(leds); + return 0; + } + +@@ -471,9 +475,13 @@ qca8k_setup_led_ctrl(struct qca8k_priv *priv) + * the correct port for LED setup. + */ + ret = qca8k_parse_port_leds(priv, port, qca8k_port_to_phy(port_num)); +- if (ret) ++ if (ret) { ++ fwnode_handle_put(port); ++ fwnode_handle_put(ports); + return ret; ++ } + } + ++ fwnode_handle_put(ports); + return 0; + } +-- +2.43.0 + diff --git a/queue-6.9/net-hns3-add-cond_resched-to-hns3-ring-buffer-init-p.patch b/queue-6.9/net-hns3-add-cond_resched-to-hns3-ring-buffer-init-p.patch new file mode 100644 index 00000000000..2d95908a004 --- /dev/null +++ b/queue-6.9/net-hns3-add-cond_resched-to-hns3-ring-buffer-init-p.patch @@ -0,0 +1,64 @@ +From a94f7e2f03649360ea46870da0caf1df2599f589 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Jun 2024 15:20:58 +0800 +Subject: net: hns3: add cond_resched() to hns3 ring buffer init process + +From: Jie Wang + +[ Upstream commit 968fde83841a8c23558dfbd0a0c69d636db52b55 ] + +Currently hns3 ring buffer init process would hold cpu too long with big +Tx/Rx ring depth. This could cause soft lockup. + +So this patch adds cond_resched() to the process. Then cpu can break to +run other tasks instead of busy looping. + +Fixes: a723fb8efe29 ("net: hns3: refine for set ring parameters") +Signed-off-by: Jie Wang +Signed-off-by: Jijie Shao +Reviewed-by: Simon Horman +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 4 ++++ + drivers/net/ethernet/hisilicon/hns3/hns3_enet.h | 2 ++ + 2 files changed, 6 insertions(+) + +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +index 19668a8d22f76..c9258b1b2b429 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +@@ -3539,6 +3539,9 @@ static int hns3_alloc_ring_buffers(struct hns3_enet_ring *ring) + ret = hns3_alloc_and_attach_buffer(ring, i); + if (ret) + goto out_buffer_fail; ++ ++ if (!(i % HNS3_RESCHED_BD_NUM)) ++ cond_resched(); + } + + return 0; +@@ -5111,6 +5114,7 @@ int hns3_init_all_ring(struct hns3_nic_priv *priv) + } + + u64_stats_init(&priv->ring[i].syncp); ++ cond_resched(); + } + + return 0; +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h +index acd756b0c7c9a..d36c4ed16d8dd 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h +@@ -214,6 +214,8 @@ enum hns3_nic_state { + #define HNS3_CQ_MODE_EQE 1U + #define HNS3_CQ_MODE_CQE 0U + ++#define HNS3_RESCHED_BD_NUM 1024 ++ + enum hns3_pkt_l2t_type { + HNS3_L2_TYPE_UNICAST, + HNS3_L2_TYPE_MULTICAST, +-- +2.43.0 + diff --git a/queue-6.9/net-hns3-fix-kernel-crash-problem-in-concurrent-scen.patch b/queue-6.9/net-hns3-fix-kernel-crash-problem-in-concurrent-scen.patch new file mode 100644 index 00000000000..8cc7bb54b84 --- /dev/null +++ b/queue-6.9/net-hns3-fix-kernel-crash-problem-in-concurrent-scen.patch @@ -0,0 +1,84 @@ +From 2a723763f3d842fc550fdd3311ef39d85a98eb11 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Jun 2024 15:20:57 +0800 +Subject: net: hns3: fix kernel crash problem in concurrent scenario + +From: Yonglong Liu + +[ Upstream commit 12cda920212a49fa22d9e8b9492ac4ea013310a4 ] + +When link status change, the nic driver need to notify the roce +driver to handle this event, but at this time, the roce driver +may uninit, then cause kernel crash. + +To fix the problem, when link status change, need to check +whether the roce registered, and when uninit, need to wait link +update finish. + +Fixes: 45e92b7e4e27 ("net: hns3: add calling roce callback function when link status change") +Signed-off-by: Yonglong Liu +Signed-off-by: Jijie Shao +Reviewed-by: Simon Horman +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + .../hisilicon/hns3/hns3pf/hclge_main.c | 21 ++++++++++++++----- + 1 file changed, 16 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +index ce60332d83c39..990d7bd397aa8 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +@@ -3042,9 +3042,7 @@ static void hclge_push_link_status(struct hclge_dev *hdev) + + static void hclge_update_link_status(struct hclge_dev *hdev) + { +- struct hnae3_handle *rhandle = &hdev->vport[0].roce; + struct hnae3_handle *handle = &hdev->vport[0].nic; +- struct hnae3_client *rclient = hdev->roce_client; + struct hnae3_client *client = hdev->nic_client; + int state; + int ret; +@@ -3068,8 +3066,15 @@ static void hclge_update_link_status(struct hclge_dev *hdev) + + client->ops->link_status_change(handle, state); + hclge_config_mac_tnl_int(hdev, state); +- if (rclient && rclient->ops->link_status_change) +- rclient->ops->link_status_change(rhandle, state); ++ ++ if (test_bit(HCLGE_STATE_ROCE_REGISTERED, &hdev->state)) { ++ struct hnae3_handle *rhandle = &hdev->vport[0].roce; ++ struct hnae3_client *rclient = hdev->roce_client; ++ ++ if (rclient && rclient->ops->link_status_change) ++ rclient->ops->link_status_change(rhandle, ++ state); ++ } + + hclge_push_link_status(hdev); + } +@@ -11245,6 +11250,12 @@ static int hclge_init_client_instance(struct hnae3_client *client, + return ret; + } + ++static bool hclge_uninit_need_wait(struct hclge_dev *hdev) ++{ ++ return test_bit(HCLGE_STATE_RST_HANDLING, &hdev->state) || ++ test_bit(HCLGE_STATE_LINK_UPDATING, &hdev->state); ++} ++ + static void hclge_uninit_client_instance(struct hnae3_client *client, + struct hnae3_ae_dev *ae_dev) + { +@@ -11253,7 +11264,7 @@ static void hclge_uninit_client_instance(struct hnae3_client *client, + + if (hdev->roce_client) { + clear_bit(HCLGE_STATE_ROCE_REGISTERED, &hdev->state); +- while (test_bit(HCLGE_STATE_RST_HANDLING, &hdev->state)) ++ while (hclge_uninit_need_wait(hdev)) + msleep(HCLGE_WAIT_RESET_DONE); + + hdev->roce_client->ops->uninit_instance(&vport->roce, 0); +-- +2.43.0 + diff --git a/queue-6.9/net-ipv6-fix-the-rt-cache-flush-via-sysctl-using-a-p.patch b/queue-6.9/net-ipv6-fix-the-rt-cache-flush-via-sysctl-using-a-p.patch new file mode 100644 index 00000000000..7f6b7980e35 --- /dev/null +++ b/queue-6.9/net-ipv6-fix-the-rt-cache-flush-via-sysctl-using-a-p.patch @@ -0,0 +1,53 @@ +From 17250040645f0b21b7497980e7eae5aca4a6c3b2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Jun 2024 13:28:28 +0200 +Subject: net/ipv6: Fix the RT cache flush via sysctl using a previous delay + +From: Petr Pavlu + +[ Upstream commit 14a20e5b4ad998793c5f43b0330d9e1388446cf3 ] + +The net.ipv6.route.flush system parameter takes a value which specifies +a delay used during the flush operation for aging exception routes. The +written value is however not used in the currently requested flush and +instead utilized only in the next one. + +A problem is that ipv6_sysctl_rtcache_flush() first reads the old value +of net->ipv6.sysctl.flush_delay into a local delay variable and then +calls proc_dointvec() which actually updates the sysctl based on the +provided input. + +Fix the problem by switching the order of the two operations. + +Fixes: 4990509f19e8 ("[NETNS][IPV6]: Make sysctls route per namespace.") +Signed-off-by: Petr Pavlu +Reviewed-by: David Ahern +Link: https://lore.kernel.org/r/20240607112828.30285-1-petr.pavlu@suse.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv6/route.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/net/ipv6/route.c b/net/ipv6/route.c +index bca6f33c7bb9e..8f8c8fcfd1c21 100644 +--- a/net/ipv6/route.c ++++ b/net/ipv6/route.c +@@ -6343,12 +6343,12 @@ static int ipv6_sysctl_rtcache_flush(struct ctl_table *ctl, int write, + if (!write) + return -EINVAL; + +- net = (struct net *)ctl->extra1; +- delay = net->ipv6.sysctl.flush_delay; + ret = proc_dointvec(ctl, write, buffer, lenp, ppos); + if (ret) + return ret; + ++ net = (struct net *)ctl->extra1; ++ delay = net->ipv6.sysctl.flush_delay; + fib6_run_gc(delay <= 0 ? 0 : (unsigned long)delay, net, delay > 0); + return 0; + } +-- +2.43.0 + diff --git a/queue-6.9/net-mlx5e-fix-features-validation-check-for-tunneled.patch b/queue-6.9/net-mlx5e-fix-features-validation-check-for-tunneled.patch new file mode 100644 index 00000000000..80baecf99a6 --- /dev/null +++ b/queue-6.9/net-mlx5e-fix-features-validation-check-for-tunneled.patch @@ -0,0 +1,53 @@ +From 6eba7207ca4d1d6bcc45e07c42d560ca93c9bb45 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Jun 2024 23:32:49 +0300 +Subject: net/mlx5e: Fix features validation check for tunneled UDP (non-VXLAN) + packets + +From: Gal Pressman + +[ Upstream commit 791b4089e326271424b78f2fae778b20e53d071b ] + +Move the vxlan_features_check() call to after we verified the packet is +a tunneled VXLAN packet. + +Without this, tunneled UDP non-VXLAN packets (for ex. GENENVE) might +wrongly not get offloaded. +In some cases, it worked by chance as GENEVE header is the same size as +VXLAN, but it is obviously incorrect. + +Fixes: e3cfc7e6b7bd ("net/mlx5e: TX, Add geneve tunnel stateless offload support") +Signed-off-by: Gal Pressman +Reviewed-by: Dragos Tatulea +Signed-off-by: Tariq Toukan +Reviewed-by: Wojciech Drewek +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +index 47be07af214ff..981a3e058840d 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +@@ -4738,7 +4738,7 @@ static netdev_features_t mlx5e_tunnel_features_check(struct mlx5e_priv *priv, + + /* Verify if UDP port is being offloaded by HW */ + if (mlx5_vxlan_lookup_port(priv->mdev->vxlan, port)) +- return features; ++ return vxlan_features_check(skb, features); + + #if IS_ENABLED(CONFIG_GENEVE) + /* Support Geneve offload for default UDP port */ +@@ -4764,7 +4764,6 @@ netdev_features_t mlx5e_features_check(struct sk_buff *skb, + struct mlx5e_priv *priv = netdev_priv(netdev); + + features = vlan_features_check(skb, features); +- features = vxlan_features_check(skb, features); + + /* Validate if the tunneled packet is being offloaded by HW */ + if (skb->encapsulation && +-- +2.43.0 + diff --git a/queue-6.9/net-pse-pd-use-eopnotsupp-error-code-instead-of-enot.patch b/queue-6.9/net-pse-pd-use-eopnotsupp-error-code-instead-of-enot.patch new file mode 100644 index 00000000000..fdf78b49398 --- /dev/null +++ b/queue-6.9/net-pse-pd-use-eopnotsupp-error-code-instead-of-enot.patch @@ -0,0 +1,47 @@ +From d91c34fd3a89ce68caa7733d0847085d510c7d22 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Jun 2024 10:34:26 +0200 +Subject: net: pse-pd: Use EOPNOTSUPP error code instead of ENOTSUPP + +From: Kory Maincent + +[ Upstream commit 144ba8580bcb82b2686c3d1a043299d844b9a682 ] + +ENOTSUPP is not a SUSV4 error code, prefer EOPNOTSUPP as reported by +checkpatch script. + +Fixes: 18ff0bcda6d1 ("ethtool: add interface to interact with Ethernet Power Equipment") +Reviewed-by: Andrew Lunn +Acked-by: Oleksij Rempel +Signed-off-by: Kory Maincent +Link: https://lore.kernel.org/r/20240610083426.740660-1-kory.maincent@bootlin.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + include/linux/pse-pd/pse.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/include/linux/pse-pd/pse.h b/include/linux/pse-pd/pse.h +index fb724c65c77bc..5ce0cd76956e0 100644 +--- a/include/linux/pse-pd/pse.h ++++ b/include/linux/pse-pd/pse.h +@@ -114,14 +114,14 @@ static inline int pse_ethtool_get_status(struct pse_control *psec, + struct netlink_ext_ack *extack, + struct pse_control_status *status) + { +- return -ENOTSUPP; ++ return -EOPNOTSUPP; + } + + static inline int pse_ethtool_set_config(struct pse_control *psec, + struct netlink_ext_ack *extack, + const struct pse_control_config *config) + { +- return -ENOTSUPP; ++ return -EOPNOTSUPP; + } + + #endif +-- +2.43.0 + diff --git a/queue-6.9/net-sched-initialize-noop_qdisc-owner.patch b/queue-6.9/net-sched-initialize-noop_qdisc-owner.patch new file mode 100644 index 00000000000..c8096ad9d8d --- /dev/null +++ b/queue-6.9/net-sched-initialize-noop_qdisc-owner.patch @@ -0,0 +1,45 @@ +From ec77e942ffcdd43d0986324ce6bd49273bdbeb5a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Jun 2024 17:53:32 +0200 +Subject: net/sched: initialize noop_qdisc owner + +From: Johannes Berg + +[ Upstream commit 44180feaccf266d9b0b28cc4ceaac019817deb5c ] + +When the noop_qdisc owner isn't initialized, then it will be 0, +so packets will erroneously be regarded as having been subject +to recursion as long as only CPU 0 queues them. For non-SMP, +that's all packets, of course. This causes a change in what's +reported to userspace, normally noop_qdisc would drop packets +silently, but with this change the syscall returns -ENOBUFS if +RECVERR is also set on the socket. + +Fix this by initializing the owner field to -1, just like it +would be for dynamically allocated qdiscs by qdisc_alloc(). + +Fixes: 0f022d32c3ec ("net/sched: Fix mirred deadlock on device recursion") +Signed-off-by: Johannes Berg +Reviewed-by: Eric Dumazet +Link: https://lore.kernel.org/r/20240607175340.786bfb938803.I493bf8422e36be4454c08880a8d3703cea8e421a@changeid +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sched/sch_generic.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c +index 4a2c763e2d116..10b1491d55809 100644 +--- a/net/sched/sch_generic.c ++++ b/net/sched/sch_generic.c +@@ -673,6 +673,7 @@ struct Qdisc noop_qdisc = { + .qlen = 0, + .lock = __SPIN_LOCK_UNLOCKED(noop_qdisc.skb_bad_txq.lock), + }, ++ .owner = -1, + }; + EXPORT_SYMBOL(noop_qdisc); + +-- +2.43.0 + diff --git a/queue-6.9/net-sfp-always-call-sfp_sm_mod_remove-on-remove.patch b/queue-6.9/net-sfp-always-call-sfp_sm_mod_remove-on-remove.patch new file mode 100644 index 00000000000..cf3b8e1713b --- /dev/null +++ b/queue-6.9/net-sfp-always-call-sfp_sm_mod_remove-on-remove.patch @@ -0,0 +1,45 @@ +From 62339bd032bb4f2723e9b5e95b99dd14bb223519 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Jun 2024 10:42:51 +0200 +Subject: net: sfp: Always call `sfp_sm_mod_remove()` on remove +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Csókás, Bence + +[ Upstream commit e96b2933152fd87b6a41765b2f58b158fde855b6 ] + +If the module is in SFP_MOD_ERROR, `sfp_sm_mod_remove()` will +not be run. As a consequence, `sfp_hwmon_remove()` is not getting +run either, leaving a stale `hwmon` device behind. `sfp_sm_mod_remove()` +itself checks `sfp->sm_mod_state` anyways, so this check was not +really needed in the first place. + +Fixes: d2e816c0293f ("net: sfp: handle module remove outside state machine") +Signed-off-by: "Csókás, Bence" +Reviewed-by: Andrew Lunn +Link: https://lore.kernel.org/r/20240605084251.63502-1-csokas.bence@prolan.hu +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/phy/sfp.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c +index f75c9eb3958ef..d999d9baadb26 100644 +--- a/drivers/net/phy/sfp.c ++++ b/drivers/net/phy/sfp.c +@@ -2418,8 +2418,7 @@ static void sfp_sm_module(struct sfp *sfp, unsigned int event) + + /* Handle remove event globally, it resets this state machine */ + if (event == SFP_E_REMOVE) { +- if (sfp->sm_mod_state > SFP_MOD_PROBE) +- sfp_sm_mod_remove(sfp); ++ sfp_sm_mod_remove(sfp); + sfp_sm_mod_next(sfp, SFP_MOD_EMPTY, 0); + return; + } +-- +2.43.0 + diff --git a/queue-6.9/net-stmmac-dwmac-qcom-ethqos-configure-host-dma-widt.patch b/queue-6.9/net-stmmac-dwmac-qcom-ethqos-configure-host-dma-widt.patch new file mode 100644 index 00000000000..705a9626c1e --- /dev/null +++ b/queue-6.9/net-stmmac-dwmac-qcom-ethqos-configure-host-dma-widt.patch @@ -0,0 +1,64 @@ +From 774a39b09566d6f83fa81dbaa32a15c87dce6690 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Jun 2024 11:57:18 -0700 +Subject: net: stmmac: dwmac-qcom-ethqos: Configure host DMA width + +From: Sagar Cheluvegowda + +[ Upstream commit 0579f27249047006a818e463ee66a6c314d04cea ] + +Commit 070246e4674b ("net: stmmac: Fix for mismatched host/device DMA +address width") added support in the stmmac driver for platform drivers +to indicate the host DMA width, but left it up to authors of the +specific platforms to indicate if their width differed from the addr64 +register read from the MAC itself. + +Qualcomm's EMAC4 integration supports only up to 36 bit width (as +opposed to the addr64 register indicating 40 bit width). Let's indicate +that in the platform driver to avoid a scenario where the driver will +allocate descriptors of size that is supported by the CPU which in our +case is 36 bit, but as the addr64 register is still capable of 40 bits +the device will use two descriptors as one address. + +Fixes: 8c4d92e82d50 ("net: stmmac: dwmac-qcom-ethqos: add support for emac4 on sa8775p platforms") +Signed-off-by: Sagar Cheluvegowda +Reviewed-by: Simon Horman +Reviewed-by: Andrew Halaney +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +index e254b21fdb598..65d7370b47d57 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +@@ -93,6 +93,7 @@ struct ethqos_emac_driver_data { + bool has_emac_ge_3; + const char *link_clk_name; + bool has_integrated_pcs; ++ u32 dma_addr_width; + struct dwmac4_addrs dwmac4_addrs; + }; + +@@ -276,6 +277,7 @@ static const struct ethqos_emac_driver_data emac_v4_0_0_data = { + .has_emac_ge_3 = true, + .link_clk_name = "phyaux", + .has_integrated_pcs = true, ++ .dma_addr_width = 36, + .dwmac4_addrs = { + .dma_chan = 0x00008100, + .dma_chan_offset = 0x1000, +@@ -845,6 +847,8 @@ static int qcom_ethqos_probe(struct platform_device *pdev) + plat_dat->flags |= STMMAC_FLAG_RX_CLK_RUNS_IN_LPI; + if (data->has_integrated_pcs) + plat_dat->flags |= STMMAC_FLAG_HAS_INTEGRATED_PCS; ++ if (data->dma_addr_width) ++ plat_dat->host_dma_width = data->dma_addr_width; + + if (ethqos->serdes_phy) { + plat_dat->serdes_powerup = qcom_ethqos_serdes_powerup; +-- +2.43.0 + diff --git a/queue-6.9/net-stmmac-replace-priv-speed-with-the-porttransmitr.patch b/queue-6.9/net-stmmac-replace-priv-speed-with-the-porttransmitr.patch new file mode 100644 index 00000000000..b3a450e559f --- /dev/null +++ b/queue-6.9/net-stmmac-replace-priv-speed-with-the-porttransmitr.patch @@ -0,0 +1,101 @@ +From 9cc12d10bf08b98a8b54cb495d5a86db8bc85021 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 8 Jun 2024 22:35:24 +0800 +Subject: net: stmmac: replace priv->speed with the portTransmitRate from the + tc-cbs parameters + +From: Xiaolei Wang + +[ Upstream commit be27b896529787e23a35ae4befb6337ce73fcca0 ] + +The current cbs parameter depends on speed after uplinking, +which is not needed and will report a configuration error +if the port is not initially connected. The UAPI exposed by +tc-cbs requires userspace to recalculate the send slope anyway, +because the formula depends on port_transmit_rate (see man tc-cbs), +which is not an invariant from tc's perspective. Therefore, we +use offload->sendslope and offload->idleslope to derive the +original port_transmit_rate from the CBS formula. + +Fixes: 1f705bc61aee ("net: stmmac: Add support for CBS QDISC") +Signed-off-by: Xiaolei Wang +Reviewed-by: Wojciech Drewek +Reviewed-by: Vladimir Oltean +Link: https://lore.kernel.org/r/20240608143524.2065736-1-xiaolei.wang@windriver.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + .../net/ethernet/stmicro/stmmac/stmmac_tc.c | 25 ++++++++----------- + 1 file changed, 11 insertions(+), 14 deletions(-) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c +index 620c16e9be3a6..b1896379dbab5 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c +@@ -343,10 +343,11 @@ static int tc_setup_cbs(struct stmmac_priv *priv, + struct tc_cbs_qopt_offload *qopt) + { + u32 tx_queues_count = priv->plat->tx_queues_to_use; ++ s64 port_transmit_rate_kbps; + u32 queue = qopt->queue; +- u32 ptr, speed_div; + u32 mode_to_use; + u64 value; ++ u32 ptr; + int ret; + + /* Queue 0 is not AVB capable */ +@@ -355,30 +356,26 @@ static int tc_setup_cbs(struct stmmac_priv *priv, + if (!priv->dma_cap.av) + return -EOPNOTSUPP; + ++ port_transmit_rate_kbps = qopt->idleslope - qopt->sendslope; ++ + /* Port Transmit Rate and Speed Divider */ +- switch (priv->speed) { ++ switch (div_s64(port_transmit_rate_kbps, 1000)) { + case SPEED_10000: +- ptr = 32; +- speed_div = 10000000; +- break; + case SPEED_5000: + ptr = 32; +- speed_div = 5000000; + break; + case SPEED_2500: +- ptr = 8; +- speed_div = 2500000; +- break; + case SPEED_1000: + ptr = 8; +- speed_div = 1000000; + break; + case SPEED_100: + ptr = 4; +- speed_div = 100000; + break; + default: +- return -EOPNOTSUPP; ++ netdev_err(priv->dev, ++ "Invalid portTransmitRate %lld (idleSlope - sendSlope)\n", ++ port_transmit_rate_kbps); ++ return -EINVAL; + } + + mode_to_use = priv->plat->tx_queues_cfg[queue].mode_to_use; +@@ -398,10 +395,10 @@ static int tc_setup_cbs(struct stmmac_priv *priv, + } + + /* Final adjustments for HW */ +- value = div_s64(qopt->idleslope * 1024ll * ptr, speed_div); ++ value = div_s64(qopt->idleslope * 1024ll * ptr, port_transmit_rate_kbps); + priv->plat->tx_queues_cfg[queue].idle_slope = value & GENMASK(31, 0); + +- value = div_s64(-qopt->sendslope * 1024ll * ptr, speed_div); ++ value = div_s64(-qopt->sendslope * 1024ll * ptr, port_transmit_rate_kbps); + priv->plat->tx_queues_cfg[queue].send_slope = value & GENMASK(31, 0); + + value = qopt->hicredit * 1024ll * 8; +-- +2.43.0 + diff --git a/queue-6.9/netdevsim-fix-backwards-compatibility-in-nsim_get_if.patch b/queue-6.9/netdevsim-fix-backwards-compatibility-in-nsim_get_if.patch new file mode 100644 index 00000000000..ac1d68ca04b --- /dev/null +++ b/queue-6.9/netdevsim-fix-backwards-compatibility-in-nsim_get_if.patch @@ -0,0 +1,44 @@ +From acbabb076235e40aa7b36542eb70c41f05393c2e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Jun 2024 07:59:08 -0700 +Subject: netdevsim: fix backwards compatibility in nsim_get_iflink() + +From: David Wei + +[ Upstream commit 5add2f7288468f35a374620dabf126c13baaea9c ] + +The default ndo_get_iflink() implementation returns the current ifindex +of the netdev. But the overridden nsim_get_iflink() returns 0 if the +current nsim is not linked, breaking backwards compatibility for +userspace that depend on this behaviour. + +Fix the problem by returning the current ifindex if not linked to a +peer. + +Fixes: 8debcf5832c3 ("netdevsim: add ndo_get_iflink() implementation") +Reported-by: Yu Watanabe +Suggested-by: Yu Watanabe +Signed-off-by: David Wei +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/netdevsim/netdev.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c +index 8330bc0bcb7e5..d405809030aab 100644 +--- a/drivers/net/netdevsim/netdev.c ++++ b/drivers/net/netdevsim/netdev.c +@@ -292,7 +292,8 @@ static int nsim_get_iflink(const struct net_device *dev) + + rcu_read_lock(); + peer = rcu_dereference(nsim->peer); +- iflink = peer ? READ_ONCE(peer->netdev->ifindex) : 0; ++ iflink = peer ? READ_ONCE(peer->netdev->ifindex) : ++ READ_ONCE(dev->ifindex); + rcu_read_unlock(); + + return iflink; +-- +2.43.0 + diff --git a/queue-6.9/netfilter-ipset-fix-race-between-namespace-cleanup-a.patch b/queue-6.9/netfilter-ipset-fix-race-between-namespace-cleanup-a.patch new file mode 100644 index 00000000000..45c98d220c1 --- /dev/null +++ b/queue-6.9/netfilter-ipset-fix-race-between-namespace-cleanup-a.patch @@ -0,0 +1,289 @@ +From c93a9ac4a5e09f694873b3abca7eb42c93f34220 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Jun 2024 15:58:03 +0200 +Subject: netfilter: ipset: Fix race between namespace cleanup and gc in the + list:set type + +From: Jozsef Kadlecsik + +[ Upstream commit 4e7aaa6b82d63e8ddcbfb56b4fd3d014ca586f10 ] + +Lion Ackermann reported that there is a race condition between namespace cleanup +in ipset and the garbage collection of the list:set type. The namespace +cleanup can destroy the list:set type of sets while the gc of the set type is +waiting to run in rcu cleanup. The latter uses data from the destroyed set which +thus leads use after free. The patch contains the following parts: + +- When destroying all sets, first remove the garbage collectors, then wait + if needed and then destroy the sets. +- Fix the badly ordered "wait then remove gc" for the destroy a single set + case. +- Fix the missing rcu locking in the list:set type in the userspace test + case. +- Use proper RCU list handlings in the list:set type. + +The patch depends on c1193d9bbbd3 (netfilter: ipset: Add list flush to cancel_gc). + +Fixes: 97f7cf1cd80e (netfilter: ipset: fix performance regression in swap operation) +Reported-by: Lion Ackermann +Tested-by: Lion Ackermann +Signed-off-by: Jozsef Kadlecsik +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/netfilter/ipset/ip_set_core.c | 81 +++++++++++++++------------ + net/netfilter/ipset/ip_set_list_set.c | 30 +++++----- + 2 files changed, 60 insertions(+), 51 deletions(-) + +diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c +index 3184cc6be4c9d..c7ae4d9bf3d24 100644 +--- a/net/netfilter/ipset/ip_set_core.c ++++ b/net/netfilter/ipset/ip_set_core.c +@@ -1172,23 +1172,50 @@ ip_set_setname_policy[IPSET_ATTR_CMD_MAX + 1] = { + .len = IPSET_MAXNAMELEN - 1 }, + }; + ++/* In order to return quickly when destroying a single set, it is split ++ * into two stages: ++ * - Cancel garbage collector ++ * - Destroy the set itself via call_rcu() ++ */ ++ + static void +-ip_set_destroy_set(struct ip_set *set) ++ip_set_destroy_set_rcu(struct rcu_head *head) + { +- pr_debug("set: %s\n", set->name); ++ struct ip_set *set = container_of(head, struct ip_set, rcu); + +- /* Must call it without holding any lock */ + set->variant->destroy(set); + module_put(set->type->me); + kfree(set); + } + + static void +-ip_set_destroy_set_rcu(struct rcu_head *head) ++_destroy_all_sets(struct ip_set_net *inst) + { +- struct ip_set *set = container_of(head, struct ip_set, rcu); ++ struct ip_set *set; ++ ip_set_id_t i; ++ bool need_wait = false; + +- ip_set_destroy_set(set); ++ /* First cancel gc's: set:list sets are flushed as well */ ++ for (i = 0; i < inst->ip_set_max; i++) { ++ set = ip_set(inst, i); ++ if (set) { ++ set->variant->cancel_gc(set); ++ if (set->type->features & IPSET_TYPE_NAME) ++ need_wait = true; ++ } ++ } ++ /* Must wait for flush to be really finished */ ++ if (need_wait) ++ rcu_barrier(); ++ for (i = 0; i < inst->ip_set_max; i++) { ++ set = ip_set(inst, i); ++ if (set) { ++ ip_set(inst, i) = NULL; ++ set->variant->destroy(set); ++ module_put(set->type->me); ++ kfree(set); ++ } ++ } + } + + static int ip_set_destroy(struct sk_buff *skb, const struct nfnl_info *info, +@@ -1202,11 +1229,10 @@ static int ip_set_destroy(struct sk_buff *skb, const struct nfnl_info *info, + if (unlikely(protocol_min_failed(attr))) + return -IPSET_ERR_PROTOCOL; + +- + /* Commands are serialized and references are + * protected by the ip_set_ref_lock. + * External systems (i.e. xt_set) must call +- * ip_set_put|get_nfnl_* functions, that way we ++ * ip_set_nfnl_get_* functions, that way we + * can safely check references here. + * + * list:set timer can only decrement the reference +@@ -1214,8 +1240,6 @@ static int ip_set_destroy(struct sk_buff *skb, const struct nfnl_info *info, + * without holding the lock. + */ + if (!attr[IPSET_ATTR_SETNAME]) { +- /* Must wait for flush to be really finished in list:set */ +- rcu_barrier(); + read_lock_bh(&ip_set_ref_lock); + for (i = 0; i < inst->ip_set_max; i++) { + s = ip_set(inst, i); +@@ -1226,15 +1250,7 @@ static int ip_set_destroy(struct sk_buff *skb, const struct nfnl_info *info, + } + inst->is_destroyed = true; + read_unlock_bh(&ip_set_ref_lock); +- for (i = 0; i < inst->ip_set_max; i++) { +- s = ip_set(inst, i); +- if (s) { +- ip_set(inst, i) = NULL; +- /* Must cancel garbage collectors */ +- s->variant->cancel_gc(s); +- ip_set_destroy_set(s); +- } +- } ++ _destroy_all_sets(inst); + /* Modified by ip_set_destroy() only, which is serialized */ + inst->is_destroyed = false; + } else { +@@ -1255,12 +1271,12 @@ static int ip_set_destroy(struct sk_buff *skb, const struct nfnl_info *info, + features = s->type->features; + ip_set(inst, i) = NULL; + read_unlock_bh(&ip_set_ref_lock); ++ /* Must cancel garbage collectors */ ++ s->variant->cancel_gc(s); + if (features & IPSET_TYPE_NAME) { + /* Must wait for flush to be really finished */ + rcu_barrier(); + } +- /* Must cancel garbage collectors */ +- s->variant->cancel_gc(s); + call_rcu(&s->rcu, ip_set_destroy_set_rcu); + } + return 0; +@@ -2365,30 +2381,25 @@ ip_set_net_init(struct net *net) + } + + static void __net_exit +-ip_set_net_exit(struct net *net) ++ip_set_net_pre_exit(struct net *net) + { + struct ip_set_net *inst = ip_set_pernet(net); + +- struct ip_set *set = NULL; +- ip_set_id_t i; +- + inst->is_deleted = true; /* flag for ip_set_nfnl_put */ ++} + +- nfnl_lock(NFNL_SUBSYS_IPSET); +- for (i = 0; i < inst->ip_set_max; i++) { +- set = ip_set(inst, i); +- if (set) { +- ip_set(inst, i) = NULL; +- set->variant->cancel_gc(set); +- ip_set_destroy_set(set); +- } +- } +- nfnl_unlock(NFNL_SUBSYS_IPSET); ++static void __net_exit ++ip_set_net_exit(struct net *net) ++{ ++ struct ip_set_net *inst = ip_set_pernet(net); ++ ++ _destroy_all_sets(inst); + kvfree(rcu_dereference_protected(inst->ip_set_list, 1)); + } + + static struct pernet_operations ip_set_net_ops = { + .init = ip_set_net_init, ++ .pre_exit = ip_set_net_pre_exit, + .exit = ip_set_net_exit, + .id = &ip_set_net_id, + .size = sizeof(struct ip_set_net), +diff --git a/net/netfilter/ipset/ip_set_list_set.c b/net/netfilter/ipset/ip_set_list_set.c +index 54e2a1dd7f5f5..bfae7066936bb 100644 +--- a/net/netfilter/ipset/ip_set_list_set.c ++++ b/net/netfilter/ipset/ip_set_list_set.c +@@ -79,7 +79,7 @@ list_set_kadd(struct ip_set *set, const struct sk_buff *skb, + struct set_elem *e; + int ret; + +- list_for_each_entry(e, &map->members, list) { ++ list_for_each_entry_rcu(e, &map->members, list) { + if (SET_WITH_TIMEOUT(set) && + ip_set_timeout_expired(ext_timeout(e, set))) + continue; +@@ -99,7 +99,7 @@ list_set_kdel(struct ip_set *set, const struct sk_buff *skb, + struct set_elem *e; + int ret; + +- list_for_each_entry(e, &map->members, list) { ++ list_for_each_entry_rcu(e, &map->members, list) { + if (SET_WITH_TIMEOUT(set) && + ip_set_timeout_expired(ext_timeout(e, set))) + continue; +@@ -188,9 +188,10 @@ list_set_utest(struct ip_set *set, void *value, const struct ip_set_ext *ext, + struct list_set *map = set->data; + struct set_adt_elem *d = value; + struct set_elem *e, *next, *prev = NULL; +- int ret; ++ int ret = 0; + +- list_for_each_entry(e, &map->members, list) { ++ rcu_read_lock(); ++ list_for_each_entry_rcu(e, &map->members, list) { + if (SET_WITH_TIMEOUT(set) && + ip_set_timeout_expired(ext_timeout(e, set))) + continue; +@@ -201,6 +202,7 @@ list_set_utest(struct ip_set *set, void *value, const struct ip_set_ext *ext, + + if (d->before == 0) { + ret = 1; ++ goto out; + } else if (d->before > 0) { + next = list_next_entry(e, list); + ret = !list_is_last(&e->list, &map->members) && +@@ -208,9 +210,11 @@ list_set_utest(struct ip_set *set, void *value, const struct ip_set_ext *ext, + } else { + ret = prev && prev->id == d->refid; + } +- return ret; ++ goto out; + } +- return 0; ++out: ++ rcu_read_unlock(); ++ return ret; + } + + static void +@@ -239,7 +243,7 @@ list_set_uadd(struct ip_set *set, void *value, const struct ip_set_ext *ext, + + /* Find where to add the new entry */ + n = prev = next = NULL; +- list_for_each_entry(e, &map->members, list) { ++ list_for_each_entry_rcu(e, &map->members, list) { + if (SET_WITH_TIMEOUT(set) && + ip_set_timeout_expired(ext_timeout(e, set))) + continue; +@@ -316,9 +320,9 @@ list_set_udel(struct ip_set *set, void *value, const struct ip_set_ext *ext, + { + struct list_set *map = set->data; + struct set_adt_elem *d = value; +- struct set_elem *e, *next, *prev = NULL; ++ struct set_elem *e, *n, *next, *prev = NULL; + +- list_for_each_entry(e, &map->members, list) { ++ list_for_each_entry_safe(e, n, &map->members, list) { + if (SET_WITH_TIMEOUT(set) && + ip_set_timeout_expired(ext_timeout(e, set))) + continue; +@@ -424,14 +428,8 @@ static void + list_set_destroy(struct ip_set *set) + { + struct list_set *map = set->data; +- struct set_elem *e, *n; + +- list_for_each_entry_safe(e, n, &map->members, list) { +- list_del(&e->list); +- ip_set_put_byindex(map->net, e->id); +- ip_set_ext_destroy(set, e); +- kfree(e); +- } ++ WARN_ON_ONCE(!list_empty(&map->members)); + kfree(map); + + set->data = NULL; +-- +2.43.0 + diff --git a/queue-6.9/netfilter-nft_inner-validate-mandatory-meta-and-payl.patch b/queue-6.9/netfilter-nft_inner-validate-mandatory-meta-and-payl.patch new file mode 100644 index 00000000000..02145b64b8f --- /dev/null +++ b/queue-6.9/netfilter-nft_inner-validate-mandatory-meta-and-payl.patch @@ -0,0 +1,55 @@ +From 2d84bf4fbc5469ade24cb2bf4ea81f7e2576899b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 5 Jun 2024 13:03:45 +0200 +Subject: netfilter: nft_inner: validate mandatory meta and payload + +From: Davide Ornaghi + +[ Upstream commit c4ab9da85b9df3692f861512fe6c9812f38b7471 ] + +Check for mandatory netlink attributes in payload and meta expression +when used embedded from the inner expression, otherwise NULL pointer +dereference is possible from userspace. + +Fixes: a150d122b6bd ("netfilter: nft_meta: add inner match support") +Fixes: 3a07327d10a0 ("netfilter: nft_inner: support for inner tunnel header matching") +Signed-off-by: Davide Ornaghi +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/netfilter/nft_meta.c | 3 +++ + net/netfilter/nft_payload.c | 4 ++++ + 2 files changed, 7 insertions(+) + +diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c +index ba0d3683a45d3..9139ce38ea7b9 100644 +--- a/net/netfilter/nft_meta.c ++++ b/net/netfilter/nft_meta.c +@@ -839,6 +839,9 @@ static int nft_meta_inner_init(const struct nft_ctx *ctx, + struct nft_meta *priv = nft_expr_priv(expr); + unsigned int len; + ++ if (!tb[NFTA_META_KEY] || !tb[NFTA_META_DREG]) ++ return -EINVAL; ++ + priv->key = ntohl(nla_get_be32(tb[NFTA_META_KEY])); + switch (priv->key) { + case NFT_META_PROTOCOL: +diff --git a/net/netfilter/nft_payload.c b/net/netfilter/nft_payload.c +index 0c43d748e23ae..50429cbd42da4 100644 +--- a/net/netfilter/nft_payload.c ++++ b/net/netfilter/nft_payload.c +@@ -650,6 +650,10 @@ static int nft_payload_inner_init(const struct nft_ctx *ctx, + struct nft_payload *priv = nft_expr_priv(expr); + u32 base; + ++ if (!tb[NFTA_PAYLOAD_BASE] || !tb[NFTA_PAYLOAD_OFFSET] || ++ !tb[NFTA_PAYLOAD_LEN] || !tb[NFTA_PAYLOAD_DREG]) ++ return -EINVAL; ++ + base = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_BASE])); + switch (base) { + case NFT_PAYLOAD_TUN_HEADER: +-- +2.43.0 + diff --git a/queue-6.9/netfilter-use-flowlabel-flow-key-when-re-routing-man.patch b/queue-6.9/netfilter-use-flowlabel-flow-key-when-re-routing-man.patch new file mode 100644 index 00000000000..a1b43f0e1d8 --- /dev/null +++ b/queue-6.9/netfilter-use-flowlabel-flow-key-when-re-routing-man.patch @@ -0,0 +1,41 @@ +From 323ac0f0571f76d91b481ff8a0194b7149387786 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Jun 2024 12:23:31 +0200 +Subject: netfilter: Use flowlabel flow key when re-routing mangled packets + +From: Florian Westphal + +[ Upstream commit 6f8f132cc7bac2ac76911e47d5baa378aafda4cb ] + +'ip6 dscp set $v' in an nftables outpute route chain has no effect. +While nftables does detect the dscp change and calls the reroute hook. +But ip6_route_me_harder never sets the dscp/flowlabel: +flowlabel/dsfield routing rules are ignored and no reroute takes place. + +Thanks to Yi Chen for an excellent reproducer script that I used +to validate this change. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Reported-by: Yi Chen +Signed-off-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/ipv6/netfilter.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c +index 53d255838e6ab..5d989d803009f 100644 +--- a/net/ipv6/netfilter.c ++++ b/net/ipv6/netfilter.c +@@ -36,6 +36,7 @@ int ip6_route_me_harder(struct net *net, struct sock *sk_partial, struct sk_buff + .flowi6_uid = sock_net_uid(net, sk), + .daddr = iph->daddr, + .saddr = iph->saddr, ++ .flowlabel = ip6_flowinfo(iph), + }; + int err; + +-- +2.43.0 + diff --git a/queue-6.9/nfs-add-barriers-when-testing-for-nfs_fsdata_blocked.patch b/queue-6.9/nfs-add-barriers-when-testing-for-nfs_fsdata_blocked.patch new file mode 100644 index 00000000000..6d6e217ed07 --- /dev/null +++ b/queue-6.9/nfs-add-barriers-when-testing-for-nfs_fsdata_blocked.patch @@ -0,0 +1,151 @@ +From 85f6a5b6541b425508b581b1f0bee24e8345ec50 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 28 May 2024 13:27:17 +1000 +Subject: NFS: add barriers when testing for NFS_FSDATA_BLOCKED + +From: NeilBrown + +[ Upstream commit 99bc9f2eb3f79a2b4296d9bf43153e1d10ca50d3 ] + +dentry->d_fsdata is set to NFS_FSDATA_BLOCKED while unlinking or +renaming-over a file to ensure that no open succeeds while the NFS +operation progressed on the server. + +Setting dentry->d_fsdata to NFS_FSDATA_BLOCKED is done under ->d_lock +after checking the refcount is not elevated. Any attempt to open the +file (through that name) will go through lookp_open() which will take +->d_lock while incrementing the refcount, we can be sure that once the +new value is set, __nfs_lookup_revalidate() *will* see the new value and +will block. + +We don't have any locking guarantee that when we set ->d_fsdata to NULL, +the wait_var_event() in __nfs_lookup_revalidate() will notice. +wait/wake primitives do NOT provide barriers to guarantee order. We +must use smp_load_acquire() in wait_var_event() to ensure we look at an +up-to-date value, and must use smp_store_release() before wake_up_var(). + +This patch adds those barrier functions and factors out +block_revalidate() and unblock_revalidate() far clarity. + +There is also a hypothetical bug in that if memory allocation fails +(which never happens in practice) we might leave ->d_fsdata locked. +This patch adds the missing call to unblock_revalidate(). + +Reported-and-tested-by: Richard Kojedzinszky +Closes: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1071501 +Fixes: 3c59366c207e ("NFS: don't unhash dentry during unlink/rename") +Signed-off-by: NeilBrown +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + fs/nfs/dir.c | 47 ++++++++++++++++++++++++++++++++--------------- + 1 file changed, 32 insertions(+), 15 deletions(-) + +diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c +index ac505671efbdb..bdd6cb33a3708 100644 +--- a/fs/nfs/dir.c ++++ b/fs/nfs/dir.c +@@ -1802,9 +1802,10 @@ __nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags, + if (parent != READ_ONCE(dentry->d_parent)) + return -ECHILD; + } else { +- /* Wait for unlink to complete */ ++ /* Wait for unlink to complete - see unblock_revalidate() */ + wait_var_event(&dentry->d_fsdata, +- dentry->d_fsdata != NFS_FSDATA_BLOCKED); ++ smp_load_acquire(&dentry->d_fsdata) ++ != NFS_FSDATA_BLOCKED); + parent = dget_parent(dentry); + ret = reval(d_inode(parent), dentry, flags); + dput(parent); +@@ -1817,6 +1818,29 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags) + return __nfs_lookup_revalidate(dentry, flags, nfs_do_lookup_revalidate); + } + ++static void block_revalidate(struct dentry *dentry) ++{ ++ /* old devname - just in case */ ++ kfree(dentry->d_fsdata); ++ ++ /* Any new reference that could lead to an open ++ * will take ->d_lock in lookup_open() -> d_lookup(). ++ * Holding this lock ensures we cannot race with ++ * __nfs_lookup_revalidate() and removes and need ++ * for further barriers. ++ */ ++ lockdep_assert_held(&dentry->d_lock); ++ ++ dentry->d_fsdata = NFS_FSDATA_BLOCKED; ++} ++ ++static void unblock_revalidate(struct dentry *dentry) ++{ ++ /* store_release ensures wait_var_event() sees the update */ ++ smp_store_release(&dentry->d_fsdata, NULL); ++ wake_up_var(&dentry->d_fsdata); ++} ++ + /* + * A weaker form of d_revalidate for revalidating just the d_inode(dentry) + * when we don't really care about the dentry name. This is called when a +@@ -2501,15 +2525,12 @@ int nfs_unlink(struct inode *dir, struct dentry *dentry) + spin_unlock(&dentry->d_lock); + goto out; + } +- /* old devname */ +- kfree(dentry->d_fsdata); +- dentry->d_fsdata = NFS_FSDATA_BLOCKED; ++ block_revalidate(dentry); + + spin_unlock(&dentry->d_lock); + error = nfs_safe_remove(dentry); + nfs_dentry_remove_handle_error(dir, dentry, error); +- dentry->d_fsdata = NULL; +- wake_up_var(&dentry->d_fsdata); ++ unblock_revalidate(dentry); + out: + trace_nfs_unlink_exit(dir, dentry, error); + return error; +@@ -2616,8 +2637,7 @@ nfs_unblock_rename(struct rpc_task *task, struct nfs_renamedata *data) + { + struct dentry *new_dentry = data->new_dentry; + +- new_dentry->d_fsdata = NULL; +- wake_up_var(&new_dentry->d_fsdata); ++ unblock_revalidate(new_dentry); + } + + /* +@@ -2679,11 +2699,6 @@ int nfs_rename(struct mnt_idmap *idmap, struct inode *old_dir, + if (WARN_ON(new_dentry->d_flags & DCACHE_NFSFS_RENAMED) || + WARN_ON(new_dentry->d_fsdata == NFS_FSDATA_BLOCKED)) + goto out; +- if (new_dentry->d_fsdata) { +- /* old devname */ +- kfree(new_dentry->d_fsdata); +- new_dentry->d_fsdata = NULL; +- } + + spin_lock(&new_dentry->d_lock); + if (d_count(new_dentry) > 2) { +@@ -2705,7 +2720,7 @@ int nfs_rename(struct mnt_idmap *idmap, struct inode *old_dir, + new_dentry = dentry; + new_inode = NULL; + } else { +- new_dentry->d_fsdata = NFS_FSDATA_BLOCKED; ++ block_revalidate(new_dentry); + must_unblock = true; + spin_unlock(&new_dentry->d_lock); + } +@@ -2717,6 +2732,8 @@ int nfs_rename(struct mnt_idmap *idmap, struct inode *old_dir, + task = nfs_async_rename(old_dir, new_dir, old_dentry, new_dentry, + must_unblock ? nfs_unblock_rename : NULL); + if (IS_ERR(task)) { ++ if (must_unblock) ++ unblock_revalidate(new_dentry); + error = PTR_ERR(task); + goto out; + } +-- +2.43.0 + diff --git a/queue-6.9/nfsv4.1-enforce-rootpath-check-in-fs_location-query.patch b/queue-6.9/nfsv4.1-enforce-rootpath-check-in-fs_location-query.patch new file mode 100644 index 00000000000..0cb57b8b23e --- /dev/null +++ b/queue-6.9/nfsv4.1-enforce-rootpath-check-in-fs_location-query.patch @@ -0,0 +1,75 @@ +From c26715e5e3daee07bc50c1621a20a95e4423636d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 29 May 2024 15:44:35 -0400 +Subject: NFSv4.1 enforce rootpath check in fs_location query + +From: Olga Kornievskaia + +[ Upstream commit 28568c906c1bb5f7560e18082ed7d6295860f1c2 ] + +In commit 4ca9f31a2be66 ("NFSv4.1 test and add 4.1 trunking transport"), +we introduce the ability to query the NFS server for possible trunking +locations of the existing filesystem. However, we never checked the +returned file system path for these alternative locations. According +to the RFC, the server can say that the filesystem currently known +under "fs_root" of fs_location also resides under these server +locations under the following "rootpath" pathname. The client cannot +handle trunking a filesystem that reside under different location +under different paths other than what the main path is. This patch +enforces the check that fs_root path and rootpath path in fs_location +reply is the same. + +Fixes: 4ca9f31a2be6 ("NFSv4.1 test and add 4.1 trunking transport") +Signed-off-by: Olga Kornievskaia +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + fs/nfs/nfs4proc.c | 23 ++++++++++++++++++++++- + 1 file changed, 22 insertions(+), 1 deletion(-) + +diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c +index c93c12063b3af..3a816c4a6d5e2 100644 +--- a/fs/nfs/nfs4proc.c ++++ b/fs/nfs/nfs4proc.c +@@ -4023,6 +4023,23 @@ static void test_fs_location_for_trunking(struct nfs4_fs_location *location, + } + } + ++static bool _is_same_nfs4_pathname(struct nfs4_pathname *path1, ++ struct nfs4_pathname *path2) ++{ ++ int i; ++ ++ if (path1->ncomponents != path2->ncomponents) ++ return false; ++ for (i = 0; i < path1->ncomponents; i++) { ++ if (path1->components[i].len != path2->components[i].len) ++ return false; ++ if (memcmp(path1->components[i].data, path2->components[i].data, ++ path1->components[i].len)) ++ return false; ++ } ++ return true; ++} ++ + static int _nfs4_discover_trunking(struct nfs_server *server, + struct nfs_fh *fhandle) + { +@@ -4056,9 +4073,13 @@ static int _nfs4_discover_trunking(struct nfs_server *server, + if (status) + goto out_free_3; + +- for (i = 0; i < locations->nlocations; i++) ++ for (i = 0; i < locations->nlocations; i++) { ++ if (!_is_same_nfs4_pathname(&locations->fs_path, ++ &locations->locations[i].rootpath)) ++ continue; + test_fs_location_for_trunking(&locations->locations[i], clp, + server); ++ } + out_free_3: + kfree(locations->fattr); + out_free_2: +-- +2.43.0 + diff --git a/queue-6.9/nvme-fix-nvme_pr_-status-code-parsing.patch b/queue-6.9/nvme-fix-nvme_pr_-status-code-parsing.patch new file mode 100644 index 00000000000..5bb8ac35952 --- /dev/null +++ b/queue-6.9/nvme-fix-nvme_pr_-status-code-parsing.patch @@ -0,0 +1,35 @@ +From 652ae270495187b76c8471e55545886312721af7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 30 May 2024 14:16:46 +0800 +Subject: nvme: fix nvme_pr_* status code parsing + +From: Weiwen Hu + +[ Upstream commit b1a1fdd7096dd2d67911b07f8118ff113d815db4 ] + +Fix the parsing if extra status bits (e.g. MORE) is present. + +Fixes: 7fb42780d06c ("nvme: Convert NVMe errors to PR errors") +Signed-off-by: Weiwen Hu +Signed-off-by: Keith Busch +Signed-off-by: Sasha Levin +--- + drivers/nvme/host/pr.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/nvme/host/pr.c b/drivers/nvme/host/pr.c +index e05571b2a1b0c..8fa1ffcdaed48 100644 +--- a/drivers/nvme/host/pr.c ++++ b/drivers/nvme/host/pr.c +@@ -77,7 +77,7 @@ static int nvme_sc_to_pr_err(int nvme_sc) + if (nvme_is_path_error(nvme_sc)) + return PR_STS_PATH_FAILED; + +- switch (nvme_sc) { ++ switch (nvme_sc & 0x7ff) { + case NVME_SC_SUCCESS: + return PR_STS_SUCCESS; + case NVME_SC_RESERVATION_CONFLICT: +-- +2.43.0 + diff --git a/queue-6.9/nvmet-passthru-propagate-status-from-id-override-fun.patch b/queue-6.9/nvmet-passthru-propagate-status-from-id-override-fun.patch new file mode 100644 index 00000000000..1b8233855b4 --- /dev/null +++ b/queue-6.9/nvmet-passthru-propagate-status-from-id-override-fun.patch @@ -0,0 +1,46 @@ +From 880b2c1ff7ecab388655927b1dd1f61d1477d966 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 12 Jun 2024 16:02:40 +0200 +Subject: nvmet-passthru: propagate status from id override functions + +From: Daniel Wagner + +[ Upstream commit d76584e53f4244dbc154bec447c3852600acc914 ] + +The id override functions return a status which is not propagated to the +caller. + +Fixes: c1fef73f793b ("nvmet: add passthru code to process commands") +Signed-off-by: Daniel Wagner +Reviewed-by: Chaitanya Kulkarni +Reviewed-by: Christoph Hellwig +Signed-off-by: Keith Busch +Signed-off-by: Sasha Levin +--- + drivers/nvme/target/passthru.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/nvme/target/passthru.c b/drivers/nvme/target/passthru.c +index bb4a69d538fd1..f003782d4ecff 100644 +--- a/drivers/nvme/target/passthru.c ++++ b/drivers/nvme/target/passthru.c +@@ -226,13 +226,13 @@ static void nvmet_passthru_execute_cmd_work(struct work_struct *w) + req->cmd->common.opcode == nvme_admin_identify) { + switch (req->cmd->identify.cns) { + case NVME_ID_CNS_CTRL: +- nvmet_passthru_override_id_ctrl(req); ++ status = nvmet_passthru_override_id_ctrl(req); + break; + case NVME_ID_CNS_NS: +- nvmet_passthru_override_id_ns(req); ++ status = nvmet_passthru_override_id_ns(req); + break; + case NVME_ID_CNS_NS_DESC_LIST: +- nvmet_passthru_override_id_descs(req); ++ status = nvmet_passthru_override_id_descs(req); + break; + } + } else if (status < 0) +-- +2.43.0 + diff --git a/queue-6.9/platform-x86-dell-smbios-fix-wrong-token-data-in-sys.patch b/queue-6.9/platform-x86-dell-smbios-fix-wrong-token-data-in-sys.patch new file mode 100644 index 00000000000..675bb70a16f --- /dev/null +++ b/queue-6.9/platform-x86-dell-smbios-fix-wrong-token-data-in-sys.patch @@ -0,0 +1,226 @@ +From 509cc06db4195828a73b71f74a064cf356a2e96c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 28 May 2024 22:49:02 +0200 +Subject: platform/x86: dell-smbios: Fix wrong token data in sysfs +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Armin Wolf + +[ Upstream commit 1981b296f858010eae409548fd297659b2cc570e ] + +When reading token data from sysfs on my Inspiron 3505, the token +locations and values are wrong. This happens because match_attribute() +blindly assumes that all entries in da_tokens have an associated +entry in token_attrs. + +This however is not true as soon as da_tokens[] contains zeroed +token entries. Those entries are being skipped when initialising +token_attrs, breaking the core assumption of match_attribute(). + +Fix this by defining an extra struct for each pair of token attributes +and use container_of() to retrieve token information. + +Tested on a Dell Inspiron 3050. + +Fixes: 33b9ca1e53b4 ("platform/x86: dell-smbios: Add a sysfs interface for SMBIOS tokens") +Signed-off-by: Armin Wolf +Reviewed-by: Ilpo Järvinen +Link: https://lore.kernel.org/r/20240528204903.445546-1-W_Armin@gmx.de +Reviewed-by: Hans de Goede +Signed-off-by: Hans de Goede +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/dell/dell-smbios-base.c | 92 ++++++++------------ + 1 file changed, 36 insertions(+), 56 deletions(-) + +diff --git a/drivers/platform/x86/dell/dell-smbios-base.c b/drivers/platform/x86/dell/dell-smbios-base.c +index e61bfaf8b5c48..86b95206cb1bd 100644 +--- a/drivers/platform/x86/dell/dell-smbios-base.c ++++ b/drivers/platform/x86/dell/dell-smbios-base.c +@@ -11,6 +11,7 @@ + */ + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + ++#include + #include + #include + #include +@@ -25,11 +26,16 @@ static u32 da_supported_commands; + static int da_num_tokens; + static struct platform_device *platform_device; + static struct calling_interface_token *da_tokens; +-static struct device_attribute *token_location_attrs; +-static struct device_attribute *token_value_attrs; ++static struct token_sysfs_data *token_entries; + static struct attribute **token_attrs; + static DEFINE_MUTEX(smbios_mutex); + ++struct token_sysfs_data { ++ struct device_attribute location_attr; ++ struct device_attribute value_attr; ++ struct calling_interface_token *token; ++}; ++ + struct smbios_device { + struct list_head list; + struct device *device; +@@ -416,47 +422,26 @@ static void __init find_tokens(const struct dmi_header *dm, void *dummy) + } + } + +-static int match_attribute(struct device *dev, +- struct device_attribute *attr) +-{ +- int i; +- +- for (i = 0; i < da_num_tokens * 2; i++) { +- if (!token_attrs[i]) +- continue; +- if (strcmp(token_attrs[i]->name, attr->attr.name) == 0) +- return i/2; +- } +- dev_dbg(dev, "couldn't match: %s\n", attr->attr.name); +- return -EINVAL; +-} +- + static ssize_t location_show(struct device *dev, + struct device_attribute *attr, char *buf) + { +- int i; ++ struct token_sysfs_data *data = container_of(attr, struct token_sysfs_data, location_attr); + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + +- i = match_attribute(dev, attr); +- if (i > 0) +- return sysfs_emit(buf, "%08x", da_tokens[i].location); +- return 0; ++ return sysfs_emit(buf, "%08x", data->token->location); + } + + static ssize_t value_show(struct device *dev, + struct device_attribute *attr, char *buf) + { +- int i; ++ struct token_sysfs_data *data = container_of(attr, struct token_sysfs_data, value_attr); + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + +- i = match_attribute(dev, attr); +- if (i > 0) +- return sysfs_emit(buf, "%08x", da_tokens[i].value); +- return 0; ++ return sysfs_emit(buf, "%08x", data->token->value); + } + + static struct attribute_group smbios_attribute_group = { +@@ -473,22 +458,15 @@ static int build_tokens_sysfs(struct platform_device *dev) + { + char *location_name; + char *value_name; +- size_t size; + int ret; + int i, j; + +- /* (number of tokens + 1 for null terminated */ +- size = sizeof(struct device_attribute) * (da_num_tokens + 1); +- token_location_attrs = kzalloc(size, GFP_KERNEL); +- if (!token_location_attrs) ++ token_entries = kcalloc(da_num_tokens, sizeof(*token_entries), GFP_KERNEL); ++ if (!token_entries) + return -ENOMEM; +- token_value_attrs = kzalloc(size, GFP_KERNEL); +- if (!token_value_attrs) +- goto out_allocate_value; + + /* need to store both location and value + terminator*/ +- size = sizeof(struct attribute *) * ((2 * da_num_tokens) + 1); +- token_attrs = kzalloc(size, GFP_KERNEL); ++ token_attrs = kcalloc((2 * da_num_tokens) + 1, sizeof(*token_attrs), GFP_KERNEL); + if (!token_attrs) + goto out_allocate_attrs; + +@@ -496,27 +474,32 @@ static int build_tokens_sysfs(struct platform_device *dev) + /* skip empty */ + if (da_tokens[i].tokenID == 0) + continue; ++ ++ token_entries[i].token = &da_tokens[i]; ++ + /* add location */ + location_name = kasprintf(GFP_KERNEL, "%04x_location", + da_tokens[i].tokenID); + if (location_name == NULL) + goto out_unwind_strings; +- sysfs_attr_init(&token_location_attrs[i].attr); +- token_location_attrs[i].attr.name = location_name; +- token_location_attrs[i].attr.mode = 0444; +- token_location_attrs[i].show = location_show; +- token_attrs[j++] = &token_location_attrs[i].attr; ++ ++ sysfs_attr_init(&token_entries[i].location_attr.attr); ++ token_entries[i].location_attr.attr.name = location_name; ++ token_entries[i].location_attr.attr.mode = 0444; ++ token_entries[i].location_attr.show = location_show; ++ token_attrs[j++] = &token_entries[i].location_attr.attr; + + /* add value */ + value_name = kasprintf(GFP_KERNEL, "%04x_value", + da_tokens[i].tokenID); + if (value_name == NULL) + goto loop_fail_create_value; +- sysfs_attr_init(&token_value_attrs[i].attr); +- token_value_attrs[i].attr.name = value_name; +- token_value_attrs[i].attr.mode = 0444; +- token_value_attrs[i].show = value_show; +- token_attrs[j++] = &token_value_attrs[i].attr; ++ ++ sysfs_attr_init(&token_entries[i].value_attr.attr); ++ token_entries[i].value_attr.attr.name = value_name; ++ token_entries[i].value_attr.attr.mode = 0444; ++ token_entries[i].value_attr.show = value_show; ++ token_attrs[j++] = &token_entries[i].value_attr.attr; + continue; + + loop_fail_create_value: +@@ -532,14 +515,12 @@ static int build_tokens_sysfs(struct platform_device *dev) + + out_unwind_strings: + while (i--) { +- kfree(token_location_attrs[i].attr.name); +- kfree(token_value_attrs[i].attr.name); ++ kfree(token_entries[i].location_attr.attr.name); ++ kfree(token_entries[i].value_attr.attr.name); + } + kfree(token_attrs); + out_allocate_attrs: +- kfree(token_value_attrs); +-out_allocate_value: +- kfree(token_location_attrs); ++ kfree(token_entries); + + return -ENOMEM; + } +@@ -551,12 +532,11 @@ static void free_group(struct platform_device *pdev) + sysfs_remove_group(&pdev->dev.kobj, + &smbios_attribute_group); + for (i = 0; i < da_num_tokens; i++) { +- kfree(token_location_attrs[i].attr.name); +- kfree(token_value_attrs[i].attr.name); ++ kfree(token_entries[i].location_attr.attr.name); ++ kfree(token_entries[i].value_attr.attr.name); + } + kfree(token_attrs); +- kfree(token_value_attrs); +- kfree(token_location_attrs); ++ kfree(token_entries); + } + + static int __init dell_smbios_init(void) +-- +2.43.0 + diff --git a/queue-6.9/scsi-ufs-core-quiesce-request-queues-before-checking.patch b/queue-6.9/scsi-ufs-core-quiesce-request-queues-before-checking.patch new file mode 100644 index 00000000000..70dec9baa83 --- /dev/null +++ b/queue-6.9/scsi-ufs-core-quiesce-request-queues-before-checking.patch @@ -0,0 +1,109 @@ +From 0f6201e6126d3aaf7aad01ed0f98d8c766f6ec07 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Jun 2024 18:06:23 +0800 +Subject: scsi: ufs: core: Quiesce request queues before checking pending cmds + +From: Ziqi Chen + +[ Upstream commit 77691af484e28af7a692e511b9ed5ca63012ec6e ] + +In ufshcd_clock_scaling_prepare(), after SCSI layer is blocked, +ufshcd_pending_cmds() is called to check whether there are pending +transactions or not. And only if there are no pending transactions can we +proceed to kickstart the clock scaling sequence. + +ufshcd_pending_cmds() traverses over all SCSI devices and calls +sbitmap_weight() on their budget_map. sbitmap_weight() can be broken down +to three steps: + + 1. Calculate the nr outstanding bits set in the 'word' bitmap. + + 2. Calculate the nr outstanding bits set in the 'cleared' bitmap. + + 3. Subtract the result from step 1 by the result from step 2. + +This can lead to a race condition as outlined below: + +Assume there is one pending transaction in the request queue of one SCSI +device, say sda, and the budget token of this request is 0, the 'word' is +0x1 and the 'cleared' is 0x0. + + 1. When step 1 executes, it gets the result as 1. + + 2. Before step 2 executes, block layer tries to dispatch a new request to + sda. Since the SCSI layer is blocked, the request cannot pass through + SCSI but the block layer would do budget_get() and budget_put() to + sda's budget map regardless, so the 'word' has become 0x3 and 'cleared' + has become 0x2 (assume the new request got budget token 1). + + 3. When step 2 executes, it gets the result as 1. + + 4. When step 3 executes, it gets the result as 0, meaning there is no + pending transactions, which is wrong. + + Thread A Thread B + ufshcd_pending_cmds() __blk_mq_sched_dispatch_requests() + | | + sbitmap_weight(word) | + | scsi_mq_get_budget() + | | + | scsi_mq_put_budget() + | | + sbitmap_weight(cleared) + ... + +When this race condition happens, the clock scaling sequence is started +with transactions still in flight, leading to subsequent hibernate enter +failure, broken link, task abort and back to back error recovery. + +Fix this race condition by quiescing the request queues before calling +ufshcd_pending_cmds() so that block layer won't touch the budget map when +ufshcd_pending_cmds() is working on it. In addition, remove the SCSI layer +blocking/unblocking to reduce redundancies and latencies. + +Fixes: 8d077ede48c1 ("scsi: ufs: Optimize the command queueing code") +Co-developed-by: Can Guo +Signed-off-by: Can Guo +Signed-off-by: Ziqi Chen +Link: https://lore.kernel.org/r/1717754818-39863-1-git-send-email-quic_ziqichen@quicinc.com +Reviewed-by: Bart Van Assche +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/ufs/core/ufshcd.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c +index 1322a9c318cff..ce1abd5d725ad 100644 +--- a/drivers/ufs/core/ufshcd.c ++++ b/drivers/ufs/core/ufshcd.c +@@ -1392,7 +1392,7 @@ static int ufshcd_clock_scaling_prepare(struct ufs_hba *hba, u64 timeout_us) + * make sure that there are no outstanding requests when + * clock scaling is in progress + */ +- ufshcd_scsi_block_requests(hba); ++ blk_mq_quiesce_tagset(&hba->host->tag_set); + mutex_lock(&hba->wb_mutex); + down_write(&hba->clk_scaling_lock); + +@@ -1401,7 +1401,7 @@ static int ufshcd_clock_scaling_prepare(struct ufs_hba *hba, u64 timeout_us) + ret = -EBUSY; + up_write(&hba->clk_scaling_lock); + mutex_unlock(&hba->wb_mutex); +- ufshcd_scsi_unblock_requests(hba); ++ blk_mq_unquiesce_tagset(&hba->host->tag_set); + goto out; + } + +@@ -1422,7 +1422,7 @@ static void ufshcd_clock_scaling_unprepare(struct ufs_hba *hba, int err, bool sc + + mutex_unlock(&hba->wb_mutex); + +- ufshcd_scsi_unblock_requests(hba); ++ blk_mq_unquiesce_tagset(&hba->host->tag_set); + ufshcd_release(hba); + } + +-- +2.43.0 + diff --git a/queue-6.9/selftests-ftrace-fix-to-check-required-event-file.patch b/queue-6.9/selftests-ftrace-fix-to-check-required-event-file.patch new file mode 100644 index 00000000000..adf00309394 --- /dev/null +++ b/queue-6.9/selftests-ftrace-fix-to-check-required-event-file.patch @@ -0,0 +1,40 @@ +From 68a7cf88e5432e41e3d734d4bfb23f1c532bd9ab Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 May 2024 09:00:22 +0900 +Subject: selftests/ftrace: Fix to check required event file + +From: Masami Hiramatsu (Google) + +[ Upstream commit f6c3c83db1d939ebdb8c8922748ae647d8126d91 ] + +The dynevent/test_duplicates.tc test case uses `syscalls/sys_enter_openat` +event for defining eprobe on it. Since this `syscalls` events depend on +CONFIG_FTRACE_SYSCALLS=y, if it is not set, the test will fail. + +Add the event file to `required` line so that the test will return +`unsupported` result. + +Fixes: 297e1dcdca3d ("selftests/ftrace: Add selftest for testing duplicate eprobes and kprobes") +Signed-off-by: Masami Hiramatsu (Google) +Signed-off-by: Shuah Khan +Signed-off-by: Sasha Levin +--- + .../testing/selftests/ftrace/test.d/dynevent/test_duplicates.tc | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/testing/selftests/ftrace/test.d/dynevent/test_duplicates.tc b/tools/testing/selftests/ftrace/test.d/dynevent/test_duplicates.tc +index d3a79da215c8b..5f72abe6fa79b 100644 +--- a/tools/testing/selftests/ftrace/test.d/dynevent/test_duplicates.tc ++++ b/tools/testing/selftests/ftrace/test.d/dynevent/test_duplicates.tc +@@ -1,7 +1,7 @@ + #!/bin/sh + # SPDX-License-Identifier: GPL-2.0 + # description: Generic dynamic event - check if duplicate events are caught +-# requires: dynamic_events "e[:[/][]] . []":README ++# requires: dynamic_events "e[:[/][]] . []":README events/syscalls/sys_enter_openat + + echo 0 > events/enable + +-- +2.43.0 + diff --git a/queue-6.9/selftests-futex-don-t-pass-a-const-char-to-asprintf-.patch b/queue-6.9/selftests-futex-don-t-pass-a-const-char-to-asprintf-.patch new file mode 100644 index 00000000000..2497b8eabc7 --- /dev/null +++ b/queue-6.9/selftests-futex-don-t-pass-a-const-char-to-asprintf-.patch @@ -0,0 +1,53 @@ +From 0f389fb2cc7a6ad2572fde180f7853d08ff314a0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 31 May 2024 13:07:54 -0700 +Subject: selftests/futex: don't pass a const char* to asprintf(3) + +From: John Hubbard + +[ Upstream commit 4bf15b1c657d22d1d70173e43264e4606dfe75ff ] + +When building with clang, via: + + make LLVM=1 -C tools/testing/selftests + +...clang issues this warning: + +futex_requeue_pi.c:403:17: warning: passing 'const char **' to parameter +of type 'char **' discards qualifiers in nested pointer types +[-Wincompatible-pointer-types-discards-qualifiers] + +This warning fires because test_name is passed into asprintf(3), which +then changes it. + +Fix this by simply removing the const qualifier. This is a local +automatic variable in a very short function, so there is not much need +to use the compiler to enforce const-ness at this scope. + +[1] https://lore.kernel.org/all/20240329-selftests-libmk-llvm-rfc-v1-1-2f9ed7d1c49f@valentinobst.de/ + +Fixes: f17d8a87ecb5 ("selftests: fuxex: Report a unique test name per run of futex_requeue_pi") +Reviewed-by: Davidlohr Bueso +Signed-off-by: John Hubbard +Signed-off-by: Shuah Khan +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/futex/functional/futex_requeue_pi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/testing/selftests/futex/functional/futex_requeue_pi.c b/tools/testing/selftests/futex/functional/futex_requeue_pi.c +index 7f3ca5c78df12..215c6cb539b4a 100644 +--- a/tools/testing/selftests/futex/functional/futex_requeue_pi.c ++++ b/tools/testing/selftests/futex/functional/futex_requeue_pi.c +@@ -360,7 +360,7 @@ int unit_test(int broadcast, long lock, int third_party_owner, long timeout_ns) + + int main(int argc, char *argv[]) + { +- const char *test_name; ++ char *test_name; + int c, ret; + + while ((c = getopt(argc, argv, "bchlot:v:")) != -1) { +-- +2.43.0 + diff --git a/queue-6.9/selftests-tracing-fix-event-filter-test-to-retry-up-.patch b/queue-6.9/selftests-tracing-fix-event-filter-test-to-retry-up-.patch new file mode 100644 index 00000000000..2ecf4ae360e --- /dev/null +++ b/queue-6.9/selftests-tracing-fix-event-filter-test-to-retry-up-.patch @@ -0,0 +1,79 @@ +From e14233c04b9ef113bec95c772ca7600b5b61ea21 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 31 May 2024 18:43:37 +0900 +Subject: selftests/tracing: Fix event filter test to retry up to 10 times + +From: Masami Hiramatsu (Google) + +[ Upstream commit 0f42bdf59b4e428485aa922bef871bfa6cc505e0 ] + +Commit eb50d0f250e9 ("selftests/ftrace: Choose target function for filter +test from samples") choose the target function from samples, but sometimes +this test failes randomly because the target function does not hit at the +next time. So retry getting samples up to 10 times. + +Fixes: eb50d0f250e9 ("selftests/ftrace: Choose target function for filter test from samples") +Signed-off-by: Masami Hiramatsu (Google) +Signed-off-by: Shuah Khan +Signed-off-by: Sasha Levin +--- + .../test.d/filter/event-filter-function.tc | 20 ++++++++++++++++++- + 1 file changed, 19 insertions(+), 1 deletion(-) + +diff --git a/tools/testing/selftests/ftrace/test.d/filter/event-filter-function.tc b/tools/testing/selftests/ftrace/test.d/filter/event-filter-function.tc +index 3f74c09c56b62..118247b8dd84d 100644 +--- a/tools/testing/selftests/ftrace/test.d/filter/event-filter-function.tc ++++ b/tools/testing/selftests/ftrace/test.d/filter/event-filter-function.tc +@@ -10,7 +10,6 @@ fail() { #msg + } + + sample_events() { +- echo > trace + echo 1 > events/kmem/kmem_cache_free/enable + echo 1 > tracing_on + ls > /dev/null +@@ -22,6 +21,7 @@ echo 0 > tracing_on + echo 0 > events/enable + + echo "Get the most frequently calling function" ++echo > trace + sample_events + + target_func=`cat trace | grep -o 'call_site=\([^+]*\)' | sed 's/call_site=//' | sort | uniq -c | sort | tail -n 1 | sed 's/^[ 0-9]*//'` +@@ -32,7 +32,16 @@ echo > trace + + echo "Test event filter function name" + echo "call_site.function == $target_func" > events/kmem/kmem_cache_free/filter ++ ++sample_events ++max_retry=10 ++while [ `grep kmem_cache_free trace| wc -l` -eq 0 ]; do + sample_events ++max_retry=$((max_retry - 1)) ++if [ $max_retry -eq 0 ]; then ++ exit_fail ++fi ++done + + hitcnt=`grep kmem_cache_free trace| grep $target_func | wc -l` + misscnt=`grep kmem_cache_free trace| grep -v $target_func | wc -l` +@@ -49,7 +58,16 @@ address=`grep " ${target_func}\$" /proc/kallsyms | cut -d' ' -f1` + + echo "Test event filter function address" + echo "call_site.function == 0x$address" > events/kmem/kmem_cache_free/filter ++echo > trace ++sample_events ++max_retry=10 ++while [ `grep kmem_cache_free trace| wc -l` -eq 0 ]; do + sample_events ++max_retry=$((max_retry - 1)) ++if [ $max_retry -eq 0 ]; then ++ exit_fail ++fi ++done + + hitcnt=`grep kmem_cache_free trace| grep $target_func | wc -l` + misscnt=`grep kmem_cache_free trace| grep -v $target_func | wc -l` +-- +2.43.0 + diff --git a/queue-6.9/series b/queue-6.9/series index 3c8e5eb9498..3f04df7d0c3 100644 --- a/queue-6.9/series +++ b/queue-6.9/series @@ -107,3 +107,87 @@ scsi-sd-use-read-16-when-reading-block-zero-on-large-capacity-disks.patch gve-clear-napi-skb-before-dev_kfree_skb_any.patch powerpc-85xx-fix-compile-error-without-config_crash_dump.patch powerpc-uaccess-fix-build-errors-seen-with-gcc-13-14.patch +hid-nvidia-shield-add-missing-check-for-input_ff_cre.patch +cxl-test-add-missing-vmalloc.h-for-tools-testing-cxl.patch +cxl-region-fix-memregion-leaks-in-devm_cxl_add_regio.patch +cachefiles-add-output-string-to-cachefiles_obj_-get-.patch +cachefiles-remove-requests-from-xarray-during-flushi.patch +cachefiles-fix-slab-use-after-free-in-cachefiles_ond.patch +cachefiles-fix-slab-use-after-free-in-cachefiles_ond.patch-26654 +cachefiles-add-spin_lock-for-cachefiles_ondemand_inf.patch +cachefiles-remove-err_put_fd-label-in-cachefiles_ond.patch +cachefiles-never-get-a-new-anonymous-fd-if-ondemand_.patch +cachefiles-defer-exposing-anon_fd-until-after-copy_t.patch +cachefiles-flush-all-requests-after-setting-cachefil.patch +kselftest-alsa-ensure-_gnu_source-is-defined.patch +selftests-ftrace-fix-to-check-required-event-file.patch +clk-sifive-do-not-register-clkdevs-for-prci-clocks.patch +nfsv4.1-enforce-rootpath-check-in-fs_location-query.patch +sunrpc-return-proper-error-from-gss_wrap_req_priv.patch +nfs-add-barriers-when-testing-for-nfs_fsdata_blocked.patch +selftests-tracing-fix-event-filter-test-to-retry-up-.patch +selftests-futex-don-t-pass-a-const-char-to-asprintf-.patch +nvme-fix-nvme_pr_-status-code-parsing.patch +drm-panel-sitronix-st7789v-add-check-for-of_drm_get_.patch +platform-x86-dell-smbios-fix-wrong-token-data-in-sys.patch +gpio-tqmx86-fix-typo-in-kconfig-label.patch +gpio-tqmx86-introduce-shadow-register-for-gpio-outpu.patch +gpio-tqmx86-store-irq-trigger-type-and-unmask-status.patch +gpio-tqmx86-fix-broken-irq_type_edge_both-interrupt-.patch +hid-core-remove-unnecessary-warn_on-in-implement.patch +iommu-amd-fix-sysfs-leak-in-iommu-init.patch +iommu-return-right-value-in-iommu_sva_bind_device.patch +io_uring-io-wq-use-set_bit-and-test_bit-at-worker-fl.patch +io_uring-io-wq-avoid-garbage-value-of-match-in-io_wq.patch +hid-logitech-dj-fix-memory-leak-in-logi_dj_recv_swit.patch +drm-vmwgfx-filter-modes-which-exceed-graphics-memory.patch +drm-vmwgfx-3d-disabled-should-not-effect-stdu-memory.patch +drm-vmwgfx-remove-stdu-logic-from-generic-mode_valid.patch +drm-vmwgfx-don-t-memcmp-equivalent-pointers.patch +af_unix-allocate-struct-unix_vertex-for-each-infligh.patch +af_unix-save-listener-for-embryo-socket.patch +net-change-proto-and-proto_ops-accept-type.patch +af_unix-annotate-data-race-of-sk-sk_state-in-unix_ac.patch +modpost-do-not-warn-about-missing-module_description.patch +net-sfp-always-call-sfp_sm_mod_remove-on-remove.patch +net-hns3-fix-kernel-crash-problem-in-concurrent-scen.patch +net-hns3-add-cond_resched-to-hns3-ring-buffer-init-p.patch +thermal-core-do-not-fail-cdev-registration-because-o.patch +liquidio-adjust-a-null-pointer-handling-path-in-lio_.patch +net-stmmac-dwmac-qcom-ethqos-configure-host-dma-widt.patch +netdevsim-fix-backwards-compatibility-in-nsim_get_if.patch +drm-komeda-check-for-error-valued-pointer.patch +drm-bridge-panel-fix-runtime-warning-on-panel-bridge.patch +tcp-fix-race-in-tcp_v6_syn_recv_sock.patch +net-dsa-qca8k-fix-usages-of-device_get_named_child_n.patch +geneve-fix-incorrect-inner-network-header-offset-whe.patch +net-mlx5e-fix-features-validation-check-for-tunneled.patch +bluetooth-hci_sync-fix-not-using-correct-handle.patch +bluetooth-l2cap-fix-rejecting-l2cap_conn_param_updat.patch +bluetooth-fix-connection-setup-in-l2cap_connect.patch +net-sched-initialize-noop_qdisc-owner.patch +tcp-use-signed-arithmetic-in-tcp_rtx_probe0_timed_ou.patch +drm-nouveau-don-t-attempt-to-schedule-hpd_work-on-he.patch +netfilter-nft_inner-validate-mandatory-meta-and-payl.patch +netfilter-ipset-fix-race-between-namespace-cleanup-a.patch +netfilter-use-flowlabel-flow-key-when-re-routing-man.patch +x86-asm-use-c-n-instead-of-p-operand-modifier-in-asm.patch +x86-uaccess-fix-missed-zeroing-of-ia32-u64-get_user-.patch +scsi-ufs-core-quiesce-request-queues-before-checking.patch +net-pse-pd-use-eopnotsupp-error-code-instead-of-enot.patch +gve-ignore-nonrelevant-gso-type-bits-when-processing.patch +net-stmmac-replace-priv-speed-with-the-porttransmitr.patch +block-sed-opal-avoid-possible-wrong-address-referenc.patch +block-fix-request.queuelist-usage-in-flush.patch +nvmet-passthru-propagate-status-from-id-override-fun.patch +net-ipv6-fix-the-rt-cache-flush-via-sysctl-using-a-p.patch +net-bridge-mst-pass-vlan-group-directly-to-br_mst_vl.patch +net-bridge-mst-fix-suspicious-rcu-usage-in-br_mst_se.patch +drm-xe-xe_gt_idle-use-gt-forcewake-domain-assertion.patch +drm-xe-flush-engine-buffers-before-signalling-user-f.patch +drm-xe-remove-mem_access-from-guc_pc-calls.patch +drm-xe-move-disable_c6-call.patch +ionic-fix-use-after-netif_napi_del.patch +bnxt_en-cap-the-size-of-hwrm_port_phy_qcfg-forwarded.patch +af_unix-read-with-msg_peek-loops-if-the-first-unread.patch +bnxt_en-adjust-logging-of-firmware-messages-in-case-.patch diff --git a/queue-6.9/sunrpc-return-proper-error-from-gss_wrap_req_priv.patch b/queue-6.9/sunrpc-return-proper-error-from-gss_wrap_req_priv.patch new file mode 100644 index 00000000000..b20da78651e --- /dev/null +++ b/queue-6.9/sunrpc-return-proper-error-from-gss_wrap_req_priv.patch @@ -0,0 +1,40 @@ +From c120ce9d93fe86579a17902b4846f8cecbd13ee3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 23 May 2024 16:47:16 +0800 +Subject: SUNRPC: return proper error from gss_wrap_req_priv + +From: Chen Hanxiao + +[ Upstream commit 33c94d7e3cb84f6d130678d6d59ba475a6c489cf ] + +don't return 0 if snd_buf->len really greater than snd_buf->buflen + +Signed-off-by: Chen Hanxiao +Fixes: 0c77668ddb4e ("SUNRPC: Introduce trace points in rpc_auth_gss.ko") +Reviewed-by: Benjamin Coddington +Reviewed-by: Chuck Lever +Signed-off-by: Trond Myklebust +Signed-off-by: Sasha Levin +--- + net/sunrpc/auth_gss/auth_gss.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c +index c7af0220f82f4..369310909fc98 100644 +--- a/net/sunrpc/auth_gss/auth_gss.c ++++ b/net/sunrpc/auth_gss/auth_gss.c +@@ -1875,8 +1875,10 @@ gss_wrap_req_priv(struct rpc_cred *cred, struct gss_cl_ctx *ctx, + offset = (u8 *)p - (u8 *)snd_buf->head[0].iov_base; + maj_stat = gss_wrap(ctx->gc_gss_ctx, offset, snd_buf, inpages); + /* slack space should prevent this ever happening: */ +- if (unlikely(snd_buf->len > snd_buf->buflen)) ++ if (unlikely(snd_buf->len > snd_buf->buflen)) { ++ status = -EIO; + goto wrap_failed; ++ } + /* We're assuming that when GSS_S_CONTEXT_EXPIRED, the encryption was + * done anyway, so it's safe to put the request on the wire: */ + if (maj_stat == GSS_S_CONTEXT_EXPIRED) +-- +2.43.0 + diff --git a/queue-6.9/tcp-fix-race-in-tcp_v6_syn_recv_sock.patch b/queue-6.9/tcp-fix-race-in-tcp_v6_syn_recv_sock.patch new file mode 100644 index 00000000000..aa92412ca0a --- /dev/null +++ b/queue-6.9/tcp-fix-race-in-tcp_v6_syn_recv_sock.patch @@ -0,0 +1,54 @@ +From be1451d60149fcb0fc2d118f47f185e315f8caf1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Jun 2024 15:46:51 +0000 +Subject: tcp: fix race in tcp_v6_syn_recv_sock() + +From: Eric Dumazet + +[ Upstream commit d37fe4255abe8e7b419b90c5847e8ec2b8debb08 ] + +tcp_v6_syn_recv_sock() calls ip6_dst_store() before +inet_sk(newsk)->pinet6 has been set up. + +This means ip6_dst_store() writes over the parent (listener) +np->dst_cookie. + +This is racy because multiple threads could share the same +parent and their final np->dst_cookie could be wrong. + +Move ip6_dst_store() call after inet_sk(newsk)->pinet6 +has been changed and after the copy of parent ipv6_pinfo. + +Fixes: e994b2f0fb92 ("tcp: do not lock listener to process SYN packets") +Signed-off-by: Eric Dumazet +Reviewed-by: Simon Horman +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/ipv6/tcp_ipv6.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c +index 5873b3c3562ed..2b2eda5a2894d 100644 +--- a/net/ipv6/tcp_ipv6.c ++++ b/net/ipv6/tcp_ipv6.c +@@ -1438,7 +1438,6 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff * + */ + + newsk->sk_gso_type = SKB_GSO_TCPV6; +- ip6_dst_store(newsk, dst, NULL, NULL); + inet6_sk_rx_dst_set(newsk, skb); + + inet_sk(newsk)->pinet6 = tcp_inet6_sk(newsk); +@@ -1449,6 +1448,8 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff * + + memcpy(newnp, np, sizeof(struct ipv6_pinfo)); + ++ ip6_dst_store(newsk, dst, NULL, NULL); ++ + newsk->sk_v6_daddr = ireq->ir_v6_rmt_addr; + newnp->saddr = ireq->ir_v6_loc_addr; + newsk->sk_v6_rcv_saddr = ireq->ir_v6_loc_addr; +-- +2.43.0 + diff --git a/queue-6.9/tcp-use-signed-arithmetic-in-tcp_rtx_probe0_timed_ou.patch b/queue-6.9/tcp-use-signed-arithmetic-in-tcp_rtx_probe0_timed_ou.patch new file mode 100644 index 00000000000..4e617ef380f --- /dev/null +++ b/queue-6.9/tcp-use-signed-arithmetic-in-tcp_rtx_probe0_timed_ou.patch @@ -0,0 +1,55 @@ +From 58cc7354027b8f7421d84fab37dbd32bdbd0bf69 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Jun 2024 12:56:52 +0000 +Subject: tcp: use signed arithmetic in tcp_rtx_probe0_timed_out() + +From: Eric Dumazet + +[ Upstream commit 36534d3c54537bf098224a32dc31397793d4594d ] + +Due to timer wheel implementation, a timer will usually fire +after its schedule. + +For instance, for HZ=1000, a timeout between 512ms and 4s +has a granularity of 64ms. +For this range of values, the extra delay could be up to 63ms. + +For TCP, this means that tp->rcv_tstamp may be after +inet_csk(sk)->icsk_timeout whenever the timer interrupt +finally triggers, if one packet came during the extra delay. + +We need to make sure tcp_rtx_probe0_timed_out() handles this case. + +Fixes: e89688e3e978 ("net: tcp: fix unexcepted socket die when snd_wnd is 0") +Signed-off-by: Eric Dumazet +Cc: Menglong Dong +Acked-by: Neal Cardwell +Reviewed-by: Jason Xing +Link: https://lore.kernel.org/r/20240607125652.1472540-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv4/tcp_timer.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c +index d1ad20ce1c8c7..f96f68cf7961c 100644 +--- a/net/ipv4/tcp_timer.c ++++ b/net/ipv4/tcp_timer.c +@@ -483,8 +483,12 @@ static bool tcp_rtx_probe0_timed_out(const struct sock *sk, + { + const struct tcp_sock *tp = tcp_sk(sk); + const int timeout = TCP_RTO_MAX * 2; +- u32 rcv_delta; ++ s32 rcv_delta; + ++ /* Note: timer interrupt might have been delayed by at least one jiffy, ++ * and tp->rcv_tstamp might very well have been written recently. ++ * rcv_delta can thus be negative. ++ */ + rcv_delta = inet_csk(sk)->icsk_timeout - tp->rcv_tstamp; + if (rcv_delta <= timeout) + return false; +-- +2.43.0 + diff --git a/queue-6.9/thermal-core-do-not-fail-cdev-registration-because-o.patch b/queue-6.9/thermal-core-do-not-fail-cdev-registration-because-o.patch new file mode 100644 index 00000000000..74d79b69341 --- /dev/null +++ b/queue-6.9/thermal-core-do-not-fail-cdev-registration-because-o.patch @@ -0,0 +1,75 @@ +From 81b1cc7ba4999d1a369184ed8a0c03a72b4f9372 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Jun 2024 20:27:19 +0200 +Subject: thermal: core: Do not fail cdev registration because of invalid + initial state + +From: Rafael J. Wysocki + +[ Upstream commit 1af89dedc8a58006d8e385b1e0d2cd24df8a3b69 ] + +It is reported that commit 31a0fa0019b0 ("thermal/debugfs: Pass cooling +device state to thermal_debug_cdev_add()") causes the ACPI fan driver +to fail probing on some systems which turns out to be due to the _FST +control method returning an invalid value until _FSL is first evaluated +for the given fan. If this happens, the .get_cur_state() cooling device +callback returns an error and __thermal_cooling_device_register() fails +as uses that callback after commit 31a0fa0019b0. + +Arguably, _FST should not return an invalid value even if it is +evaluated before _FSL, so this may be regarded as a platform firmware +issue, but at the same time it is not a good enough reason for failing +the cooling device registration where the initial cooling device state +is only needed to initialize a thermal debug facility. + +Accordingly, modify __thermal_cooling_device_register() to avoid +calling thermal_debug_cdev_add() instead of returning an error if the +initial .get_cur_state() callback invocation fails. + +Fixes: 31a0fa0019b0 ("thermal/debugfs: Pass cooling device state to thermal_debug_cdev_add()") +Closes: https://lore.kernel.org/linux-acpi/20240530153727.843378-1-laura.nao@collabora.com +Reported-by: Laura Nao +Signed-off-by: Rafael J. Wysocki +Acked-by: Daniel Lezcano +Tested-by: Laura Nao +Signed-off-by: Sasha Levin +--- + drivers/thermal/thermal_core.c | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c +index 38b7d02384d7c..258482036f1e9 100644 +--- a/drivers/thermal/thermal_core.c ++++ b/drivers/thermal/thermal_core.c +@@ -936,9 +936,17 @@ __thermal_cooling_device_register(struct device_node *np, + if (ret) + goto out_cdev_type; + ++ /* ++ * The cooling device's current state is only needed for debug ++ * initialization below, so a failure to get it does not cause ++ * the entire cooling device initialization to fail. However, ++ * the debug will not work for the device if its initial state ++ * cannot be determined and drivers are responsible for ensuring ++ * that this will not happen. ++ */ + ret = cdev->ops->get_cur_state(cdev, ¤t_state); + if (ret) +- goto out_cdev_type; ++ current_state = ULONG_MAX; + + thermal_cooling_device_setup_sysfs(cdev); + +@@ -953,7 +961,8 @@ __thermal_cooling_device_register(struct device_node *np, + return ERR_PTR(ret); + } + +- thermal_debug_cdev_add(cdev, current_state); ++ if (current_state <= cdev->max_state) ++ thermal_debug_cdev_add(cdev, current_state); + + /* Add 'this' new cdev to the global cdev list */ + mutex_lock(&thermal_list_lock); +-- +2.43.0 + diff --git a/queue-6.9/x86-asm-use-c-n-instead-of-p-operand-modifier-in-asm.patch b/queue-6.9/x86-asm-use-c-n-instead-of-p-operand-modifier-in-asm.patch new file mode 100644 index 00000000000..bb4ac8c8e8c --- /dev/null +++ b/queue-6.9/x86-asm-use-c-n-instead-of-p-operand-modifier-in-asm.patch @@ -0,0 +1,163 @@ +From 2e361009073f5c7d031e45c382154b27dcb462ce Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 19 Mar 2024 11:40:13 +0100 +Subject: x86/asm: Use %c/%n instead of %P operand modifier in asm templates + +From: Uros Bizjak + +[ Upstream commit 41cd2e1ee96e56401a18dbce6f42f0bdaebcbf3b ] + +The "P" asm operand modifier is a x86 target-specific modifier. + +When used with a constant, the "P" modifier emits "cst" instead of +"$cst". This property is currently used to emit the bare constant +without all syntax-specific prefixes. + +The generic "c" resp. "n" operand modifier should be used instead. + +No functional changes intended. + +Signed-off-by: Uros Bizjak +Signed-off-by: Ingo Molnar +Cc: Linus Torvalds +Cc: Josh Poimboeuf +Cc: Ard Biesheuvel +Cc: "H. Peter Anvin" +Link: https://lore.kernel.org/r/20240319104418.284519-3-ubizjak@gmail.com +Stable-dep-of: 8c860ed825cb ("x86/uaccess: Fix missed zeroing of ia32 u64 get_user() range checking") +Signed-off-by: Sasha Levin +--- + arch/x86/boot/main.c | 4 ++-- + arch/x86/include/asm/alternative.h | 22 +++++++++++----------- + arch/x86/include/asm/atomic64_32.h | 2 +- + arch/x86/include/asm/cpufeature.h | 2 +- + arch/x86/include/asm/irq_stack.h | 2 +- + arch/x86/include/asm/uaccess.h | 4 ++-- + 6 files changed, 18 insertions(+), 18 deletions(-) + +diff --git a/arch/x86/boot/main.c b/arch/x86/boot/main.c +index c4ea5258ab558..9049f390d8347 100644 +--- a/arch/x86/boot/main.c ++++ b/arch/x86/boot/main.c +@@ -119,8 +119,8 @@ static void init_heap(void) + char *stack_end; + + if (boot_params.hdr.loadflags & CAN_USE_HEAP) { +- asm("leal %P1(%%esp),%0" +- : "=r" (stack_end) : "i" (-STACK_SIZE)); ++ asm("leal %n1(%%esp),%0" ++ : "=r" (stack_end) : "i" (STACK_SIZE)); + + heap_end = (char *) + ((size_t)boot_params.hdr.heap_end_ptr + 0x200); +diff --git a/arch/x86/include/asm/alternative.h b/arch/x86/include/asm/alternative.h +index 67b68d0d17d1e..0cb2396de066d 100644 +--- a/arch/x86/include/asm/alternative.h ++++ b/arch/x86/include/asm/alternative.h +@@ -294,10 +294,10 @@ static inline int alternatives_text_reserved(void *start, void *end) + * Otherwise, if CPU has feature1, newinstr1 is used. + * Otherwise, oldinstr is used. + */ +-#define alternative_input_2(oldinstr, newinstr1, ft_flags1, newinstr2, \ +- ft_flags2, input...) \ +- asm_inline volatile(ALTERNATIVE_2(oldinstr, newinstr1, ft_flags1, \ +- newinstr2, ft_flags2) \ ++#define alternative_input_2(oldinstr, newinstr1, ft_flags1, newinstr2, \ ++ ft_flags2, input...) \ ++ asm_inline volatile(ALTERNATIVE_2(oldinstr, newinstr1, ft_flags1, \ ++ newinstr2, ft_flags2) \ + : : "i" (0), ## input) + + /* Like alternative_input, but with a single output argument */ +@@ -307,7 +307,7 @@ static inline int alternatives_text_reserved(void *start, void *end) + + /* Like alternative_io, but for replacing a direct call with another one. */ + #define alternative_call(oldfunc, newfunc, ft_flags, output, input...) \ +- asm_inline volatile (ALTERNATIVE("call %P[old]", "call %P[new]", ft_flags) \ ++ asm_inline volatile (ALTERNATIVE("call %c[old]", "call %c[new]", ft_flags) \ + : output : [old] "i" (oldfunc), [new] "i" (newfunc), ## input) + + /* +@@ -316,12 +316,12 @@ static inline int alternatives_text_reserved(void *start, void *end) + * Otherwise, if CPU has feature1, function1 is used. + * Otherwise, old function is used. + */ +-#define alternative_call_2(oldfunc, newfunc1, ft_flags1, newfunc2, ft_flags2, \ +- output, input...) \ +- asm_inline volatile (ALTERNATIVE_2("call %P[old]", "call %P[new1]", ft_flags1,\ +- "call %P[new2]", ft_flags2) \ +- : output, ASM_CALL_CONSTRAINT \ +- : [old] "i" (oldfunc), [new1] "i" (newfunc1), \ ++#define alternative_call_2(oldfunc, newfunc1, ft_flags1, newfunc2, ft_flags2, \ ++ output, input...) \ ++ asm_inline volatile (ALTERNATIVE_2("call %c[old]", "call %c[new1]", ft_flags1, \ ++ "call %c[new2]", ft_flags2) \ ++ : output, ASM_CALL_CONSTRAINT \ ++ : [old] "i" (oldfunc), [new1] "i" (newfunc1), \ + [new2] "i" (newfunc2), ## input) + + /* +diff --git a/arch/x86/include/asm/atomic64_32.h b/arch/x86/include/asm/atomic64_32.h +index 3486d91b8595f..d510405e4e1de 100644 +--- a/arch/x86/include/asm/atomic64_32.h ++++ b/arch/x86/include/asm/atomic64_32.h +@@ -24,7 +24,7 @@ typedef struct { + + #ifdef CONFIG_X86_CMPXCHG64 + #define __alternative_atomic64(f, g, out, in...) \ +- asm volatile("call %P[func]" \ ++ asm volatile("call %c[func]" \ + : out : [func] "i" (atomic64_##g##_cx8), ## in) + + #define ATOMIC64_DECL(sym) ATOMIC64_DECL_ONE(sym##_cx8) +diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h +index 686e92d2663ee..3508f3fc928d4 100644 +--- a/arch/x86/include/asm/cpufeature.h ++++ b/arch/x86/include/asm/cpufeature.h +@@ -173,7 +173,7 @@ extern void clear_cpu_cap(struct cpuinfo_x86 *c, unsigned int bit); + static __always_inline bool _static_cpu_has(u16 bit) + { + asm goto( +- ALTERNATIVE_TERNARY("jmp 6f", %P[feature], "", "jmp %l[t_no]") ++ ALTERNATIVE_TERNARY("jmp 6f", %c[feature], "", "jmp %l[t_no]") + ".pushsection .altinstr_aux,\"ax\"\n" + "6:\n" + " testb %[bitnum]," _ASM_RIP(%P[cap_byte]) "\n" +diff --git a/arch/x86/include/asm/irq_stack.h b/arch/x86/include/asm/irq_stack.h +index 798183867d789..b71ad173f8776 100644 +--- a/arch/x86/include/asm/irq_stack.h ++++ b/arch/x86/include/asm/irq_stack.h +@@ -100,7 +100,7 @@ + } + + #define ASM_CALL_ARG0 \ +- "call %P[__func] \n" \ ++ "call %c[__func] \n" \ + ASM_REACHABLE + + #define ASM_CALL_ARG1 \ +diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h +index 237dc8cdd12b9..0f9bab92a43d7 100644 +--- a/arch/x86/include/asm/uaccess.h ++++ b/arch/x86/include/asm/uaccess.h +@@ -78,7 +78,7 @@ extern int __get_user_bad(void); + int __ret_gu; \ + register __inttype(*(ptr)) __val_gu asm("%"_ASM_DX); \ + __chk_user_ptr(ptr); \ +- asm volatile("call __" #fn "_%P4" \ ++ asm volatile("call __" #fn "_%c4" \ + : "=a" (__ret_gu), "=r" (__val_gu), \ + ASM_CALL_CONSTRAINT \ + : "0" (ptr), "i" (sizeof(*(ptr)))); \ +@@ -177,7 +177,7 @@ extern void __put_user_nocheck_8(void); + __chk_user_ptr(__ptr); \ + __ptr_pu = __ptr; \ + __val_pu = __x; \ +- asm volatile("call __" #fn "_%P[size]" \ ++ asm volatile("call __" #fn "_%c[size]" \ + : "=c" (__ret_pu), \ + ASM_CALL_CONSTRAINT \ + : "0" (__ptr_pu), \ +-- +2.43.0 + diff --git a/queue-6.9/x86-uaccess-fix-missed-zeroing-of-ia32-u64-get_user-.patch b/queue-6.9/x86-uaccess-fix-missed-zeroing-of-ia32-u64-get_user-.patch new file mode 100644 index 00000000000..1ff1dc6bd7b --- /dev/null +++ b/queue-6.9/x86-uaccess-fix-missed-zeroing-of-ia32-u64-get_user-.patch @@ -0,0 +1,85 @@ +From b4c3d64dd8d5c41ae267b4d855ca1e0cc0c31082 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Jun 2024 14:02:27 -0700 +Subject: x86/uaccess: Fix missed zeroing of ia32 u64 get_user() range checking + +From: Kees Cook + +[ Upstream commit 8c860ed825cb85f6672cd7b10a8f33e3498a7c81 ] + +When reworking the range checking for get_user(), the get_user_8() case +on 32-bit wasn't zeroing the high register. (The jump to bad_get_user_8 +was accidentally dropped.) Restore the correct error handling +destination (and rename the jump to using the expected ".L" prefix). + +While here, switch to using a named argument ("size") for the call +template ("%c4" to "%c[size]") as already used in the other call +templates in this file. + +Found after moving the usercopy selftests to KUnit: + + # usercopy_test_invalid: EXPECTATION FAILED at + lib/usercopy_kunit.c:278 + Expected val_u64 == 0, but + val_u64 == -60129542144 (0xfffffff200000000) + +Closes: https://lore.kernel.org/all/CABVgOSn=tb=Lj9SxHuT4_9MTjjKVxsq-ikdXC4kGHO4CfKVmGQ@mail.gmail.com +Fixes: b19b74bc99b1 ("x86/mm: Rework address range check in get_user() and put_user()") +Reported-by: David Gow +Signed-off-by: Kees Cook +Signed-off-by: Dave Hansen +Reviewed-by: Kirill A. Shutemov +Reviewed-by: Qiuxu Zhuo +Tested-by: David Gow +Link: https://lore.kernel.org/all/20240610210213.work.143-kees%40kernel.org +Signed-off-by: Sasha Levin +--- + arch/x86/include/asm/uaccess.h | 4 ++-- + arch/x86/lib/getuser.S | 6 +++++- + 2 files changed, 7 insertions(+), 3 deletions(-) + +diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h +index 0f9bab92a43d7..3a7755c1a4410 100644 +--- a/arch/x86/include/asm/uaccess.h ++++ b/arch/x86/include/asm/uaccess.h +@@ -78,10 +78,10 @@ extern int __get_user_bad(void); + int __ret_gu; \ + register __inttype(*(ptr)) __val_gu asm("%"_ASM_DX); \ + __chk_user_ptr(ptr); \ +- asm volatile("call __" #fn "_%c4" \ ++ asm volatile("call __" #fn "_%c[size]" \ + : "=a" (__ret_gu), "=r" (__val_gu), \ + ASM_CALL_CONSTRAINT \ +- : "0" (ptr), "i" (sizeof(*(ptr)))); \ ++ : "0" (ptr), [size] "i" (sizeof(*(ptr)))); \ + instrument_get_user(__val_gu); \ + (x) = (__force __typeof__(*(ptr))) __val_gu; \ + __builtin_expect(__ret_gu, 0); \ +diff --git a/arch/x86/lib/getuser.S b/arch/x86/lib/getuser.S +index 10d5ed8b5990f..a1cb3a4e6742d 100644 +--- a/arch/x86/lib/getuser.S ++++ b/arch/x86/lib/getuser.S +@@ -44,7 +44,11 @@ + or %rdx, %rax + .else + cmp $TASK_SIZE_MAX-\size+1, %eax ++.if \size != 8 + jae .Lbad_get_user ++.else ++ jae .Lbad_get_user_8 ++.endif + sbb %edx, %edx /* array_index_mask_nospec() */ + and %edx, %eax + .endif +@@ -154,7 +158,7 @@ SYM_CODE_END(__get_user_handle_exception) + #ifdef CONFIG_X86_32 + SYM_CODE_START_LOCAL(__get_user_8_handle_exception) + ASM_CLAC +-bad_get_user_8: ++.Lbad_get_user_8: + xor %edx,%edx + xor %ecx,%ecx + mov $(-EFAULT),%_ASM_AX +-- +2.43.0 +