From: Sasha Levin Date: Mon, 18 Mar 2024 00:20:44 +0000 (-0400) Subject: Fixes for 6.6 X-Git-Tag: v6.8.2~105 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2812d02b59b1c814bfe0195f90485e862155da42;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 6.6 Signed-off-by: Sasha Levin --- diff --git a/queue-6.6/io_uring-drop-any-code-related-to-scm_rights.patch b/queue-6.6/io_uring-drop-any-code-related-to-scm_rights.patch new file mode 100644 index 00000000000..71ea47842a4 --- /dev/null +++ b/queue-6.6/io_uring-drop-any-code-related-to-scm_rights.patch @@ -0,0 +1,377 @@ +From 095e7a746ed134b8e69c8ad523d7df7f8396fd86 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 19 Dec 2023 12:36:34 -0700 +Subject: io_uring: drop any code related to SCM_RIGHTS + +From: Jens Axboe + +This is dead code after we dropped support for passing io_uring fds +over SCM_RIGHTS, get rid of it. + +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + include/linux/io_uring_types.h | 3 - + io_uring/filetable.c | 11 +-- + io_uring/io_uring.c | 32 +------ + io_uring/rsrc.c | 169 +-------------------------------- + io_uring/rsrc.h | 15 --- + 5 files changed, 10 insertions(+), 220 deletions(-) + +diff --git a/include/linux/io_uring_types.h b/include/linux/io_uring_types.h +index 5fd664fb71c86..731beb3198c4f 100644 +--- a/include/linux/io_uring_types.h ++++ b/include/linux/io_uring_types.h +@@ -347,9 +347,6 @@ struct io_ring_ctx { + + struct list_head io_buffers_pages; + +- #if defined(CONFIG_UNIX) +- struct socket *ring_sock; +- #endif + /* hashed buffered write serialization */ + struct io_wq_hash *hash_map; + +diff --git a/io_uring/filetable.c b/io_uring/filetable.c +index e7d749991de42..6e86e6188dbee 100644 +--- a/io_uring/filetable.c ++++ b/io_uring/filetable.c +@@ -87,13 +87,10 @@ static int io_install_fixed_file(struct io_ring_ctx *ctx, struct file *file, + io_file_bitmap_clear(&ctx->file_table, slot_index); + } + +- ret = io_scm_file_account(ctx, file); +- if (!ret) { +- *io_get_tag_slot(ctx->file_data, slot_index) = 0; +- io_fixed_file_set(file_slot, file); +- io_file_bitmap_set(&ctx->file_table, slot_index); +- } +- return ret; ++ *io_get_tag_slot(ctx->file_data, slot_index) = 0; ++ io_fixed_file_set(file_slot, file); ++ io_file_bitmap_set(&ctx->file_table, slot_index); ++ return 0; + } + + int __io_fixed_fd_install(struct io_ring_ctx *ctx, struct file *file, +diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c +index 747d2a6ecab89..2744d72f10858 100644 +--- a/io_uring/io_uring.c ++++ b/io_uring/io_uring.c +@@ -60,7 +60,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -2931,13 +2930,6 @@ static __cold void io_ring_ctx_free(struct io_ring_ctx *ctx) + io_rsrc_node_destroy(ctx, ctx->rsrc_node); + + WARN_ON_ONCE(!list_empty(&ctx->rsrc_ref_list)); +- +-#if defined(CONFIG_UNIX) +- if (ctx->ring_sock) { +- ctx->ring_sock->file = NULL; /* so that iput() is called */ +- sock_release(ctx->ring_sock); +- } +-#endif + WARN_ON_ONCE(!list_empty(&ctx->ltimeout_list)); + + io_alloc_cache_free(&ctx->rsrc_node_cache, io_rsrc_node_cache_free); +@@ -3825,32 +3817,12 @@ static int io_uring_install_fd(struct file *file) + /* + * Allocate an anonymous fd, this is what constitutes the application + * visible backing of an io_uring instance. The application mmaps this +- * fd to gain access to the SQ/CQ ring details. If UNIX sockets are enabled, +- * we have to tie this fd to a socket for file garbage collection purposes. ++ * fd to gain access to the SQ/CQ ring details. + */ + static struct file *io_uring_get_file(struct io_ring_ctx *ctx) + { +- struct file *file; +-#if defined(CONFIG_UNIX) +- int ret; +- +- ret = sock_create_kern(&init_net, PF_UNIX, SOCK_RAW, IPPROTO_IP, +- &ctx->ring_sock); +- if (ret) +- return ERR_PTR(ret); +-#endif +- +- file = anon_inode_getfile_secure("[io_uring]", &io_uring_fops, ctx, ++ return anon_inode_getfile_secure("[io_uring]", &io_uring_fops, ctx, + O_RDWR | O_CLOEXEC, NULL); +-#if defined(CONFIG_UNIX) +- if (IS_ERR(file)) { +- sock_release(ctx->ring_sock); +- ctx->ring_sock = NULL; +- } else { +- ctx->ring_sock->file = file; +- } +-#endif +- return file; + } + + static __cold int io_uring_create(unsigned entries, struct io_uring_params *p, +diff --git a/io_uring/rsrc.c b/io_uring/rsrc.c +index dde501abd7196..95230921b16d0 100644 +--- a/io_uring/rsrc.c ++++ b/io_uring/rsrc.c +@@ -24,7 +24,6 @@ struct io_rsrc_update { + }; + + static void io_rsrc_buf_put(struct io_ring_ctx *ctx, struct io_rsrc_put *prsrc); +-static void io_rsrc_file_put(struct io_ring_ctx *ctx, struct io_rsrc_put *prsrc); + static int io_sqe_buffer_register(struct io_ring_ctx *ctx, struct iovec *iov, + struct io_mapped_ubuf **pimu, + struct page **last_hpage); +@@ -157,7 +156,7 @@ static void io_rsrc_put_work(struct io_rsrc_node *node) + + switch (node->type) { + case IORING_RSRC_FILE: +- io_rsrc_file_put(node->ctx, prsrc); ++ fput(prsrc->file); + break; + case IORING_RSRC_BUFFER: + io_rsrc_buf_put(node->ctx, prsrc); +@@ -402,23 +401,13 @@ static int __io_sqe_files_update(struct io_ring_ctx *ctx, + break; + } + /* +- * Don't allow io_uring instances to be registered. If +- * UNIX isn't enabled, then this causes a reference +- * cycle and this instance can never get freed. If UNIX +- * is enabled we'll handle it just fine, but there's +- * still no point in allowing a ring fd as it doesn't +- * support regular read/write anyway. ++ * Don't allow io_uring instances to be registered. + */ + if (io_is_uring_fops(file)) { + fput(file); + err = -EBADF; + break; + } +- err = io_scm_file_account(ctx, file); +- if (err) { +- fput(file); +- break; +- } + *io_get_tag_slot(data, i) = tag; + io_fixed_file_set(file_slot, file); + io_file_bitmap_set(&ctx->file_table, i); +@@ -675,22 +664,12 @@ void __io_sqe_files_unregister(struct io_ring_ctx *ctx) + for (i = 0; i < ctx->nr_user_files; i++) { + struct file *file = io_file_from_index(&ctx->file_table, i); + +- /* skip scm accounted files, they'll be freed by ->ring_sock */ +- if (!file || io_file_need_scm(file)) ++ if (!file) + continue; + io_file_bitmap_clear(&ctx->file_table, i); + fput(file); + } + +-#if defined(CONFIG_UNIX) +- if (ctx->ring_sock) { +- struct sock *sock = ctx->ring_sock->sk; +- struct sk_buff *skb; +- +- while ((skb = skb_dequeue(&sock->sk_receive_queue)) != NULL) +- kfree_skb(skb); +- } +-#endif + io_free_file_tables(&ctx->file_table); + io_file_table_set_alloc_range(ctx, 0, 0); + io_rsrc_data_free(ctx->file_data); +@@ -718,137 +697,6 @@ int io_sqe_files_unregister(struct io_ring_ctx *ctx) + return ret; + } + +-/* +- * Ensure the UNIX gc is aware of our file set, so we are certain that +- * the io_uring can be safely unregistered on process exit, even if we have +- * loops in the file referencing. We account only files that can hold other +- * files because otherwise they can't form a loop and so are not interesting +- * for GC. +- */ +-int __io_scm_file_account(struct io_ring_ctx *ctx, struct file *file) +-{ +-#if defined(CONFIG_UNIX) +- struct sock *sk = ctx->ring_sock->sk; +- struct sk_buff_head *head = &sk->sk_receive_queue; +- struct scm_fp_list *fpl; +- struct sk_buff *skb; +- +- if (likely(!io_file_need_scm(file))) +- return 0; +- +- /* +- * See if we can merge this file into an existing skb SCM_RIGHTS +- * file set. If there's no room, fall back to allocating a new skb +- * and filling it in. +- */ +- spin_lock_irq(&head->lock); +- skb = skb_peek(head); +- if (skb && UNIXCB(skb).fp->count < SCM_MAX_FD) +- __skb_unlink(skb, head); +- else +- skb = NULL; +- spin_unlock_irq(&head->lock); +- +- if (!skb) { +- fpl = kzalloc(sizeof(*fpl), GFP_KERNEL); +- if (!fpl) +- return -ENOMEM; +- +- skb = alloc_skb(0, GFP_KERNEL); +- if (!skb) { +- kfree(fpl); +- return -ENOMEM; +- } +- +- fpl->user = get_uid(current_user()); +- fpl->max = SCM_MAX_FD; +- fpl->count = 0; +- +- UNIXCB(skb).fp = fpl; +- skb->sk = sk; +- skb->destructor = io_uring_destruct_scm; +- refcount_add(skb->truesize, &sk->sk_wmem_alloc); +- } +- +- fpl = UNIXCB(skb).fp; +- fpl->fp[fpl->count++] = get_file(file); +- unix_inflight(fpl->user, file); +- skb_queue_head(head, skb); +- fput(file); +-#endif +- return 0; +-} +- +-static __cold void io_rsrc_file_scm_put(struct io_ring_ctx *ctx, struct file *file) +-{ +-#if defined(CONFIG_UNIX) +- struct sock *sock = ctx->ring_sock->sk; +- struct sk_buff_head list, *head = &sock->sk_receive_queue; +- struct sk_buff *skb; +- int i; +- +- __skb_queue_head_init(&list); +- +- /* +- * Find the skb that holds this file in its SCM_RIGHTS. When found, +- * remove this entry and rearrange the file array. +- */ +- skb = skb_dequeue(head); +- while (skb) { +- struct scm_fp_list *fp; +- +- fp = UNIXCB(skb).fp; +- for (i = 0; i < fp->count; i++) { +- int left; +- +- if (fp->fp[i] != file) +- continue; +- +- unix_notinflight(fp->user, fp->fp[i]); +- left = fp->count - 1 - i; +- if (left) { +- memmove(&fp->fp[i], &fp->fp[i + 1], +- left * sizeof(struct file *)); +- } +- fp->count--; +- if (!fp->count) { +- kfree_skb(skb); +- skb = NULL; +- } else { +- __skb_queue_tail(&list, skb); +- } +- fput(file); +- file = NULL; +- break; +- } +- +- if (!file) +- break; +- +- __skb_queue_tail(&list, skb); +- +- skb = skb_dequeue(head); +- } +- +- if (skb_peek(&list)) { +- spin_lock_irq(&head->lock); +- while ((skb = __skb_dequeue(&list)) != NULL) +- __skb_queue_tail(head, skb); +- spin_unlock_irq(&head->lock); +- } +-#endif +-} +- +-static void io_rsrc_file_put(struct io_ring_ctx *ctx, struct io_rsrc_put *prsrc) +-{ +- struct file *file = prsrc->file; +- +- if (likely(!io_file_need_scm(file))) +- fput(file); +- else +- io_rsrc_file_scm_put(ctx, file); +-} +- + int io_sqe_files_register(struct io_ring_ctx *ctx, void __user *arg, + unsigned nr_args, u64 __user *tags) + { +@@ -897,21 +745,12 @@ int io_sqe_files_register(struct io_ring_ctx *ctx, void __user *arg, + goto fail; + + /* +- * Don't allow io_uring instances to be registered. If UNIX +- * isn't enabled, then this causes a reference cycle and this +- * instance can never get freed. If UNIX is enabled we'll +- * handle it just fine, but there's still no point in allowing +- * a ring fd as it doesn't support regular read/write anyway. ++ * Don't allow io_uring instances to be registered. + */ + if (io_is_uring_fops(file)) { + fput(file); + goto fail; + } +- ret = io_scm_file_account(ctx, file); +- if (ret) { +- fput(file); +- goto fail; +- } + file_slot = io_fixed_file_slot(&ctx->file_table, i); + io_fixed_file_set(file_slot, file); + io_file_bitmap_set(&ctx->file_table, i); +diff --git a/io_uring/rsrc.h b/io_uring/rsrc.h +index 08ac0d8e07ef8..7238b9cfe33b6 100644 +--- a/io_uring/rsrc.h ++++ b/io_uring/rsrc.h +@@ -75,21 +75,6 @@ int io_sqe_files_unregister(struct io_ring_ctx *ctx); + int io_sqe_files_register(struct io_ring_ctx *ctx, void __user *arg, + unsigned nr_args, u64 __user *tags); + +-int __io_scm_file_account(struct io_ring_ctx *ctx, struct file *file); +- +-static inline bool io_file_need_scm(struct file *filp) +-{ +- return false; +-} +- +-static inline int io_scm_file_account(struct io_ring_ctx *ctx, +- struct file *file) +-{ +- if (likely(!io_file_need_scm(file))) +- return 0; +- return __io_scm_file_account(ctx, file); +-} +- + int io_register_files_update(struct io_ring_ctx *ctx, void __user *arg, + unsigned nr_args); + int io_register_rsrc_update(struct io_ring_ctx *ctx, void __user *arg, +-- +2.43.0 + diff --git a/queue-6.6/io_uring-unix-drop-usage-of-io_uring-socket.patch b/queue-6.6/io_uring-unix-drop-usage-of-io_uring-socket.patch new file mode 100644 index 00000000000..780fcdc766e --- /dev/null +++ b/queue-6.6/io_uring-unix-drop-usage-of-io_uring-socket.patch @@ -0,0 +1,137 @@ +From 521ce28ae486366685cf7830cb559598eef3d1d1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 19 Dec 2023 12:30:43 -0700 +Subject: io_uring/unix: drop usage of io_uring socket + +From: Jens Axboe + +Commit a4104821ad651d8a0b374f0b2474c345bbb42f82 upstream. + +Since we no longer allow sending io_uring fds over SCM_RIGHTS, move to +using io_is_uring_fops() to detect whether this is a io_uring fd or not. +With that done, kill off io_uring_get_socket() as nobody calls it +anymore. + +This is in preparation to yanking out the rest of the core related to +unix gc with io_uring. + +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + include/linux/io_uring.h | 10 +++++----- + io_uring/io_uring.c | 13 ------------- + io_uring/io_uring.h | 1 - + net/core/scm.c | 2 +- + net/unix/scm.c | 4 +--- + 5 files changed, 7 insertions(+), 23 deletions(-) + +diff --git a/include/linux/io_uring.h b/include/linux/io_uring.h +index 106cdc55ff3bd..f99ff6de926cb 100644 +--- a/include/linux/io_uring.h ++++ b/include/linux/io_uring.h +@@ -46,7 +46,6 @@ int io_uring_cmd_import_fixed(u64 ubuf, unsigned long len, int rw, + struct iov_iter *iter, void *ioucmd); + void io_uring_cmd_done(struct io_uring_cmd *cmd, ssize_t ret, ssize_t res2, + unsigned issue_flags); +-struct sock *io_uring_get_socket(struct file *file); + void __io_uring_cancel(bool cancel_all); + void __io_uring_free(struct task_struct *tsk); + void io_uring_unreg_ringfd(void); +@@ -82,6 +81,7 @@ static inline void io_uring_free(struct task_struct *tsk) + __io_uring_free(tsk); + } + int io_uring_cmd_sock(struct io_uring_cmd *cmd, unsigned int issue_flags); ++bool io_is_uring_fops(struct file *file); + #else + static inline int io_uring_cmd_import_fixed(u64 ubuf, unsigned long len, int rw, + struct iov_iter *iter, void *ioucmd) +@@ -100,10 +100,6 @@ static inline void io_uring_cmd_do_in_task_lazy(struct io_uring_cmd *ioucmd, + void (*task_work_cb)(struct io_uring_cmd *, unsigned)) + { + } +-static inline struct sock *io_uring_get_socket(struct file *file) +-{ +- return NULL; +-} + static inline void io_uring_task_cancel(void) + { + } +@@ -122,6 +118,10 @@ static inline int io_uring_cmd_sock(struct io_uring_cmd *cmd, + { + return -EOPNOTSUPP; + } ++static inline bool io_is_uring_fops(struct file *file) ++{ ++ return false; ++} + #endif + + #endif +diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c +index ea772a02c1405..747d2a6ecab89 100644 +--- a/io_uring/io_uring.c ++++ b/io_uring/io_uring.c +@@ -175,19 +175,6 @@ static struct ctl_table kernel_io_uring_disabled_table[] = { + }; + #endif + +-struct sock *io_uring_get_socket(struct file *file) +-{ +-#if defined(CONFIG_UNIX) +- if (io_is_uring_fops(file)) { +- struct io_ring_ctx *ctx = file->private_data; +- +- return ctx->ring_sock->sk; +- } +-#endif +- return NULL; +-} +-EXPORT_SYMBOL(io_uring_get_socket); +- + static inline void io_submit_flush_completions(struct io_ring_ctx *ctx) + { + if (!wq_list_empty(&ctx->submit_state.compl_reqs) || +diff --git a/io_uring/io_uring.h b/io_uring/io_uring.h +index c8cba78310831..411c883b37a95 100644 +--- a/io_uring/io_uring.h ++++ b/io_uring/io_uring.h +@@ -61,7 +61,6 @@ struct file *io_file_get_fixed(struct io_kiocb *req, int fd, + unsigned issue_flags); + + void __io_req_task_work_add(struct io_kiocb *req, unsigned flags); +-bool io_is_uring_fops(struct file *file); + bool io_alloc_async_data(struct io_kiocb *req); + void io_req_task_queue(struct io_kiocb *req); + void io_queue_iowq(struct io_kiocb *req, struct io_tw_state *ts_dont_use); +diff --git a/net/core/scm.c b/net/core/scm.c +index 7dc47c17d8638..737917c7ac627 100644 +--- a/net/core/scm.c ++++ b/net/core/scm.c +@@ -105,7 +105,7 @@ static int scm_fp_copy(struct cmsghdr *cmsg, struct scm_fp_list **fplp) + if (fd < 0 || !(file = fget_raw(fd))) + return -EBADF; + /* don't allow io_uring files */ +- if (io_uring_get_socket(file)) { ++ if (io_is_uring_fops(file)) { + fput(file); + return -EINVAL; + } +diff --git a/net/unix/scm.c b/net/unix/scm.c +index 6ff628f2349f5..822ce0d0d7915 100644 +--- a/net/unix/scm.c ++++ b/net/unix/scm.c +@@ -35,10 +35,8 @@ struct sock *unix_get_socket(struct file *filp) + /* PF_UNIX ? */ + if (s && ops && ops->family == PF_UNIX) + u_sock = s; +- } else { +- /* Could be an io_uring instance */ +- u_sock = io_uring_get_socket(filp); + } ++ + return u_sock; + } + EXPORT_SYMBOL(unix_get_socket); +-- +2.43.0 + diff --git a/queue-6.6/platform-x86-p2sb-on-goldmont-only-cache-p2sb-and-sp.patch b/queue-6.6/platform-x86-p2sb-on-goldmont-only-cache-p2sb-and-sp.patch new file mode 100644 index 00000000000..94c365b91e2 --- /dev/null +++ b/queue-6.6/platform-x86-p2sb-on-goldmont-only-cache-p2sb-and-sp.patch @@ -0,0 +1,81 @@ +From bdb8742175babcb3e4c121d76a65247b394600c0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Mar 2024 14:43:55 +0100 +Subject: platform/x86: p2sb: On Goldmont only cache P2SB and SPI devfn BAR + +From: Hans de Goede + +[ Upstream commit aec7d25b497ce4a8d044e9496de0aa433f7f8f06 ] + +On Goldmont p2sb_bar() only ever gets called for 2 devices, the actual P2SB +devfn 13,0 and the SPI controller which is part of the P2SB, devfn 13,2. + +But the current p2sb code tries to cache BAR0 info for all of +devfn 13,0 to 13,7 . This involves calling pci_scan_single_device() +for device 13 functions 0-7 and the hw does not seem to like +pci_scan_single_device() getting called for some of the other hidden +devices. E.g. on an ASUS VivoBook D540NV-GQ065T this leads to continuous +ACPI errors leading to high CPU usage. + +Fix this by only caching BAR0 info and thus only calling +pci_scan_single_device() for the P2SB and the SPI controller. + +Fixes: 5913320eb0b3 ("platform/x86: p2sb: Allow p2sb_bar() calls during PCI device probe") +Reported-by: Danil Rybakov +Closes: https://bugzilla.kernel.org/show_bug.cgi?id=218531 +Tested-by: Danil Rybakov +Signed-off-by: Hans de Goede +Link: https://lore.kernel.org/r/20240304134356.305375-2-hdegoede@redhat.com +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/p2sb.c | 25 +++++++++---------------- + 1 file changed, 9 insertions(+), 16 deletions(-) + +diff --git a/drivers/platform/x86/p2sb.c b/drivers/platform/x86/p2sb.c +index 17cc4b45e0239..a64f56ddd4a44 100644 +--- a/drivers/platform/x86/p2sb.c ++++ b/drivers/platform/x86/p2sb.c +@@ -20,9 +20,11 @@ + #define P2SBC_HIDE BIT(8) + + #define P2SB_DEVFN_DEFAULT PCI_DEVFN(31, 1) ++#define P2SB_DEVFN_GOLDMONT PCI_DEVFN(13, 0) ++#define SPI_DEVFN_GOLDMONT PCI_DEVFN(13, 2) + + static const struct x86_cpu_id p2sb_cpu_ids[] = { +- X86_MATCH_INTEL_FAM6_MODEL(ATOM_GOLDMONT, PCI_DEVFN(13, 0)), ++ X86_MATCH_INTEL_FAM6_MODEL(ATOM_GOLDMONT, P2SB_DEVFN_GOLDMONT), + {} + }; + +@@ -98,21 +100,12 @@ static void p2sb_scan_and_cache_devfn(struct pci_bus *bus, unsigned int devfn) + + static int p2sb_scan_and_cache(struct pci_bus *bus, unsigned int devfn) + { +- unsigned int slot, fn; +- +- if (PCI_FUNC(devfn) == 0) { +- /* +- * When function number of the P2SB device is zero, scan it and +- * other function numbers, and if devices are available, cache +- * their BAR0s. +- */ +- slot = PCI_SLOT(devfn); +- for (fn = 0; fn < NR_P2SB_RES_CACHE; fn++) +- p2sb_scan_and_cache_devfn(bus, PCI_DEVFN(slot, fn)); +- } else { +- /* Scan the P2SB device and cache its BAR0 */ +- p2sb_scan_and_cache_devfn(bus, devfn); +- } ++ /* Scan the P2SB device and cache its BAR0 */ ++ p2sb_scan_and_cache_devfn(bus, devfn); ++ ++ /* On Goldmont p2sb_bar() also gets called for the SPI controller */ ++ if (devfn == P2SB_DEVFN_GOLDMONT) ++ p2sb_scan_and_cache_devfn(bus, SPI_DEVFN_GOLDMONT); + + if (!p2sb_valid_resource(&p2sb_resources[PCI_FUNC(devfn)].res)) + return -ENOENT; +-- +2.43.0 + diff --git a/queue-6.6/series b/queue-6.6/series new file mode 100644 index 00000000000..82d86f23690 --- /dev/null +++ b/queue-6.6/series @@ -0,0 +1,4 @@ +platform-x86-p2sb-on-goldmont-only-cache-p2sb-and-sp.patch +io_uring-unix-drop-usage-of-io_uring-socket.patch +io_uring-drop-any-code-related-to-scm_rights.patch +soc-qcom-pmic_glink_altmode-fix-drm-bridge-use-after.patch diff --git a/queue-6.6/soc-qcom-pmic_glink_altmode-fix-drm-bridge-use-after.patch b/queue-6.6/soc-qcom-pmic_glink_altmode-fix-drm-bridge-use-after.patch new file mode 100644 index 00000000000..210cf0bb65e --- /dev/null +++ b/queue-6.6/soc-qcom-pmic_glink_altmode-fix-drm-bridge-use-after.patch @@ -0,0 +1,111 @@ +From 3dd08420bf5ec79da8a16b5ce5e655202dfac663 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 8 Mar 2024 10:03:57 +0100 +Subject: soc: qcom: pmic_glink_altmode: fix drm bridge use-after-free + +From: Johan Hovold + +commit b979f2d50a099f3402418d7ff5f26c3952fb08bb upstream. + +A recent DRM series purporting to simplify support for "transparent +bridges" and handling of probe deferrals ironically exposed a +use-after-free issue on pmic_glink_altmode probe deferral. + +This has manifested itself as the display subsystem occasionally failing +to initialise and NULL-pointer dereferences during boot of machines like +the Lenovo ThinkPad X13s. + +Specifically, the dp-hpd bridge is currently registered before all +resources have been acquired which means that it can also be +deregistered on probe deferrals. + +In the meantime there is a race window where the new aux bridge driver +(or PHY driver previously) may have looked up the dp-hpd bridge and +stored a (non-reference-counted) pointer to the bridge which is about to +be deallocated. + +When the display controller is later initialised, this triggers a +use-after-free when attaching the bridges: + + dp -> aux -> dp-hpd (freed) + +which may, for example, result in the freed bridge failing to attach: + + [drm:drm_bridge_attach [drm]] *ERROR* failed to attach bridge /soc@0/phy@88eb000 to encoder TMDS-31: -16 + +or a NULL-pointer dereference: + + Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000 + ... + Call trace: + drm_bridge_attach+0x70/0x1a8 [drm] + drm_aux_bridge_attach+0x24/0x38 [aux_bridge] + drm_bridge_attach+0x80/0x1a8 [drm] + dp_bridge_init+0xa8/0x15c [msm] + msm_dp_modeset_init+0x28/0xc4 [msm] + +The DRM bridge implementation is clearly fragile and implicitly built on +the assumption that bridges may never go away. In this case, the fix is +to move the bridge registration in the pmic_glink_altmode driver to +after all resources have been looked up. + +Incidentally, with the new dp-hpd bridge implementation, which registers +child devices, this is also a requirement due to a long-standing issue +in driver core that can otherwise lead to a probe deferral loop (see +commit fbc35b45f9f6 ("Add documentation on meaning of -EPROBE_DEFER")). + +[DB: slightly fixed commit message by adding the word 'commit'] +Fixes: 080b4e24852b ("soc: qcom: pmic_glink: Introduce altmode support") +Fixes: 2bcca96abfbf ("soc: qcom: pmic-glink: switch to DRM_AUX_HPD_BRIDGE") +Cc: # 6.3 +Cc: Bjorn Andersson +Cc: Dmitry Baryshkov +Signed-off-by: Johan Hovold +Reviewed-by: Bjorn Andersson +Reviewed-by: Dmitry Baryshkov +Signed-off-by: Dmitry Baryshkov +Link: https://patchwork.freedesktop.org/patch/msgid/20240217150228.5788-4-johan+linaro@kernel.org +[ johan: backport to 6.7 which does not have DRM aux bridge ] +Signed-off-by: Johan Hovold +Signed-off-by: Sasha Levin +--- + drivers/soc/qcom/pmic_glink_altmode.c | 16 ++++++++++------ + 1 file changed, 10 insertions(+), 6 deletions(-) + +diff --git a/drivers/soc/qcom/pmic_glink_altmode.c b/drivers/soc/qcom/pmic_glink_altmode.c +index 9b0000b5f064c..a35df66bb07b5 100644 +--- a/drivers/soc/qcom/pmic_glink_altmode.c ++++ b/drivers/soc/qcom/pmic_glink_altmode.c +@@ -469,12 +469,6 @@ static int pmic_glink_altmode_probe(struct auxiliary_device *adev, + alt_port->bridge.ops = DRM_BRIDGE_OP_HPD; + alt_port->bridge.type = DRM_MODE_CONNECTOR_DisplayPort; + +- ret = devm_drm_bridge_add(dev, &alt_port->bridge); +- if (ret) { +- fwnode_handle_put(fwnode); +- return ret; +- } +- + alt_port->dp_alt.svid = USB_TYPEC_DP_SID; + alt_port->dp_alt.mode = USB_TYPEC_DP_MODE; + alt_port->dp_alt.active = 1; +@@ -525,6 +519,16 @@ static int pmic_glink_altmode_probe(struct auxiliary_device *adev, + } + } + ++ for (port = 0; port < ARRAY_SIZE(altmode->ports); port++) { ++ alt_port = &altmode->ports[port]; ++ if (!alt_port->altmode) ++ continue; ++ ++ ret = devm_drm_bridge_add(dev, &alt_port->bridge); ++ if (ret) ++ return ret; ++ } ++ + altmode->client = devm_pmic_glink_register_client(dev, + altmode->owner_id, + pmic_glink_altmode_callback, +-- +2.43.0 +