]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 6.6
authorSasha Levin <sashal@kernel.org>
Mon, 18 Mar 2024 00:20:44 +0000 (20:20 -0400)
committerSasha Levin <sashal@kernel.org>
Mon, 18 Mar 2024 00:20:44 +0000 (20:20 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-6.6/io_uring-drop-any-code-related-to-scm_rights.patch [new file with mode: 0644]
queue-6.6/io_uring-unix-drop-usage-of-io_uring-socket.patch [new file with mode: 0644]
queue-6.6/platform-x86-p2sb-on-goldmont-only-cache-p2sb-and-sp.patch [new file with mode: 0644]
queue-6.6/series [new file with mode: 0644]
queue-6.6/soc-qcom-pmic_glink_altmode-fix-drm-bridge-use-after.patch [new file with mode: 0644]

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 (file)
index 0000000..71ea478
--- /dev/null
@@ -0,0 +1,377 @@
+From 095e7a746ed134b8e69c8ad523d7df7f8396fd86 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 19 Dec 2023 12:36:34 -0700
+Subject: io_uring: drop any code related to SCM_RIGHTS
+
+From: Jens Axboe <axboe@kernel.dk>
+
+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 <axboe@kernel.dk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 <linux/net.h>
+ #include <net/sock.h>
+ #include <net/af_unix.h>
+-#include <net/scm.h>
+ #include <linux/anon_inodes.h>
+ #include <linux/sched/mm.h>
+ #include <linux/uaccess.h>
+@@ -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 (file)
index 0000000..780fcdc
--- /dev/null
@@ -0,0 +1,137 @@
+From 521ce28ae486366685cf7830cb559598eef3d1d1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 19 Dec 2023 12:30:43 -0700
+Subject: io_uring/unix: drop usage of io_uring socket
+
+From: Jens Axboe <axboe@kernel.dk>
+
+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 <axboe@kernel.dk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..94c365b
--- /dev/null
@@ -0,0 +1,81 @@
+From bdb8742175babcb3e4c121d76a65247b394600c0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <hdegoede@redhat.com>
+
+[ 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 <danilrybakov249@gmail.com>
+Closes: https://bugzilla.kernel.org/show_bug.cgi?id=218531
+Tested-by: Danil Rybakov <danilrybakov249@gmail.com>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Link: https://lore.kernel.org/r/20240304134356.305375-2-hdegoede@redhat.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..82d86f2
--- /dev/null
@@ -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 (file)
index 0000000..210cf0b
--- /dev/null
@@ -0,0 +1,111 @@
+From 3dd08420bf5ec79da8a16b5ce5e655202dfac663 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 8 Mar 2024 10:03:57 +0100
+Subject: soc: qcom: pmic_glink_altmode: fix drm bridge use-after-free
+
+From: Johan Hovold <johan+linaro@kernel.org>
+
+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: <stable@vger.kernel.org>      # 6.3
+Cc: Bjorn Andersson <andersson@kernel.org>
+Cc: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Signed-off-by: Johan Hovold <johan+linaro@kernel.org>
+Reviewed-by: Bjorn Andersson <andersson@kernel.org>
+Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+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 <johan+linaro@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+