]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.13-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 30 Jan 2025 09:53:13 +0000 (10:53 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 30 Jan 2025 09:53:13 +0000 (10:53 +0100)
added patches:
cachestat-fix-page-cache-statistics-permission-checking.patch
gfs2-truncate-address-space-when-flipping-gfs2_dif_jdata-flag.patch
libfs-replace-simple_offset-end-of-directory-detection.patch
libfs-return-enospc-when-the-directory-offset-range-is-exhausted.patch
libfs-use-d_children-list-to-iterate-simple_offset-directories.patch
net-sched-fix-ets-qdisc-oob-indexing.patch
revert-hid-multitouch-add-support-for-lenovo-y9000p-touchpad.patch
revert-libfs-add-simple_offset_empty.patch
revert-libfs-fix-infinite-directory-reads-for-offset-dir.patch
scsi-storvsc-ratelimit-warning-logs-to-prevent-vm-denial-of-service.patch
smb-client-handle-lack-of-ea-support-in-smb2_query_path_info.patch
vfio-platform-check-the-bounds-of-read-write-syscalls.patch

13 files changed:
queue-6.13/cachestat-fix-page-cache-statistics-permission-checking.patch [new file with mode: 0644]
queue-6.13/gfs2-truncate-address-space-when-flipping-gfs2_dif_jdata-flag.patch [new file with mode: 0644]
queue-6.13/libfs-replace-simple_offset-end-of-directory-detection.patch [new file with mode: 0644]
queue-6.13/libfs-return-enospc-when-the-directory-offset-range-is-exhausted.patch [new file with mode: 0644]
queue-6.13/libfs-use-d_children-list-to-iterate-simple_offset-directories.patch [new file with mode: 0644]
queue-6.13/net-sched-fix-ets-qdisc-oob-indexing.patch [new file with mode: 0644]
queue-6.13/revert-hid-multitouch-add-support-for-lenovo-y9000p-touchpad.patch [new file with mode: 0644]
queue-6.13/revert-libfs-add-simple_offset_empty.patch [new file with mode: 0644]
queue-6.13/revert-libfs-fix-infinite-directory-reads-for-offset-dir.patch [new file with mode: 0644]
queue-6.13/scsi-storvsc-ratelimit-warning-logs-to-prevent-vm-denial-of-service.patch [new file with mode: 0644]
queue-6.13/series
queue-6.13/smb-client-handle-lack-of-ea-support-in-smb2_query_path_info.patch [new file with mode: 0644]
queue-6.13/vfio-platform-check-the-bounds-of-read-write-syscalls.patch [new file with mode: 0644]

diff --git a/queue-6.13/cachestat-fix-page-cache-statistics-permission-checking.patch b/queue-6.13/cachestat-fix-page-cache-statistics-permission-checking.patch
new file mode 100644 (file)
index 0000000..8210336
--- /dev/null
@@ -0,0 +1,65 @@
+From 5f537664e705b0bf8b7e329861f20128534f6a83 Mon Sep 17 00:00:00 2001
+From: Linus Torvalds <torvalds@linux-foundation.org>
+Date: Tue, 21 Jan 2025 09:27:22 -0800
+Subject: cachestat: fix page cache statistics permission checking
+
+From: Linus Torvalds <torvalds@linux-foundation.org>
+
+commit 5f537664e705b0bf8b7e329861f20128534f6a83 upstream.
+
+When the 'cachestat()' system call was added in commit cf264e1329fb
+("cachestat: implement cachestat syscall"), it was meant to be a much
+more convenient (and performant) version of mincore() that didn't need
+mapping things into the user virtual address space in order to work.
+
+But it ended up missing the "check for writability or ownership" fix for
+mincore(), done in commit 134fca9063ad ("mm/mincore.c: make mincore()
+more conservative").
+
+This just adds equivalent logic to 'cachestat()', modified for the file
+context (rather than vma).
+
+Reported-by: Sudheendra Raghav Neela <sneela@tugraz.at>
+Fixes: cf264e1329fb ("cachestat: implement cachestat syscall")
+Tested-by: Johannes Weiner <hannes@cmpxchg.org>
+Acked-by: Johannes Weiner <hannes@cmpxchg.org>
+Acked-by: Nhat Pham <nphamcs@gmail.com>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/filemap.c |   17 +++++++++++++++++
+ 1 file changed, 17 insertions(+)
+
+--- a/mm/filemap.c
++++ b/mm/filemap.c
+@@ -4376,6 +4376,20 @@ resched:
+ }
+ /*
++ * See mincore: reveal pagecache information only for files
++ * that the calling process has write access to, or could (if
++ * tried) open for writing.
++ */
++static inline bool can_do_cachestat(struct file *f)
++{
++      if (f->f_mode & FMODE_WRITE)
++              return true;
++      if (inode_owner_or_capable(file_mnt_idmap(f), file_inode(f)))
++              return true;
++      return file_permission(f, MAY_WRITE) == 0;
++}
++
++/*
+  * The cachestat(2) system call.
+  *
+  * cachestat() returns the page cache statistics of a file in the
+@@ -4430,6 +4444,9 @@ SYSCALL_DEFINE4(cachestat, unsigned int,
+       if (is_file_hugepages(fd_file(f)))
+               return -EOPNOTSUPP;
++      if (!can_do_cachestat(fd_file(f)))
++              return -EPERM;
++
+       if (flags != 0)
+               return -EINVAL;
diff --git a/queue-6.13/gfs2-truncate-address-space-when-flipping-gfs2_dif_jdata-flag.patch b/queue-6.13/gfs2-truncate-address-space-when-flipping-gfs2_dif_jdata-flag.patch
new file mode 100644 (file)
index 0000000..4e0fcd6
--- /dev/null
@@ -0,0 +1,30 @@
+From 7c9d9223802fbed4dee1ae301661bf346964c9d2 Mon Sep 17 00:00:00 2001
+From: Andreas Gruenbacher <agruenba@redhat.com>
+Date: Mon, 13 Jan 2025 19:31:28 +0100
+Subject: gfs2: Truncate address space when flipping GFS2_DIF_JDATA flag
+
+From: Andreas Gruenbacher <agruenba@redhat.com>
+
+commit 7c9d9223802fbed4dee1ae301661bf346964c9d2 upstream.
+
+Truncate an inode's address space when flipping the GFS2_DIF_JDATA flag:
+depending on that flag, the pages in the address space will either use
+buffer heads or iomap_folio_state structs, and we cannot mix the two.
+
+Reported-by: Kun Hu <huk23@m.fudan.edu.cn>, Jiaji Qin <jjtan24@m.fudan.edu.cn>
+Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/gfs2/file.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/fs/gfs2/file.c
++++ b/fs/gfs2/file.c
+@@ -251,6 +251,7 @@ static int do_gfs2_set_flags(struct inod
+               error = filemap_fdatawait(inode->i_mapping);
+               if (error)
+                       goto out;
++              truncate_inode_pages(inode->i_mapping, 0);
+               if (new_flags & GFS2_DIF_JDATA)
+                       gfs2_ordered_del_inode(ip);
+       }
diff --git a/queue-6.13/libfs-replace-simple_offset-end-of-directory-detection.patch b/queue-6.13/libfs-replace-simple_offset-end-of-directory-detection.patch
new file mode 100644 (file)
index 0000000..d5d37e0
--- /dev/null
@@ -0,0 +1,149 @@
+From 68a3a65003145644efcbb651e91db249ccd96281 Mon Sep 17 00:00:00 2001
+From: Chuck Lever <chuck.lever@oracle.com>
+Date: Sat, 28 Dec 2024 12:55:20 -0500
+Subject: libfs: Replace simple_offset end-of-directory detection
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+commit 68a3a65003145644efcbb651e91db249ccd96281 upstream.
+
+According to getdents(3), the d_off field in each returned directory
+entry points to the next entry in the directory. The d_off field in
+the last returned entry in the readdir buffer must contain a valid
+offset value, but if it points to an actual directory entry, then
+readdir/getdents can loop.
+
+This patch introduces a specific fixed offset value that is placed
+in the d_off field of the last entry in a directory. Some user space
+applications assume that the EOD offset value is larger than the
+offsets of real directory entries, so the largest valid offset value
+is reserved for this purpose. This new value is never allocated by
+simple_offset_add().
+
+When ->iterate_dir() returns, getdents{64} inserts the ctx->pos
+value into the d_off field of the last valid entry in the readdir
+buffer. When it hits EOD, offset_readdir() sets ctx->pos to the EOD
+offset value so the last entry is updated to point to the EOD marker.
+
+When trying to read the entry at the EOD offset, offset_readdir()
+terminates immediately.
+
+It is worth noting that using a Maple tree for directory offset
+value allocation does not guarantee a 63-bit range of values --
+on platforms where "long" is a 32-bit type, the directory offset
+value range is still 0..(2^31 - 1). For broad compatibility with
+32-bit user space, the largest tmpfs directory cookie value is now
+S32_MAX.
+
+Fixes: 796432efab1e ("libfs: getdents() should return 0 after reaching EOD")
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Link: https://lore.kernel.org/r/20241228175522.1854234-5-cel@kernel.org
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/libfs.c |   37 +++++++++++++++++++++----------------
+ 1 file changed, 21 insertions(+), 16 deletions(-)
+
+--- a/fs/libfs.c
++++ b/fs/libfs.c
+@@ -245,9 +245,15 @@ const struct inode_operations simple_dir
+ };
+ EXPORT_SYMBOL(simple_dir_inode_operations);
+-/* 0 is '.', 1 is '..', so always start with offset 2 or more */
++/* simple_offset_add() never assigns these to a dentry */
+ enum {
+-      DIR_OFFSET_MIN  = 2,
++      DIR_OFFSET_EOD          = S32_MAX,
++};
++
++/* simple_offset_add() allocation range */
++enum {
++      DIR_OFFSET_MIN          = 2,
++      DIR_OFFSET_MAX          = DIR_OFFSET_EOD - 1,
+ };
+ static void offset_set(struct dentry *dentry, long offset)
+@@ -291,7 +297,8 @@ int simple_offset_add(struct offset_ctx
+               return -EBUSY;
+       ret = mtree_alloc_cyclic(&octx->mt, &offset, dentry, DIR_OFFSET_MIN,
+-                               LONG_MAX, &octx->next_offset, GFP_KERNEL);
++                               DIR_OFFSET_MAX, &octx->next_offset,
++                               GFP_KERNEL);
+       if (unlikely(ret < 0))
+               return ret == -EBUSY ? -ENOSPC : ret;
+@@ -447,8 +454,6 @@ static loff_t offset_dir_llseek(struct f
+               return -EINVAL;
+       }
+-      /* In this case, ->private_data is protected by f_pos_lock */
+-      file->private_data = NULL;
+       return vfs_setpos(file, offset, LONG_MAX);
+ }
+@@ -458,7 +463,7 @@ static struct dentry *offset_find_next(s
+       struct dentry *child, *found = NULL;
+       rcu_read_lock();
+-      child = mas_find(&mas, LONG_MAX);
++      child = mas_find(&mas, DIR_OFFSET_MAX);
+       if (!child)
+               goto out;
+       spin_lock(&child->d_lock);
+@@ -479,7 +484,7 @@ static bool offset_dir_emit(struct dir_c
+                         inode->i_ino, fs_umode_to_dtype(inode->i_mode));
+ }
+-static void *offset_iterate_dir(struct inode *inode, struct dir_context *ctx)
++static void offset_iterate_dir(struct inode *inode, struct dir_context *ctx)
+ {
+       struct offset_ctx *octx = inode->i_op->get_offset_ctx(inode);
+       struct dentry *dentry;
+@@ -487,7 +492,7 @@ static void *offset_iterate_dir(struct i
+       while (true) {
+               dentry = offset_find_next(octx, ctx->pos);
+               if (!dentry)
+-                      return ERR_PTR(-ENOENT);
++                      goto out_eod;
+               if (!offset_dir_emit(ctx, dentry)) {
+                       dput(dentry);
+@@ -497,7 +502,10 @@ static void *offset_iterate_dir(struct i
+               ctx->pos = dentry2offset(dentry) + 1;
+               dput(dentry);
+       }
+-      return NULL;
++      return;
++
++out_eod:
++      ctx->pos = DIR_OFFSET_EOD;
+ }
+ /**
+@@ -517,6 +525,8 @@ static void *offset_iterate_dir(struct i
+  *
+  * On return, @ctx->pos contains an offset that will read the next entry
+  * in this directory when offset_readdir() is called again with @ctx.
++ * Caller places this value in the d_off field of the last entry in the
++ * user's buffer.
+  *
+  * Return values:
+  *   %0 - Complete
+@@ -529,13 +539,8 @@ static int offset_readdir(struct file *f
+       if (!dir_emit_dots(file, ctx))
+               return 0;
+-
+-      /* In this case, ->private_data is protected by f_pos_lock */
+-      if (ctx->pos == DIR_OFFSET_MIN)
+-              file->private_data = NULL;
+-      else if (file->private_data == ERR_PTR(-ENOENT))
+-              return 0;
+-      file->private_data = offset_iterate_dir(d_inode(dir), ctx);
++      if (ctx->pos != DIR_OFFSET_EOD)
++              offset_iterate_dir(d_inode(dir), ctx);
+       return 0;
+ }
diff --git a/queue-6.13/libfs-return-enospc-when-the-directory-offset-range-is-exhausted.patch b/queue-6.13/libfs-return-enospc-when-the-directory-offset-range-is-exhausted.patch
new file mode 100644 (file)
index 0000000..5298a3f
--- /dev/null
@@ -0,0 +1,46 @@
+From 903dc9c43a155e0893280c7472d4a9a3a83d75a6 Mon Sep 17 00:00:00 2001
+From: Chuck Lever <chuck.lever@oracle.com>
+Date: Sat, 28 Dec 2024 12:55:17 -0500
+Subject: libfs: Return ENOSPC when the directory offset range is exhausted
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+commit 903dc9c43a155e0893280c7472d4a9a3a83d75a6 upstream.
+
+Testing shows that the EBUSY error return from mtree_alloc_cyclic()
+leaks into user space. The ERRORS section of "man creat(2)" says:
+
+>      EBUSY   O_EXCL was specified in flags and pathname refers
+>              to a block device that is in use by the system
+>              (e.g., it is mounted).
+
+ENOSPC is closer to what applications expect in this situation.
+
+Note that the normal range of simple directory offset values is
+2..2^63, so hitting this error is going to be rare to impossible.
+
+Fixes: 6faddda69f62 ("libfs: Add directory operations for stable offsets")
+Cc: stable@vger.kernel.org # v6.9+
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+Reviewed-by: Yang Erkun <yangerkun@huawei.com>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Link: https://lore.kernel.org/r/20241228175522.1854234-2-cel@kernel.org
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/libfs.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/fs/libfs.c
++++ b/fs/libfs.c
+@@ -292,8 +292,8 @@ int simple_offset_add(struct offset_ctx
+       ret = mtree_alloc_cyclic(&octx->mt, &offset, dentry, DIR_OFFSET_MIN,
+                                LONG_MAX, &octx->next_offset, GFP_KERNEL);
+-      if (ret < 0)
+-              return ret;
++      if (unlikely(ret < 0))
++              return ret == -EBUSY ? -ENOSPC : ret;
+       offset_set(dentry, offset);
+       return 0;
diff --git a/queue-6.13/libfs-use-d_children-list-to-iterate-simple_offset-directories.patch b/queue-6.13/libfs-use-d_children-list-to-iterate-simple_offset-directories.patch
new file mode 100644 (file)
index 0000000..15ff9f2
--- /dev/null
@@ -0,0 +1,171 @@
+From b9b588f22a0c049a14885399e27625635ae6ef91 Mon Sep 17 00:00:00 2001
+From: Chuck Lever <chuck.lever@oracle.com>
+Date: Sat, 28 Dec 2024 12:55:21 -0500
+Subject: libfs: Use d_children list to iterate simple_offset directories
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+commit b9b588f22a0c049a14885399e27625635ae6ef91 upstream.
+
+The mtree mechanism has been effective at creating directory offsets
+that are stable over multiple opendir instances. However, it has not
+been able to handle the subtleties of renames that are concurrent
+with readdir.
+
+Instead of using the mtree to emit entries in the order of their
+offset values, use it only to map incoming ctx->pos to a starting
+entry. Then use the directory's d_children list, which is already
+maintained properly by the dcache, to find the next child to emit.
+
+One of the sneaky things about this is that when the mtree-allocated
+offset value wraps (which is very rare), looking up ctx->pos++ is
+not going to find the next entry; it will return NULL. Instead, by
+following the d_children list, the offset values can appear in any
+order but all of the entries in the directory will be visited
+eventually.
+
+Note also that the readdir() is guaranteed to reach the tail of this
+list. Entries are added only at the head of d_children, and readdir
+walks from its current position in that list towards its tail.
+
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Link: https://lore.kernel.org/r/20241228175522.1854234-6-cel@kernel.org
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/libfs.c |   84 ++++++++++++++++++++++++++++++++++++++++++-------------------
+ 1 file changed, 58 insertions(+), 26 deletions(-)
+
+--- a/fs/libfs.c
++++ b/fs/libfs.c
+@@ -247,12 +247,13 @@ EXPORT_SYMBOL(simple_dir_inode_operation
+ /* simple_offset_add() never assigns these to a dentry */
+ enum {
++      DIR_OFFSET_FIRST        = 2,            /* Find first real entry */
+       DIR_OFFSET_EOD          = S32_MAX,
+ };
+ /* simple_offset_add() allocation range */
+ enum {
+-      DIR_OFFSET_MIN          = 2,
++      DIR_OFFSET_MIN          = DIR_OFFSET_FIRST + 1,
+       DIR_OFFSET_MAX          = DIR_OFFSET_EOD - 1,
+ };
+@@ -457,51 +458,82 @@ static loff_t offset_dir_llseek(struct f
+       return vfs_setpos(file, offset, LONG_MAX);
+ }
+-static struct dentry *offset_find_next(struct offset_ctx *octx, loff_t offset)
++static struct dentry *find_positive_dentry(struct dentry *parent,
++                                         struct dentry *dentry,
++                                         bool next)
++{
++      struct dentry *found = NULL;
++
++      spin_lock(&parent->d_lock);
++      if (next)
++              dentry = d_next_sibling(dentry);
++      else if (!dentry)
++              dentry = d_first_child(parent);
++      hlist_for_each_entry_from(dentry, d_sib) {
++              if (!simple_positive(dentry))
++                      continue;
++              spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
++              if (simple_positive(dentry))
++                      found = dget_dlock(dentry);
++              spin_unlock(&dentry->d_lock);
++              if (likely(found))
++                      break;
++      }
++      spin_unlock(&parent->d_lock);
++      return found;
++}
++
++static noinline_for_stack struct dentry *
++offset_dir_lookup(struct dentry *parent, loff_t offset)
+ {
+-      MA_STATE(mas, &octx->mt, offset, offset);
++      struct inode *inode = d_inode(parent);
++      struct offset_ctx *octx = inode->i_op->get_offset_ctx(inode);
+       struct dentry *child, *found = NULL;
+-      rcu_read_lock();
+-      child = mas_find(&mas, DIR_OFFSET_MAX);
+-      if (!child)
+-              goto out;
+-      spin_lock(&child->d_lock);
+-      if (simple_positive(child))
+-              found = dget_dlock(child);
+-      spin_unlock(&child->d_lock);
+-out:
+-      rcu_read_unlock();
++      MA_STATE(mas, &octx->mt, offset, offset);
++
++      if (offset == DIR_OFFSET_FIRST)
++              found = find_positive_dentry(parent, NULL, false);
++      else {
++              rcu_read_lock();
++              child = mas_find(&mas, DIR_OFFSET_MAX);
++              found = find_positive_dentry(parent, child, false);
++              rcu_read_unlock();
++      }
+       return found;
+ }
+ static bool offset_dir_emit(struct dir_context *ctx, struct dentry *dentry)
+ {
+       struct inode *inode = d_inode(dentry);
+-      long offset = dentry2offset(dentry);
+-      return ctx->actor(ctx, dentry->d_name.name, dentry->d_name.len, offset,
+-                        inode->i_ino, fs_umode_to_dtype(inode->i_mode));
++      return dir_emit(ctx, dentry->d_name.name, dentry->d_name.len,
++                      inode->i_ino, fs_umode_to_dtype(inode->i_mode));
+ }
+-static void offset_iterate_dir(struct inode *inode, struct dir_context *ctx)
++static void offset_iterate_dir(struct file *file, struct dir_context *ctx)
+ {
+-      struct offset_ctx *octx = inode->i_op->get_offset_ctx(inode);
++      struct dentry *dir = file->f_path.dentry;
+       struct dentry *dentry;
++      dentry = offset_dir_lookup(dir, ctx->pos);
++      if (!dentry)
++              goto out_eod;
+       while (true) {
+-              dentry = offset_find_next(octx, ctx->pos);
+-              if (!dentry)
+-                      goto out_eod;
++              struct dentry *next;
+-              if (!offset_dir_emit(ctx, dentry)) {
+-                      dput(dentry);
++              ctx->pos = dentry2offset(dentry);
++              if (!offset_dir_emit(ctx, dentry))
+                       break;
+-              }
+-              ctx->pos = dentry2offset(dentry) + 1;
++              next = find_positive_dentry(dir, dentry, true);
+               dput(dentry);
++
++              if (!next)
++                      goto out_eod;
++              dentry = next;
+       }
++      dput(dentry);
+       return;
+ out_eod:
+@@ -540,7 +572,7 @@ static int offset_readdir(struct file *f
+       if (!dir_emit_dots(file, ctx))
+               return 0;
+       if (ctx->pos != DIR_OFFSET_EOD)
+-              offset_iterate_dir(d_inode(dir), ctx);
++              offset_iterate_dir(file, ctx);
+       return 0;
+ }
diff --git a/queue-6.13/net-sched-fix-ets-qdisc-oob-indexing.patch b/queue-6.13/net-sched-fix-ets-qdisc-oob-indexing.patch
new file mode 100644 (file)
index 0000000..33b543d
--- /dev/null
@@ -0,0 +1,91 @@
+From d62b04fca4340a0d468d7853bd66e511935a18cb Mon Sep 17 00:00:00 2001
+From: Jamal Hadi Salim <jhs@mojatatu.com>
+Date: Sat, 11 Jan 2025 09:57:39 -0500
+Subject: net: sched: fix ets qdisc OOB Indexing
+
+From: Jamal Hadi Salim <jhs@mojatatu.com>
+
+commit d62b04fca4340a0d468d7853bd66e511935a18cb upstream.
+
+Haowei Yan <g1042620637@gmail.com> found that ets_class_from_arg() can
+index an Out-Of-Bound class in ets_class_from_arg() when passed clid of
+0. The overflow may cause local privilege escalation.
+
+ [   18.852298] ------------[ cut here ]------------
+ [   18.853271] UBSAN: array-index-out-of-bounds in net/sched/sch_ets.c:93:20
+ [   18.853743] index 18446744073709551615 is out of range for type 'ets_class [16]'
+ [   18.854254] CPU: 0 UID: 0 PID: 1275 Comm: poc Not tainted 6.12.6-dirty #17
+ [   18.854821] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014
+ [   18.856532] Call Trace:
+ [   18.857441]  <TASK>
+ [   18.858227]  dump_stack_lvl+0xc2/0xf0
+ [   18.859607]  dump_stack+0x10/0x20
+ [   18.860908]  __ubsan_handle_out_of_bounds+0xa7/0xf0
+ [   18.864022]  ets_class_change+0x3d6/0x3f0
+ [   18.864322]  tc_ctl_tclass+0x251/0x910
+ [   18.864587]  ? lock_acquire+0x5e/0x140
+ [   18.865113]  ? __mutex_lock+0x9c/0xe70
+ [   18.866009]  ? __mutex_lock+0xa34/0xe70
+ [   18.866401]  rtnetlink_rcv_msg+0x170/0x6f0
+ [   18.866806]  ? __lock_acquire+0x578/0xc10
+ [   18.867184]  ? __pfx_rtnetlink_rcv_msg+0x10/0x10
+ [   18.867503]  netlink_rcv_skb+0x59/0x110
+ [   18.867776]  rtnetlink_rcv+0x15/0x30
+ [   18.868159]  netlink_unicast+0x1c3/0x2b0
+ [   18.868440]  netlink_sendmsg+0x239/0x4b0
+ [   18.868721]  ____sys_sendmsg+0x3e2/0x410
+ [   18.869012]  ___sys_sendmsg+0x88/0xe0
+ [   18.869276]  ? rseq_ip_fixup+0x198/0x260
+ [   18.869563]  ? rseq_update_cpu_node_id+0x10a/0x190
+ [   18.869900]  ? trace_hardirqs_off+0x5a/0xd0
+ [   18.870196]  ? syscall_exit_to_user_mode+0xcc/0x220
+ [   18.870547]  ? do_syscall_64+0x93/0x150
+ [   18.870821]  ? __memcg_slab_free_hook+0x69/0x290
+ [   18.871157]  __sys_sendmsg+0x69/0xd0
+ [   18.871416]  __x64_sys_sendmsg+0x1d/0x30
+ [   18.871699]  x64_sys_call+0x9e2/0x2670
+ [   18.871979]  do_syscall_64+0x87/0x150
+ [   18.873280]  ? do_syscall_64+0x93/0x150
+ [   18.874742]  ? lock_release+0x7b/0x160
+ [   18.876157]  ? do_user_addr_fault+0x5ce/0x8f0
+ [   18.877833]  ? irqentry_exit_to_user_mode+0xc2/0x210
+ [   18.879608]  ? irqentry_exit+0x77/0xb0
+ [   18.879808]  ? clear_bhb_loop+0x15/0x70
+ [   18.880023]  ? clear_bhb_loop+0x15/0x70
+ [   18.880223]  ? clear_bhb_loop+0x15/0x70
+ [   18.880426]  entry_SYSCALL_64_after_hwframe+0x76/0x7e
+ [   18.880683] RIP: 0033:0x44a957
+ [   18.880851] Code: ff ff e8 fc 00 00 00 66 2e 0f 1f 84 00 00 00 00 00 66 90 f3 0f 1e fa 64 8b 04 25 18 00 00 00 85 c0 75 10 b8 2e 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 51 c3 48 83 ec 28 89 54 24 1c 48 8974 24 10
+ [   18.881766] RSP: 002b:00007ffcdd00fad8 EFLAGS: 00000246 ORIG_RAX: 000000000000002e
+ [   18.882149] RAX: ffffffffffffffda RBX: 00007ffcdd010db8 RCX: 000000000044a957
+ [   18.882507] RDX: 0000000000000000 RSI: 00007ffcdd00fb70 RDI: 0000000000000003
+ [   18.885037] RBP: 00007ffcdd010bc0 R08: 000000000703c770 R09: 000000000703c7c0
+ [   18.887203] R10: 0000000000000080 R11: 0000000000000246 R12: 0000000000000001
+ [   18.888026] R13: 00007ffcdd010da8 R14: 00000000004ca7d0 R15: 0000000000000001
+ [   18.888395]  </TASK>
+ [   18.888610] ---[ end trace ]---
+
+Fixes: dcc68b4d8084 ("net: sch_ets: Add a new Qdisc")
+Reported-by: Haowei Yan <g1042620637@gmail.com>
+Suggested-by: Haowei Yan <g1042620637@gmail.com>
+Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Petr Machata <petrm@nvidia.com>
+Link: https://patch.msgid.link/20250111145740.74755-1-jhs@mojatatu.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/sched/sch_ets.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/net/sched/sch_ets.c
++++ b/net/sched/sch_ets.c
+@@ -91,6 +91,8 @@ ets_class_from_arg(struct Qdisc *sch, un
+ {
+       struct ets_sched *q = qdisc_priv(sch);
++      if (arg == 0 || arg > q->nbands)
++              return NULL;
+       return &q->classes[arg - 1];
+ }
diff --git a/queue-6.13/revert-hid-multitouch-add-support-for-lenovo-y9000p-touchpad.patch b/queue-6.13/revert-hid-multitouch-add-support-for-lenovo-y9000p-touchpad.patch
new file mode 100644 (file)
index 0000000..5b163f8
--- /dev/null
@@ -0,0 +1,76 @@
+From 3d88ba86ba6f35a0467f25a88c38aa5639190d04 Mon Sep 17 00:00:00 2001
+From: Jiri Kosina <jkosina@suse.com>
+Date: Thu, 12 Dec 2024 09:53:10 +0100
+Subject: Revert "HID: multitouch: Add support for lenovo Y9000P Touchpad"
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Jiri Kosina <jkosina@suse.com>
+
+commit 3d88ba86ba6f35a0467f25a88c38aa5639190d04 upstream.
+
+This reverts commit 251efae73bd46b097deec4f9986d926813aed744.
+
+Quoting Wang Yuli:
+
+       "The 27C6:01E0 touchpad doesn't require the workaround and applying it
+       would actually break functionality.
+
+       The initial report came from a BBS forum, but we suspect the
+       information provided by the forum user may be incorrect which could
+       happen sometimes. [1]
+
+       Further investigation showed that the Lenovo Y9000P 2024 doesn't even
+       use a Goodix touchpad. [2]
+
+       For the broader issue of 27c6:01e0 being unusable on some devices, it
+       just need to address it with a libinput quirk.
+
+       In conclusion, we should revert this commit, which is the best
+       solution."
+
+Reported-by: Ulrich Müller <ulm@gentoo.org>
+Reported-by: WangYuli <wangyuli@uniontech.com>
+Link: https://lore.kernel.org/all/uikt4wwpw@gentoo.org/
+Signed-off-by: Jiri Kosina <jkosina@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/hid/hid-ids.h        |    1 -
+ drivers/hid/hid-multitouch.c |    8 ++------
+ 2 files changed, 2 insertions(+), 7 deletions(-)
+
+--- a/drivers/hid/hid-ids.h
++++ b/drivers/hid/hid-ids.h
+@@ -506,7 +506,6 @@
+ #define USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_E100 0xe100
+ #define I2C_VENDOR_ID_GOODIX          0x27c6
+-#define I2C_DEVICE_ID_GOODIX_01E0     0x01e0
+ #define I2C_DEVICE_ID_GOODIX_01E8     0x01e8
+ #define I2C_DEVICE_ID_GOODIX_01E9     0x01e9
+ #define I2C_DEVICE_ID_GOODIX_01F0     0x01f0
+--- a/drivers/hid/hid-multitouch.c
++++ b/drivers/hid/hid-multitouch.c
+@@ -1460,8 +1460,7 @@ static const __u8 *mt_report_fixup(struc
+ {
+       if (hdev->vendor == I2C_VENDOR_ID_GOODIX &&
+           (hdev->product == I2C_DEVICE_ID_GOODIX_01E8 ||
+-           hdev->product == I2C_DEVICE_ID_GOODIX_01E9 ||
+-               hdev->product == I2C_DEVICE_ID_GOODIX_01E0)) {
++           hdev->product == I2C_DEVICE_ID_GOODIX_01E9)) {
+               if (rdesc[607] == 0x15) {
+                       rdesc[607] = 0x25;
+                       dev_info(
+@@ -2085,10 +2084,7 @@ static const struct hid_device_id mt_dev
+                    I2C_DEVICE_ID_GOODIX_01E8) },
+       { .driver_data = MT_CLS_WIN_8_FORCE_MULTI_INPUT_NSMU,
+         HID_DEVICE(BUS_I2C, HID_GROUP_ANY, I2C_VENDOR_ID_GOODIX,
+-                   I2C_DEVICE_ID_GOODIX_01E9) },
+-      { .driver_data = MT_CLS_WIN_8_FORCE_MULTI_INPUT_NSMU,
+-        HID_DEVICE(BUS_I2C, HID_GROUP_ANY, I2C_VENDOR_ID_GOODIX,
+-                   I2C_DEVICE_ID_GOODIX_01E0) },
++                   I2C_DEVICE_ID_GOODIX_01E8) },
+       /* GoodTouch panels */
+       { .driver_data = MT_CLS_NSMU,
diff --git a/queue-6.13/revert-libfs-add-simple_offset_empty.patch b/queue-6.13/revert-libfs-add-simple_offset_empty.patch
new file mode 100644 (file)
index 0000000..5ceef55
--- /dev/null
@@ -0,0 +1,99 @@
+From d7bde4f27ceef3dc6d72010a20d4da23db835a32 Mon Sep 17 00:00:00 2001
+From: Chuck Lever <chuck.lever@oracle.com>
+Date: Sat, 28 Dec 2024 12:55:18 -0500
+Subject: Revert "libfs: Add simple_offset_empty()"
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+commit d7bde4f27ceef3dc6d72010a20d4da23db835a32 upstream.
+
+simple_empty() and simple_offset_empty() perform the same task.
+The latter's use as a canary to find bugs has not found any new
+issues. A subsequent patch will remove the use of the mtree for
+iterating directory contents, so revert back to using a similar
+mechanism for determining whether a directory is indeed empty.
+
+Only one such mechanism is ever needed.
+
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Link: https://lore.kernel.org/r/20241228175522.1854234-3-cel@kernel.org
+Reviewed-by: Yang Erkun <yangerkun@huawei.com>
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/libfs.c         |   32 --------------------------------
+ include/linux/fs.h |    1 -
+ mm/shmem.c         |    4 ++--
+ 3 files changed, 2 insertions(+), 35 deletions(-)
+
+--- a/fs/libfs.c
++++ b/fs/libfs.c
+@@ -330,38 +330,6 @@ void simple_offset_remove(struct offset_
+ }
+ /**
+- * simple_offset_empty - Check if a dentry can be unlinked
+- * @dentry: dentry to be tested
+- *
+- * Returns 0 if @dentry is a non-empty directory; otherwise returns 1.
+- */
+-int simple_offset_empty(struct dentry *dentry)
+-{
+-      struct inode *inode = d_inode(dentry);
+-      struct offset_ctx *octx;
+-      struct dentry *child;
+-      unsigned long index;
+-      int ret = 1;
+-
+-      if (!inode || !S_ISDIR(inode->i_mode))
+-              return ret;
+-
+-      index = DIR_OFFSET_MIN;
+-      octx = inode->i_op->get_offset_ctx(inode);
+-      mt_for_each(&octx->mt, child, index, LONG_MAX) {
+-              spin_lock(&child->d_lock);
+-              if (simple_positive(child)) {
+-                      spin_unlock(&child->d_lock);
+-                      ret = 0;
+-                      break;
+-              }
+-              spin_unlock(&child->d_lock);
+-      }
+-
+-      return ret;
+-}
+-
+-/**
+  * simple_offset_rename - handle directory offsets for rename
+  * @old_dir: parent directory of source entry
+  * @old_dentry: dentry of source entry
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -3468,7 +3468,6 @@ struct offset_ctx {
+ void simple_offset_init(struct offset_ctx *octx);
+ int simple_offset_add(struct offset_ctx *octx, struct dentry *dentry);
+ void simple_offset_remove(struct offset_ctx *octx, struct dentry *dentry);
+-int simple_offset_empty(struct dentry *dentry);
+ int simple_offset_rename(struct inode *old_dir, struct dentry *old_dentry,
+                        struct inode *new_dir, struct dentry *new_dentry);
+ int simple_offset_rename_exchange(struct inode *old_dir,
+--- a/mm/shmem.c
++++ b/mm/shmem.c
+@@ -3821,7 +3821,7 @@ static int shmem_unlink(struct inode *di
+ static int shmem_rmdir(struct inode *dir, struct dentry *dentry)
+ {
+-      if (!simple_offset_empty(dentry))
++      if (!simple_empty(dentry))
+               return -ENOTEMPTY;
+       drop_nlink(d_inode(dentry));
+@@ -3878,7 +3878,7 @@ static int shmem_rename2(struct mnt_idma
+               return simple_offset_rename_exchange(old_dir, old_dentry,
+                                                    new_dir, new_dentry);
+-      if (!simple_offset_empty(new_dentry))
++      if (!simple_empty(new_dentry))
+               return -ENOTEMPTY;
+       if (flags & RENAME_WHITEOUT) {
diff --git a/queue-6.13/revert-libfs-fix-infinite-directory-reads-for-offset-dir.patch b/queue-6.13/revert-libfs-fix-infinite-directory-reads-for-offset-dir.patch
new file mode 100644 (file)
index 0000000..41a7674
--- /dev/null
@@ -0,0 +1,149 @@
+From b662d858131da9a8a14e68661656989b14dbf113 Mon Sep 17 00:00:00 2001
+From: Chuck Lever <chuck.lever@oracle.com>
+Date: Sat, 28 Dec 2024 12:55:19 -0500
+Subject: Revert "libfs: fix infinite directory reads for offset dir"
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+commit b662d858131da9a8a14e68661656989b14dbf113 upstream.
+
+The current directory offset allocator (based on mtree_alloc_cyclic)
+stores the next offset value to return in octx->next_offset. This
+mechanism typically returns values that increase monotonically over
+time. Eventually, though, the newly allocated offset value wraps
+back to a low number (say, 2) which is smaller than other already-
+allocated offset values.
+
+Yu Kuai <yukuai3@huawei.com> reports that, after commit 64a7ce76fb90
+("libfs: fix infinite directory reads for offset dir"), if a
+directory's offset allocator wraps, existing entries are no longer
+visible via readdir/getdents because offset_readdir() stops listing
+entries once an entry's offset is larger than octx->next_offset.
+These entries vanish persistently -- they can be looked up, but will
+never again appear in readdir(3) output.
+
+The reason for this is that the commit treats directory offsets as
+monotonically increasing integer values rather than opaque cookies,
+and introduces this comparison:
+
+       if (dentry2offset(dentry) >= last_index) {
+
+On 64-bit platforms, the directory offset value upper bound is
+2^63 - 1. Directory offsets will monotonically increase for millions
+of years without wrapping.
+
+On 32-bit platforms, however, LONG_MAX is 2^31 - 1. The allocator
+can wrap after only a few weeks (at worst).
+
+Revert commit 64a7ce76fb90 ("libfs: fix infinite directory reads for
+offset dir") to prepare for a fix that can work properly on 32-bit
+systems and might apply to recent LTS kernels where shmem employs
+the simple_offset mechanism.
+
+Reported-by: Yu Kuai <yukuai3@huawei.com>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Link: https://lore.kernel.org/r/20241228175522.1854234-4-cel@kernel.org
+Reviewed-by: Yang Erkun <yangerkun@huawei.com>
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/libfs.c |   35 +++++++++++------------------------
+ 1 file changed, 11 insertions(+), 24 deletions(-)
+
+--- a/fs/libfs.c
++++ b/fs/libfs.c
+@@ -422,14 +422,6 @@ void simple_offset_destroy(struct offset
+       mtree_destroy(&octx->mt);
+ }
+-static int offset_dir_open(struct inode *inode, struct file *file)
+-{
+-      struct offset_ctx *ctx = inode->i_op->get_offset_ctx(inode);
+-
+-      file->private_data = (void *)ctx->next_offset;
+-      return 0;
+-}
+-
+ /**
+  * offset_dir_llseek - Advance the read position of a directory descriptor
+  * @file: an open directory whose position is to be updated
+@@ -443,9 +435,6 @@ static int offset_dir_open(struct inode
+  */
+ static loff_t offset_dir_llseek(struct file *file, loff_t offset, int whence)
+ {
+-      struct inode *inode = file->f_inode;
+-      struct offset_ctx *ctx = inode->i_op->get_offset_ctx(inode);
+-
+       switch (whence) {
+       case SEEK_CUR:
+               offset += file->f_pos;
+@@ -459,8 +448,7 @@ static loff_t offset_dir_llseek(struct f
+       }
+       /* In this case, ->private_data is protected by f_pos_lock */
+-      if (!offset)
+-              file->private_data = (void *)ctx->next_offset;
++      file->private_data = NULL;
+       return vfs_setpos(file, offset, LONG_MAX);
+ }
+@@ -491,7 +479,7 @@ static bool offset_dir_emit(struct dir_c
+                         inode->i_ino, fs_umode_to_dtype(inode->i_mode));
+ }
+-static void offset_iterate_dir(struct inode *inode, struct dir_context *ctx, long last_index)
++static void *offset_iterate_dir(struct inode *inode, struct dir_context *ctx)
+ {
+       struct offset_ctx *octx = inode->i_op->get_offset_ctx(inode);
+       struct dentry *dentry;
+@@ -499,21 +487,17 @@ static void offset_iterate_dir(struct in
+       while (true) {
+               dentry = offset_find_next(octx, ctx->pos);
+               if (!dentry)
+-                      return;
+-
+-              if (dentry2offset(dentry) >= last_index) {
+-                      dput(dentry);
+-                      return;
+-              }
++                      return ERR_PTR(-ENOENT);
+               if (!offset_dir_emit(ctx, dentry)) {
+                       dput(dentry);
+-                      return;
++                      break;
+               }
+               ctx->pos = dentry2offset(dentry) + 1;
+               dput(dentry);
+       }
++      return NULL;
+ }
+ /**
+@@ -540,19 +524,22 @@ static void offset_iterate_dir(struct in
+ static int offset_readdir(struct file *file, struct dir_context *ctx)
+ {
+       struct dentry *dir = file->f_path.dentry;
+-      long last_index = (long)file->private_data;
+       lockdep_assert_held(&d_inode(dir)->i_rwsem);
+       if (!dir_emit_dots(file, ctx))
+               return 0;
+-      offset_iterate_dir(d_inode(dir), ctx, last_index);
++      /* In this case, ->private_data is protected by f_pos_lock */
++      if (ctx->pos == DIR_OFFSET_MIN)
++              file->private_data = NULL;
++      else if (file->private_data == ERR_PTR(-ENOENT))
++              return 0;
++      file->private_data = offset_iterate_dir(d_inode(dir), ctx);
+       return 0;
+ }
+ const struct file_operations simple_offset_dir_operations = {
+-      .open           = offset_dir_open,
+       .llseek         = offset_dir_llseek,
+       .iterate_shared = offset_readdir,
+       .read           = generic_read_dir,
diff --git a/queue-6.13/scsi-storvsc-ratelimit-warning-logs-to-prevent-vm-denial-of-service.patch b/queue-6.13/scsi-storvsc-ratelimit-warning-logs-to-prevent-vm-denial-of-service.patch
new file mode 100644 (file)
index 0000000..1aef74b
--- /dev/null
@@ -0,0 +1,48 @@
+From d2138eab8cde61e0e6f62d0713e45202e8457d6d Mon Sep 17 00:00:00 2001
+From: Easwar Hariharan <eahariha@linux.microsoft.com>
+Date: Tue, 7 Jan 2025 17:28:40 +0000
+Subject: scsi: storvsc: Ratelimit warning logs to prevent VM denial of service
+
+From: Easwar Hariharan <eahariha@linux.microsoft.com>
+
+commit d2138eab8cde61e0e6f62d0713e45202e8457d6d upstream.
+
+If there's a persistent error in the hypervisor, the SCSI warning for
+failed I/O can flood the kernel log and max out CPU utilization,
+preventing troubleshooting from the VM side. Ratelimit the warning so
+it doesn't DoS the VM.
+
+Closes: https://github.com/microsoft/WSL/issues/9173
+Signed-off-by: Easwar Hariharan <eahariha@linux.microsoft.com>
+Link: https://lore.kernel.org/r/20250107-eahariha-ratelimit-storvsc-v1-1-7fc193d1f2b0@linux.microsoft.com
+Reviewed-by: Michael Kelley <mhklinux@outlook.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/scsi/storvsc_drv.c |    8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+--- a/drivers/scsi/storvsc_drv.c
++++ b/drivers/scsi/storvsc_drv.c
+@@ -171,6 +171,12 @@ do {                                                              \
+               dev_warn(&(dev)->device, fmt, ##__VA_ARGS__);   \
+ } while (0)
++#define storvsc_log_ratelimited(dev, level, fmt, ...)                         \
++do {                                                                          \
++      if (do_logging(level))                                                  \
++              dev_warn_ratelimited(&(dev)->device, fmt, ##__VA_ARGS__);       \
++} while (0)
++
+ struct vmscsi_request {
+       u16 length;
+       u8 srb_status;
+@@ -1177,7 +1183,7 @@ static void storvsc_on_io_completion(str
+               int loglevel = (stor_pkt->vm_srb.cdb[0] == TEST_UNIT_READY) ?
+                       STORVSC_LOGGING_WARN : STORVSC_LOGGING_ERROR;
+-              storvsc_log(device, loglevel,
++              storvsc_log_ratelimited(device, loglevel,
+                       "tag#%d cmd 0x%x status: scsi 0x%x srb 0x%x hv 0x%x\n",
+                       scsi_cmd_to_rq(request->cmd)->tag,
+                       stor_pkt->vm_srb.cdb[0],
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..a3a5682f719cc5852bc7970d6cc0f669c97024a4 100644 (file)
@@ -0,0 +1,12 @@
+gfs2-truncate-address-space-when-flipping-gfs2_dif_jdata-flag.patch
+libfs-return-enospc-when-the-directory-offset-range-is-exhausted.patch
+revert-libfs-add-simple_offset_empty.patch
+revert-libfs-fix-infinite-directory-reads-for-offset-dir.patch
+libfs-replace-simple_offset-end-of-directory-detection.patch
+libfs-use-d_children-list-to-iterate-simple_offset-directories.patch
+smb-client-handle-lack-of-ea-support-in-smb2_query_path_info.patch
+net-sched-fix-ets-qdisc-oob-indexing.patch
+revert-hid-multitouch-add-support-for-lenovo-y9000p-touchpad.patch
+cachestat-fix-page-cache-statistics-permission-checking.patch
+vfio-platform-check-the-bounds-of-read-write-syscalls.patch
+scsi-storvsc-ratelimit-warning-logs-to-prevent-vm-denial-of-service.patch
diff --git a/queue-6.13/smb-client-handle-lack-of-ea-support-in-smb2_query_path_info.patch b/queue-6.13/smb-client-handle-lack-of-ea-support-in-smb2_query_path_info.patch
new file mode 100644 (file)
index 0000000..d48e75f
--- /dev/null
@@ -0,0 +1,198 @@
+From 3681c74d342db75b0d641ba60de27bf73e16e66b Mon Sep 17 00:00:00 2001
+From: Paulo Alcantara <pc@manguebit.com>
+Date: Tue, 21 Jan 2025 15:25:36 -0300
+Subject: smb: client: handle lack of EA support in smb2_query_path_info()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Paulo Alcantara <pc@manguebit.com>
+
+commit 3681c74d342db75b0d641ba60de27bf73e16e66b upstream.
+
+If the server doesn't support both EAs and reparse point in a file,
+the SMB2_QUERY_INFO request will fail with either
+STATUS_NO_EAS_ON_FILE or STATUS_EAS_NOT_SUPPORT in the compound chain,
+so ignore it as long as reparse point isn't
+IO_REPARSE_TAG_LX_(CHR|BLK), which would require the EAs to know about
+major/minor numbers.
+
+Reported-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Paulo Alcantara (Red Hat) <pc@manguebit.com>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/smb/client/smb2inode.c |   92 ++++++++++++++++++++++++++++++++++------------
+ 1 file changed, 69 insertions(+), 23 deletions(-)
+
+--- a/fs/smb/client/smb2inode.c
++++ b/fs/smb/client/smb2inode.c
+@@ -176,27 +176,27 @@ static int smb2_compound_op(const unsign
+                           struct kvec *out_iov, int *out_buftype, struct dentry *dentry)
+ {
+-      struct reparse_data_buffer *rbuf;
++      struct smb2_query_info_rsp *qi_rsp = NULL;
+       struct smb2_compound_vars *vars = NULL;
+-      struct kvec *rsp_iov, *iov;
+-      struct smb_rqst *rqst;
+-      int rc;
+-      __le16 *utf16_path = NULL;
+       __u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
+-      struct cifs_fid fid;
++      struct cifs_open_info_data *idata;
+       struct cifs_ses *ses = tcon->ses;
++      struct reparse_data_buffer *rbuf;
+       struct TCP_Server_Info *server;
+-      int num_rqst = 0, i;
+       int resp_buftype[MAX_COMPOUND];
+-      struct smb2_query_info_rsp *qi_rsp = NULL;
+-      struct cifs_open_info_data *idata;
++      int retries = 0, cur_sleep = 1;
++      __u8 delete_pending[8] = {1,};
++      struct kvec *rsp_iov, *iov;
+       struct inode *inode = NULL;
+-      int flags = 0;
+-      __u8 delete_pending[8] = {1, 0, 0, 0, 0, 0, 0, 0};
++      __le16 *utf16_path = NULL;
++      struct smb_rqst *rqst;
+       unsigned int size[2];
+-      void *data[2];
++      struct cifs_fid fid;
++      int num_rqst = 0, i;
+       unsigned int len;
+-      int retries = 0, cur_sleep = 1;
++      int tmp_rc, rc;
++      int flags = 0;
++      void *data[2];
+ replay_again:
+       /* reinitialize for possible replay */
+@@ -637,7 +637,14 @@ finished:
+               tcon->need_reconnect = true;
+       }
++      tmp_rc = rc;
+       for (i = 0; i < num_cmds; i++) {
++              char *buf = rsp_iov[i + i].iov_base;
++
++              if (buf && resp_buftype[i + 1] != CIFS_NO_BUFFER)
++                      rc = server->ops->map_error(buf, false);
++              else
++                      rc = tmp_rc;
+               switch (cmds[i]) {
+               case SMB2_OP_QUERY_INFO:
+                       idata = in_iov[i].iov_base;
+@@ -803,6 +810,7 @@ finished:
+               }
+       }
+       SMB2_close_free(&rqst[num_rqst]);
++      rc = tmp_rc;
+       num_cmds += 2;
+       if (out_iov && out_buftype) {
+@@ -858,22 +866,52 @@ static int parse_create_response(struct
+       return rc;
+ }
++/* Check only if SMB2_OP_QUERY_WSL_EA command failed in the compound chain */
++static bool ea_unsupported(int *cmds, int num_cmds,
++                         struct kvec *out_iov, int *out_buftype)
++{
++      int i;
++
++      if (cmds[num_cmds - 1] != SMB2_OP_QUERY_WSL_EA)
++              return false;
++
++      for (i = 1; i < num_cmds - 1; i++) {
++              struct smb2_hdr *hdr = out_iov[i].iov_base;
++
++              if (out_buftype[i] == CIFS_NO_BUFFER || !hdr ||
++                  hdr->Status != STATUS_SUCCESS)
++                      return false;
++      }
++      return true;
++}
++
++static inline void free_rsp_iov(struct kvec *iovs, int *buftype, int count)
++{
++      int i;
++
++      for (i = 0; i < count; i++) {
++              free_rsp_buf(buftype[i], iovs[i].iov_base);
++              memset(&iovs[i], 0, sizeof(*iovs));
++              buftype[i] = CIFS_NO_BUFFER;
++      }
++}
++
+ int smb2_query_path_info(const unsigned int xid,
+                        struct cifs_tcon *tcon,
+                        struct cifs_sb_info *cifs_sb,
+                        const char *full_path,
+                        struct cifs_open_info_data *data)
+ {
++      struct kvec in_iov[3], out_iov[5] = {};
++      struct cached_fid *cfid = NULL;
+       struct cifs_open_parms oparms;
+-      __u32 create_options = 0;
+       struct cifsFileInfo *cfile;
+-      struct cached_fid *cfid = NULL;
++      __u32 create_options = 0;
++      int out_buftype[5] = {};
+       struct smb2_hdr *hdr;
+-      struct kvec in_iov[3], out_iov[3] = {};
+-      int out_buftype[3] = {};
++      int num_cmds = 0;
+       int cmds[3];
+       bool islink;
+-      int i, num_cmds = 0;
+       int rc, rc2;
+       data->adjust_tz = false;
+@@ -943,14 +981,14 @@ int smb2_query_path_info(const unsigned
+               if (rc || !data->reparse_point)
+                       goto out;
+-              if (!tcon->posix_extensions)
+-                      cmds[num_cmds++] = SMB2_OP_QUERY_WSL_EA;
+               /*
+                * Skip SMB2_OP_GET_REPARSE if symlink already parsed in create
+                * response.
+                */
+               if (data->reparse.tag != IO_REPARSE_TAG_SYMLINK)
+                       cmds[num_cmds++] = SMB2_OP_GET_REPARSE;
++              if (!tcon->posix_extensions)
++                      cmds[num_cmds++] = SMB2_OP_QUERY_WSL_EA;
+               oparms = CIFS_OPARMS(cifs_sb, tcon, full_path,
+                                    FILE_READ_ATTRIBUTES |
+@@ -958,9 +996,18 @@ int smb2_query_path_info(const unsigned
+                                    FILE_OPEN, create_options |
+                                    OPEN_REPARSE_POINT, ACL_NO_MODE);
+               cifs_get_readable_path(tcon, full_path, &cfile);
++              free_rsp_iov(out_iov, out_buftype, ARRAY_SIZE(out_iov));
+               rc = smb2_compound_op(xid, tcon, cifs_sb, full_path,
+                                     &oparms, in_iov, cmds, num_cmds,
+-                                    cfile, NULL, NULL, NULL);
++                                    cfile, out_iov, out_buftype, NULL);
++              if (rc && ea_unsupported(cmds, num_cmds,
++                                       out_iov, out_buftype)) {
++                      if (data->reparse.tag != IO_REPARSE_TAG_LX_BLK &&
++                          data->reparse.tag != IO_REPARSE_TAG_LX_CHR)
++                              rc = 0;
++                      else
++                              rc = -EOPNOTSUPP;
++              }
+               break;
+       case -EREMOTE:
+               break;
+@@ -978,8 +1025,7 @@ int smb2_query_path_info(const unsigned
+       }
+ out:
+-      for (i = 0; i < ARRAY_SIZE(out_buftype); i++)
+-              free_rsp_buf(out_buftype[i], out_iov[i].iov_base);
++      free_rsp_iov(out_iov, out_buftype, ARRAY_SIZE(out_iov));
+       return rc;
+ }
diff --git a/queue-6.13/vfio-platform-check-the-bounds-of-read-write-syscalls.patch b/queue-6.13/vfio-platform-check-the-bounds-of-read-write-syscalls.patch
new file mode 100644 (file)
index 0000000..58f98fe
--- /dev/null
@@ -0,0 +1,54 @@
+From ce9ff21ea89d191e477a02ad7eabf4f996b80a69 Mon Sep 17 00:00:00 2001
+From: Alex Williamson <alex.williamson@redhat.com>
+Date: Wed, 22 Jan 2025 10:38:30 -0700
+Subject: vfio/platform: check the bounds of read/write syscalls
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Alex Williamson <alex.williamson@redhat.com>
+
+commit ce9ff21ea89d191e477a02ad7eabf4f996b80a69 upstream.
+
+count and offset are passed from user space and not checked, only
+offset is capped to 40 bits, which can be used to read/write out of
+bounds of the device.
+
+Fixes: 6e3f26456009 (“vfio/platform: read and write support for the device fd”)
+Cc: stable@vger.kernel.org
+Reported-by: Mostafa Saleh <smostafa@google.com>
+Reviewed-by: Eric Auger <eric.auger@redhat.com>
+Reviewed-by: Mostafa Saleh <smostafa@google.com>
+Tested-by: Mostafa Saleh <smostafa@google.com>
+Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/vfio/platform/vfio_platform_common.c |   10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+--- a/drivers/vfio/platform/vfio_platform_common.c
++++ b/drivers/vfio/platform/vfio_platform_common.c
+@@ -388,6 +388,11 @@ static ssize_t vfio_platform_read_mmio(s
+ {
+       unsigned int done = 0;
++      if (off >= reg->size)
++              return -EINVAL;
++
++      count = min_t(size_t, count, reg->size - off);
++
+       if (!reg->ioaddr) {
+               reg->ioaddr =
+                       ioremap(reg->addr, reg->size);
+@@ -467,6 +472,11 @@ static ssize_t vfio_platform_write_mmio(
+ {
+       unsigned int done = 0;
++      if (off >= reg->size)
++              return -EINVAL;
++
++      count = min_t(size_t, count, reg->size - off);
++
+       if (!reg->ioaddr) {
+               reg->ioaddr =
+                       ioremap(reg->addr, reg->size);