]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for all trees
authorSasha Levin <sashal@kernel.org>
Wed, 27 Aug 2025 03:27:56 +0000 (23:27 -0400)
committerSasha Levin <sashal@kernel.org>
Wed, 27 Aug 2025 03:27:56 +0000 (23:27 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-5.10/alloc_fdtable-change-calling-conventions.patch [new file with mode: 0644]
queue-5.10/series
queue-5.15/alloc_fdtable-change-calling-conventions.patch [new file with mode: 0644]
queue-5.15/series
queue-5.4/alloc_fdtable-change-calling-conventions.patch [new file with mode: 0644]
queue-5.4/series
queue-6.1/alloc_fdtable-change-calling-conventions.patch [new file with mode: 0644]
queue-6.1/series
queue-6.6/alloc_fdtable-change-calling-conventions.patch [new file with mode: 0644]
queue-6.6/series

diff --git a/queue-5.10/alloc_fdtable-change-calling-conventions.patch b/queue-5.10/alloc_fdtable-change-calling-conventions.patch
new file mode 100644 (file)
index 0000000..134355b
--- /dev/null
@@ -0,0 +1,164 @@
+From b452d7883a5e165999fc57720a32cef809a134d4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 Aug 2025 17:27:47 -0400
+Subject: alloc_fdtable(): change calling conventions.
+
+From: Al Viro <viro@zeniv.linux.org.uk>
+
+[ Upstream commit 1d3b4bec3ce55e0c46cdce7d0402dbd6b4af3a3d ]
+
+First of all, tell it how many slots do we want, not which slot
+is wanted.  It makes one caller (dup_fd()) more straightforward
+and doesn't harm another (expand_fdtable()).
+
+Furthermore, make it return ERR_PTR() on failure rather than
+returning NULL.  Simplifies the callers.
+
+Simplify the size calculation, while we are at it - note that we
+always have slots_wanted greater than BITS_PER_LONG.  What the
+rules boil down to is
+       * use the smallest power of two large enough to give us
+that many slots
+       * on 32bit skip 64 and 128 - the minimal capacity we want
+there is 256 slots (i.e. 1Kb fd array).
+       * on 64bit don't skip anything, the minimal capacity is
+128 - and we'll never be asked for 64 or less.  128 slots means
+1Kb fd array, again.
+       * on 128bit, if that ever happens, don't skip anything -
+we'll never be asked for 128 or less, so the fd array allocation
+will be at least 2Kb.
+
+Reviewed-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/file.c | 68 +++++++++++++++++++++++--------------------------------
+ 1 file changed, 28 insertions(+), 40 deletions(-)
+
+diff --git a/fs/file.c b/fs/file.c
+index c44c70af33ad..c8fff3d79336 100644
+--- a/fs/file.c
++++ b/fs/file.c
+@@ -90,18 +90,11 @@ static void copy_fdtable(struct fdtable *nfdt, struct fdtable *ofdt)
+  * 'unsigned long' in some places, but simply because that is how the Linux
+  * kernel bitmaps are defined to work: they are not "bits in an array of bytes",
+  * they are very much "bits in an array of unsigned long".
+- *
+- * The ALIGN(nr, BITS_PER_LONG) here is for clarity: since we just multiplied
+- * by that "1024/sizeof(ptr)" before, we already know there are sufficient
+- * clear low bits. Clang seems to realize that, gcc ends up being confused.
+- *
+- * On a 128-bit machine, the ALIGN() would actually matter. In the meantime,
+- * let's consider it documentation (and maybe a test-case for gcc to improve
+- * its code generation ;)
+  */
+-static struct fdtable * alloc_fdtable(unsigned int nr)
++static struct fdtable *alloc_fdtable(unsigned int slots_wanted)
+ {
+       struct fdtable *fdt;
++      unsigned int nr;
+       void *data;
+       /*
+@@ -109,22 +102,32 @@ static struct fdtable * alloc_fdtable(unsigned int nr)
+        * Allocation steps are keyed to the size of the fdarray, since it
+        * grows far faster than any of the other dynamic data. We try to fit
+        * the fdarray into comfortable page-tuned chunks: starting at 1024B
+-       * and growing in powers of two from there on.
++       * and growing in powers of two from there on.  Since we called only
++       * with slots_wanted > BITS_PER_LONG (embedded instance in files->fdtab
++       * already gives BITS_PER_LONG slots), the above boils down to
++       * 1.  use the smallest power of two large enough to give us that many
++       * slots.
++       * 2.  on 32bit skip 64 and 128 - the minimal capacity we want there is
++       * 256 slots (i.e. 1Kb fd array).
++       * 3.  on 64bit don't skip anything, 1Kb fd array means 128 slots there
++       * and we are never going to be asked for 64 or less.
+        */
+-      nr /= (1024 / sizeof(struct file *));
+-      nr = roundup_pow_of_two(nr + 1);
+-      nr *= (1024 / sizeof(struct file *));
+-      nr = ALIGN(nr, BITS_PER_LONG);
++      if (IS_ENABLED(CONFIG_32BIT) && slots_wanted < 256)
++              nr = 256;
++      else
++              nr = roundup_pow_of_two(slots_wanted);
+       /*
+        * Note that this can drive nr *below* what we had passed if sysctl_nr_open
+-       * had been set lower between the check in expand_files() and here.  Deal
+-       * with that in caller, it's cheaper that way.
++       * had been set lower between the check in expand_files() and here.
+        *
+        * We make sure that nr remains a multiple of BITS_PER_LONG - otherwise
+        * bitmaps handling below becomes unpleasant, to put it mildly...
+        */
+-      if (unlikely(nr > sysctl_nr_open))
+-              nr = ((sysctl_nr_open - 1) | (BITS_PER_LONG - 1)) + 1;
++      if (unlikely(nr > sysctl_nr_open)) {
++              nr = round_down(sysctl_nr_open, BITS_PER_LONG);
++              if (nr < slots_wanted)
++                      return ERR_PTR(-EMFILE);
++      }
+       /*
+        * Check if the allocation size would exceed INT_MAX. kvmalloc_array()
+@@ -168,7 +171,7 @@ static struct fdtable * alloc_fdtable(unsigned int nr)
+ out_fdt:
+       kfree(fdt);
+ out:
+-      return NULL;
++      return ERR_PTR(-ENOMEM);
+ }
+ /*
+@@ -185,7 +188,7 @@ static int expand_fdtable(struct files_struct *files, unsigned int nr)
+       struct fdtable *new_fdt, *cur_fdt;
+       spin_unlock(&files->file_lock);
+-      new_fdt = alloc_fdtable(nr);
++      new_fdt = alloc_fdtable(nr + 1);
+       /* make sure all fd_install() have seen resize_in_progress
+        * or have finished their rcu_read_lock_sched() section.
+@@ -194,16 +197,8 @@ static int expand_fdtable(struct files_struct *files, unsigned int nr)
+               synchronize_rcu();
+       spin_lock(&files->file_lock);
+-      if (!new_fdt)
+-              return -ENOMEM;
+-      /*
+-       * extremely unlikely race - sysctl_nr_open decreased between the check in
+-       * caller and alloc_fdtable().  Cheaper to catch it here...
+-       */
+-      if (unlikely(new_fdt->max_fds <= nr)) {
+-              __free_fdtable(new_fdt);
+-              return -EMFILE;
+-      }
++      if (IS_ERR(new_fdt))
++              return PTR_ERR(new_fdt);
+       cur_fdt = files_fdtable(files);
+       BUG_ON(nr < cur_fdt->max_fds);
+       copy_fdtable(new_fdt, cur_fdt);
+@@ -363,16 +358,9 @@ struct files_struct *dup_fd(struct files_struct *oldf, unsigned int max_fds, int
+               if (new_fdt != &newf->fdtab)
+                       __free_fdtable(new_fdt);
+-              new_fdt = alloc_fdtable(open_files - 1);
+-              if (!new_fdt) {
+-                      *errorp = -ENOMEM;
+-                      goto out_release;
+-              }
+-
+-              /* beyond sysctl_nr_open; nothing to do */
+-              if (unlikely(new_fdt->max_fds < open_files)) {
+-                      __free_fdtable(new_fdt);
+-                      *errorp = -EMFILE;
++              new_fdt = alloc_fdtable(open_files);
++              if (IS_ERR(new_fdt)) {
++                      *errorp = PTR_ERR(new_fdt);
+                       goto out_release;
+               }
+-- 
+2.50.1
+
index 8dbcdf5c1ceca6c6d23b50dccf15a544400805fe..07ce3a2f577a8c075de28d17dca002819d53cb14 100644 (file)
@@ -521,3 +521,4 @@ s390-hypfs-enable-limited-access-during-lockdown.patch
 netfilter-nft_reject-unify-reject-init-and-dump-into.patch
 netfilter-nft_reject_inet-allow-to-use-reject-from-i.patch
 netfilter-nf_reject-don-t-leak-dst-refcount-for-loop.patch
+alloc_fdtable-change-calling-conventions.patch
diff --git a/queue-5.15/alloc_fdtable-change-calling-conventions.patch b/queue-5.15/alloc_fdtable-change-calling-conventions.patch
new file mode 100644 (file)
index 0000000..a215f41
--- /dev/null
@@ -0,0 +1,185 @@
+From c5114b0875a73ef7ada0de96e4bc19d94ead727a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 6 Aug 2024 22:14:07 -0400
+Subject: alloc_fdtable(): change calling conventions.
+
+From: Al Viro <viro@zeniv.linux.org.uk>
+
+[ Upstream commit 1d3b4bec3ce55e0c46cdce7d0402dbd6b4af3a3d ]
+
+First of all, tell it how many slots do we want, not which slot
+is wanted.  It makes one caller (dup_fd()) more straightforward
+and doesn't harm another (expand_fdtable()).
+
+Furthermore, make it return ERR_PTR() on failure rather than
+returning NULL.  Simplifies the callers.
+
+Simplify the size calculation, while we are at it - note that we
+always have slots_wanted greater than BITS_PER_LONG.  What the
+rules boil down to is
+       * use the smallest power of two large enough to give us
+that many slots
+       * on 32bit skip 64 and 128 - the minimal capacity we want
+there is 256 slots (i.e. 1Kb fd array).
+       * on 64bit don't skip anything, the minimal capacity is
+128 - and we'll never be asked for 64 or less.  128 slots means
+1Kb fd array, again.
+       * on 128bit, if that ever happens, don't skip anything -
+we'll never be asked for 128 or less, so the fd array allocation
+will be at least 2Kb.
+
+Reviewed-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/file.c | 75 +++++++++++++++++++++----------------------------------
+ 1 file changed, 29 insertions(+), 46 deletions(-)
+
+diff --git a/fs/file.c b/fs/file.c
+index 30c040248a1b..8f013aaf351f 100644
+--- a/fs/file.c
++++ b/fs/file.c
+@@ -90,18 +90,11 @@ static void copy_fdtable(struct fdtable *nfdt, struct fdtable *ofdt)
+  * 'unsigned long' in some places, but simply because that is how the Linux
+  * kernel bitmaps are defined to work: they are not "bits in an array of bytes",
+  * they are very much "bits in an array of unsigned long".
+- *
+- * The ALIGN(nr, BITS_PER_LONG) here is for clarity: since we just multiplied
+- * by that "1024/sizeof(ptr)" before, we already know there are sufficient
+- * clear low bits. Clang seems to realize that, gcc ends up being confused.
+- *
+- * On a 128-bit machine, the ALIGN() would actually matter. In the meantime,
+- * let's consider it documentation (and maybe a test-case for gcc to improve
+- * its code generation ;)
+  */
+-static struct fdtable * alloc_fdtable(unsigned int nr)
++static struct fdtable *alloc_fdtable(unsigned int slots_wanted)
+ {
+       struct fdtable *fdt;
++      unsigned int nr;
+       void *data;
+       /*
+@@ -109,22 +102,32 @@ static struct fdtable * alloc_fdtable(unsigned int nr)
+        * Allocation steps are keyed to the size of the fdarray, since it
+        * grows far faster than any of the other dynamic data. We try to fit
+        * the fdarray into comfortable page-tuned chunks: starting at 1024B
+-       * and growing in powers of two from there on.
++       * and growing in powers of two from there on.  Since we called only
++       * with slots_wanted > BITS_PER_LONG (embedded instance in files->fdtab
++       * already gives BITS_PER_LONG slots), the above boils down to
++       * 1.  use the smallest power of two large enough to give us that many
++       * slots.
++       * 2.  on 32bit skip 64 and 128 - the minimal capacity we want there is
++       * 256 slots (i.e. 1Kb fd array).
++       * 3.  on 64bit don't skip anything, 1Kb fd array means 128 slots there
++       * and we are never going to be asked for 64 or less.
+        */
+-      nr /= (1024 / sizeof(struct file *));
+-      nr = roundup_pow_of_two(nr + 1);
+-      nr *= (1024 / sizeof(struct file *));
+-      nr = ALIGN(nr, BITS_PER_LONG);
++      if (IS_ENABLED(CONFIG_32BIT) && slots_wanted < 256)
++              nr = 256;
++      else
++              nr = roundup_pow_of_two(slots_wanted);
+       /*
+        * Note that this can drive nr *below* what we had passed if sysctl_nr_open
+-       * had been set lower between the check in expand_files() and here.  Deal
+-       * with that in caller, it's cheaper that way.
++       * had been set lower between the check in expand_files() and here.
+        *
+        * We make sure that nr remains a multiple of BITS_PER_LONG - otherwise
+        * bitmaps handling below becomes unpleasant, to put it mildly...
+        */
+-      if (unlikely(nr > sysctl_nr_open))
+-              nr = ((sysctl_nr_open - 1) | (BITS_PER_LONG - 1)) + 1;
++      if (unlikely(nr > sysctl_nr_open)) {
++              nr = round_down(sysctl_nr_open, BITS_PER_LONG);
++              if (nr < slots_wanted)
++                      return ERR_PTR(-EMFILE);
++      }
+       /*
+        * Check if the allocation size would exceed INT_MAX. kvmalloc_array()
+@@ -168,7 +171,7 @@ static struct fdtable * alloc_fdtable(unsigned int nr)
+ out_fdt:
+       kfree(fdt);
+ out:
+-      return NULL;
++      return ERR_PTR(-ENOMEM);
+ }
+ /*
+@@ -185,7 +188,7 @@ static int expand_fdtable(struct files_struct *files, unsigned int nr)
+       struct fdtable *new_fdt, *cur_fdt;
+       spin_unlock(&files->file_lock);
+-      new_fdt = alloc_fdtable(nr);
++      new_fdt = alloc_fdtable(nr + 1);
+       /* make sure all fd_install() have seen resize_in_progress
+        * or have finished their rcu_read_lock_sched() section.
+@@ -194,16 +197,8 @@ static int expand_fdtable(struct files_struct *files, unsigned int nr)
+               synchronize_rcu();
+       spin_lock(&files->file_lock);
+-      if (!new_fdt)
+-              return -ENOMEM;
+-      /*
+-       * extremely unlikely race - sysctl_nr_open decreased between the check in
+-       * caller and alloc_fdtable().  Cheaper to catch it here...
+-       */
+-      if (unlikely(new_fdt->max_fds <= nr)) {
+-              __free_fdtable(new_fdt);
+-              return -EMFILE;
+-      }
++      if (IS_ERR(new_fdt))
++              return PTR_ERR(new_fdt);
+       cur_fdt = files_fdtable(files);
+       BUG_ON(nr < cur_fdt->max_fds);
+       copy_fdtable(new_fdt, cur_fdt);
+@@ -317,7 +312,6 @@ struct files_struct *dup_fd(struct files_struct *oldf, struct fd_range *punch_ho
+       struct file **old_fds, **new_fds;
+       unsigned int open_files, i;
+       struct fdtable *old_fdt, *new_fdt;
+-      int error;
+       newf = kmem_cache_alloc(files_cachep, GFP_KERNEL);
+       if (!newf)
+@@ -349,17 +343,10 @@ struct files_struct *dup_fd(struct files_struct *oldf, struct fd_range *punch_ho
+               if (new_fdt != &newf->fdtab)
+                       __free_fdtable(new_fdt);
+-              new_fdt = alloc_fdtable(open_files - 1);
+-              if (!new_fdt) {
+-                      error = -ENOMEM;
+-                      goto out_release;
+-              }
+-
+-              /* beyond sysctl_nr_open; nothing to do */
+-              if (unlikely(new_fdt->max_fds < open_files)) {
+-                      __free_fdtable(new_fdt);
+-                      error = -EMFILE;
+-                      goto out_release;
++              new_fdt = alloc_fdtable(open_files);
++              if (IS_ERR(new_fdt)) {
++                      kmem_cache_free(files_cachep, newf);
++                      return ERR_CAST(new_fdt);
+               }
+               /*
+@@ -400,10 +387,6 @@ struct files_struct *dup_fd(struct files_struct *oldf, struct fd_range *punch_ho
+       rcu_assign_pointer(newf->fdt, new_fdt);
+       return newf;
+-
+-out_release:
+-      kmem_cache_free(files_cachep, newf);
+-      return ERR_PTR(error);
+ }
+ static struct fdtable *close_files(struct files_struct * files)
+-- 
+2.50.1
+
index d91d0dad6f6c647bdc6ee4a8d7d8aaad577dbea3..86ee57d5be7e8f23a293cfbb200c5fdb583329f0 100644 (file)
@@ -642,3 +642,4 @@ s390-hypfs-avoid-unnecessary-ioctl-registration-in-d.patch
 s390-hypfs-enable-limited-access-during-lockdown.patch
 netfilter-nf_reject-don-t-leak-dst-refcount-for-loop.patch
 wifi-mac80211-check-basic-rates-validity-in-sta_link_apply_parameters.patch
+alloc_fdtable-change-calling-conventions.patch
diff --git a/queue-5.4/alloc_fdtable-change-calling-conventions.patch b/queue-5.4/alloc_fdtable-change-calling-conventions.patch
new file mode 100644 (file)
index 0000000..d90819c
--- /dev/null
@@ -0,0 +1,161 @@
+From 70d092d36ea4dc7da3427d8d691c10fc3fddc8cb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 Aug 2025 17:27:47 -0400
+Subject: alloc_fdtable(): change calling conventions.
+
+From: Al Viro <viro@zeniv.linux.org.uk>
+
+[ Upstream commit 1d3b4bec3ce55e0c46cdce7d0402dbd6b4af3a3d ]
+
+First of all, tell it how many slots do we want, not which slot
+is wanted.  It makes one caller (dup_fd()) more straightforward
+and doesn't harm another (expand_fdtable()).
+
+Furthermore, make it return ERR_PTR() on failure rather than
+returning NULL.  Simplifies the callers.
+
+Simplify the size calculation, while we are at it - note that we
+always have slots_wanted greater than BITS_PER_LONG.  What the
+rules boil down to is
+       * use the smallest power of two large enough to give us
+that many slots
+       * on 32bit skip 64 and 128 - the minimal capacity we want
+there is 256 slots (i.e. 1Kb fd array).
+       * on 64bit don't skip anything, the minimal capacity is
+128 - and we'll never be asked for 64 or less.  128 slots means
+1Kb fd array, again.
+       * on 128bit, if that ever happens, don't skip anything -
+we'll never be asked for 128 or less, so the fd array allocation
+will be at least 2Kb.
+
+Reviewed-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/file.c | 66 +++++++++++++++++++++++++++++--------------------------
+ 1 file changed, 35 insertions(+), 31 deletions(-)
+
+diff --git a/fs/file.c b/fs/file.c
+index 9574a9116468..95f6af59df80 100644
+--- a/fs/file.c
++++ b/fs/file.c
+@@ -78,9 +78,17 @@ static void copy_fdtable(struct fdtable *nfdt, struct fdtable *ofdt)
+       copy_fd_bitmaps(nfdt, ofdt, fdt_words(ofdt));
+ }
+-static struct fdtable * alloc_fdtable(unsigned int nr)
++/*
++ * Note how the fdtable bitmap allocations very much have to be a multiple of
++ * BITS_PER_LONG. This is not only because we walk those things in chunks of
++ * 'unsigned long' in some places, but simply because that is how the Linux
++ * kernel bitmaps are defined to work: they are not "bits in an array of bytes",
++ * they are very much "bits in an array of unsigned long".
++ */
++static struct fdtable *alloc_fdtable(unsigned int slots_wanted)
+ {
+       struct fdtable *fdt;
++      unsigned int nr;
+       void *data;
+       /*
+@@ -88,21 +96,32 @@ static struct fdtable * alloc_fdtable(unsigned int nr)
+        * Allocation steps are keyed to the size of the fdarray, since it
+        * grows far faster than any of the other dynamic data. We try to fit
+        * the fdarray into comfortable page-tuned chunks: starting at 1024B
+-       * and growing in powers of two from there on.
++       * and growing in powers of two from there on.  Since we called only
++       * with slots_wanted > BITS_PER_LONG (embedded instance in files->fdtab
++       * already gives BITS_PER_LONG slots), the above boils down to
++       * 1.  use the smallest power of two large enough to give us that many
++       * slots.
++       * 2.  on 32bit skip 64 and 128 - the minimal capacity we want there is
++       * 256 slots (i.e. 1Kb fd array).
++       * 3.  on 64bit don't skip anything, 1Kb fd array means 128 slots there
++       * and we are never going to be asked for 64 or less.
+        */
+-      nr /= (1024 / sizeof(struct file *));
+-      nr = roundup_pow_of_two(nr + 1);
+-      nr *= (1024 / sizeof(struct file *));
++      if (IS_ENABLED(CONFIG_32BIT) && slots_wanted < 256)
++              nr = 256;
++      else
++              nr = roundup_pow_of_two(slots_wanted);
+       /*
+        * Note that this can drive nr *below* what we had passed if sysctl_nr_open
+-       * had been set lower between the check in expand_files() and here.  Deal
+-       * with that in caller, it's cheaper that way.
++       * had been set lower between the check in expand_files() and here.
+        *
+        * We make sure that nr remains a multiple of BITS_PER_LONG - otherwise
+        * bitmaps handling below becomes unpleasant, to put it mildly...
+        */
+-      if (unlikely(nr > sysctl_nr_open))
+-              nr = ((sysctl_nr_open - 1) | (BITS_PER_LONG - 1)) + 1;
++      if (unlikely(nr > sysctl_nr_open)) {
++              nr = round_down(sysctl_nr_open, BITS_PER_LONG);
++              if (nr < slots_wanted)
++                      return ERR_PTR(-EMFILE);
++      }
+       /*
+        * Check if the allocation size would exceed INT_MAX. kvmalloc_array()
+@@ -146,7 +165,7 @@ static struct fdtable * alloc_fdtable(unsigned int nr)
+ out_fdt:
+       kfree(fdt);
+ out:
+-      return NULL;
++      return ERR_PTR(-ENOMEM);
+ }
+ /*
+@@ -163,7 +182,7 @@ static int expand_fdtable(struct files_struct *files, unsigned int nr)
+       struct fdtable *new_fdt, *cur_fdt;
+       spin_unlock(&files->file_lock);
+-      new_fdt = alloc_fdtable(nr);
++      new_fdt = alloc_fdtable(nr + 1);
+       /* make sure all __fd_install() have seen resize_in_progress
+        * or have finished their rcu_read_lock_sched() section.
+@@ -172,16 +191,8 @@ static int expand_fdtable(struct files_struct *files, unsigned int nr)
+               synchronize_rcu();
+       spin_lock(&files->file_lock);
+-      if (!new_fdt)
+-              return -ENOMEM;
+-      /*
+-       * extremely unlikely race - sysctl_nr_open decreased between the check in
+-       * caller and alloc_fdtable().  Cheaper to catch it here...
+-       */
+-      if (unlikely(new_fdt->max_fds <= nr)) {
+-              __free_fdtable(new_fdt);
+-              return -EMFILE;
+-      }
++      if (IS_ERR(new_fdt))
++              return PTR_ERR(new_fdt);
+       cur_fdt = files_fdtable(files);
+       BUG_ON(nr < cur_fdt->max_fds);
+       copy_fdtable(new_fdt, cur_fdt);
+@@ -318,16 +329,9 @@ struct files_struct *dup_fd(struct files_struct *oldf, int *errorp)
+               if (new_fdt != &newf->fdtab)
+                       __free_fdtable(new_fdt);
+-              new_fdt = alloc_fdtable(open_files - 1);
+-              if (!new_fdt) {
+-                      *errorp = -ENOMEM;
+-                      goto out_release;
+-              }
+-
+-              /* beyond sysctl_nr_open; nothing to do */
+-              if (unlikely(new_fdt->max_fds < open_files)) {
+-                      __free_fdtable(new_fdt);
+-                      *errorp = -EMFILE;
++              new_fdt = alloc_fdtable(open_files);
++              if (IS_ERR(new_fdt)) {
++                      *errorp = PTR_ERR(new_fdt);
+                       goto out_release;
+               }
+-- 
+2.50.1
+
index ca21709792ed43614afcc2483cc2359549f4fa13..32eee1a33e9304d2d1d029c6a7e13f9b4d0d67af 100644 (file)
@@ -401,3 +401,4 @@ net-sched-remove-unnecessary-warning-condition-for-e.patch
 alsa-usb-audio-use-correct-sub-type-for-uac3-feature.patch
 s390-hypfs-avoid-unnecessary-ioctl-registration-in-d.patch
 s390-hypfs-enable-limited-access-during-lockdown.patch
+alloc_fdtable-change-calling-conventions.patch
diff --git a/queue-6.1/alloc_fdtable-change-calling-conventions.patch b/queue-6.1/alloc_fdtable-change-calling-conventions.patch
new file mode 100644 (file)
index 0000000..1ac8552
--- /dev/null
@@ -0,0 +1,185 @@
+From 3b83cce5beddba8f5162940142f9723fba6b7873 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 6 Aug 2024 22:14:07 -0400
+Subject: alloc_fdtable(): change calling conventions.
+
+From: Al Viro <viro@zeniv.linux.org.uk>
+
+[ Upstream commit 1d3b4bec3ce55e0c46cdce7d0402dbd6b4af3a3d ]
+
+First of all, tell it how many slots do we want, not which slot
+is wanted.  It makes one caller (dup_fd()) more straightforward
+and doesn't harm another (expand_fdtable()).
+
+Furthermore, make it return ERR_PTR() on failure rather than
+returning NULL.  Simplifies the callers.
+
+Simplify the size calculation, while we are at it - note that we
+always have slots_wanted greater than BITS_PER_LONG.  What the
+rules boil down to is
+       * use the smallest power of two large enough to give us
+that many slots
+       * on 32bit skip 64 and 128 - the minimal capacity we want
+there is 256 slots (i.e. 1Kb fd array).
+       * on 64bit don't skip anything, the minimal capacity is
+128 - and we'll never be asked for 64 or less.  128 slots means
+1Kb fd array, again.
+       * on 128bit, if that ever happens, don't skip anything -
+we'll never be asked for 128 or less, so the fd array allocation
+will be at least 2Kb.
+
+Reviewed-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/file.c | 75 +++++++++++++++++++++----------------------------------
+ 1 file changed, 29 insertions(+), 46 deletions(-)
+
+diff --git a/fs/file.c b/fs/file.c
+index ff12a1c1bfc7..e921e6072ada 100644
+--- a/fs/file.c
++++ b/fs/file.c
+@@ -90,18 +90,11 @@ static void copy_fdtable(struct fdtable *nfdt, struct fdtable *ofdt)
+  * 'unsigned long' in some places, but simply because that is how the Linux
+  * kernel bitmaps are defined to work: they are not "bits in an array of bytes",
+  * they are very much "bits in an array of unsigned long".
+- *
+- * The ALIGN(nr, BITS_PER_LONG) here is for clarity: since we just multiplied
+- * by that "1024/sizeof(ptr)" before, we already know there are sufficient
+- * clear low bits. Clang seems to realize that, gcc ends up being confused.
+- *
+- * On a 128-bit machine, the ALIGN() would actually matter. In the meantime,
+- * let's consider it documentation (and maybe a test-case for gcc to improve
+- * its code generation ;)
+  */
+-static struct fdtable * alloc_fdtable(unsigned int nr)
++static struct fdtable *alloc_fdtable(unsigned int slots_wanted)
+ {
+       struct fdtable *fdt;
++      unsigned int nr;
+       void *data;
+       /*
+@@ -109,22 +102,32 @@ static struct fdtable * alloc_fdtable(unsigned int nr)
+        * Allocation steps are keyed to the size of the fdarray, since it
+        * grows far faster than any of the other dynamic data. We try to fit
+        * the fdarray into comfortable page-tuned chunks: starting at 1024B
+-       * and growing in powers of two from there on.
++       * and growing in powers of two from there on.  Since we called only
++       * with slots_wanted > BITS_PER_LONG (embedded instance in files->fdtab
++       * already gives BITS_PER_LONG slots), the above boils down to
++       * 1.  use the smallest power of two large enough to give us that many
++       * slots.
++       * 2.  on 32bit skip 64 and 128 - the minimal capacity we want there is
++       * 256 slots (i.e. 1Kb fd array).
++       * 3.  on 64bit don't skip anything, 1Kb fd array means 128 slots there
++       * and we are never going to be asked for 64 or less.
+        */
+-      nr /= (1024 / sizeof(struct file *));
+-      nr = roundup_pow_of_two(nr + 1);
+-      nr *= (1024 / sizeof(struct file *));
+-      nr = ALIGN(nr, BITS_PER_LONG);
++      if (IS_ENABLED(CONFIG_32BIT) && slots_wanted < 256)
++              nr = 256;
++      else
++              nr = roundup_pow_of_two(slots_wanted);
+       /*
+        * Note that this can drive nr *below* what we had passed if sysctl_nr_open
+-       * had been set lower between the check in expand_files() and here.  Deal
+-       * with that in caller, it's cheaper that way.
++       * had been set lower between the check in expand_files() and here.
+        *
+        * We make sure that nr remains a multiple of BITS_PER_LONG - otherwise
+        * bitmaps handling below becomes unpleasant, to put it mildly...
+        */
+-      if (unlikely(nr > sysctl_nr_open))
+-              nr = ((sysctl_nr_open - 1) | (BITS_PER_LONG - 1)) + 1;
++      if (unlikely(nr > sysctl_nr_open)) {
++              nr = round_down(sysctl_nr_open, BITS_PER_LONG);
++              if (nr < slots_wanted)
++                      return ERR_PTR(-EMFILE);
++      }
+       /*
+        * Check if the allocation size would exceed INT_MAX. kvmalloc_array()
+@@ -168,7 +171,7 @@ static struct fdtable * alloc_fdtable(unsigned int nr)
+ out_fdt:
+       kfree(fdt);
+ out:
+-      return NULL;
++      return ERR_PTR(-ENOMEM);
+ }
+ /*
+@@ -185,7 +188,7 @@ static int expand_fdtable(struct files_struct *files, unsigned int nr)
+       struct fdtable *new_fdt, *cur_fdt;
+       spin_unlock(&files->file_lock);
+-      new_fdt = alloc_fdtable(nr);
++      new_fdt = alloc_fdtable(nr + 1);
+       /* make sure all fd_install() have seen resize_in_progress
+        * or have finished their rcu_read_lock_sched() section.
+@@ -194,16 +197,8 @@ static int expand_fdtable(struct files_struct *files, unsigned int nr)
+               synchronize_rcu();
+       spin_lock(&files->file_lock);
+-      if (!new_fdt)
+-              return -ENOMEM;
+-      /*
+-       * extremely unlikely race - sysctl_nr_open decreased between the check in
+-       * caller and alloc_fdtable().  Cheaper to catch it here...
+-       */
+-      if (unlikely(new_fdt->max_fds <= nr)) {
+-              __free_fdtable(new_fdt);
+-              return -EMFILE;
+-      }
++      if (IS_ERR(new_fdt))
++              return PTR_ERR(new_fdt);
+       cur_fdt = files_fdtable(files);
+       BUG_ON(nr < cur_fdt->max_fds);
+       copy_fdtable(new_fdt, cur_fdt);
+@@ -317,7 +312,6 @@ struct files_struct *dup_fd(struct files_struct *oldf, struct fd_range *punch_ho
+       struct file **old_fds, **new_fds;
+       unsigned int open_files, i;
+       struct fdtable *old_fdt, *new_fdt;
+-      int error;
+       newf = kmem_cache_alloc(files_cachep, GFP_KERNEL);
+       if (!newf)
+@@ -349,17 +343,10 @@ struct files_struct *dup_fd(struct files_struct *oldf, struct fd_range *punch_ho
+               if (new_fdt != &newf->fdtab)
+                       __free_fdtable(new_fdt);
+-              new_fdt = alloc_fdtable(open_files - 1);
+-              if (!new_fdt) {
+-                      error = -ENOMEM;
+-                      goto out_release;
+-              }
+-
+-              /* beyond sysctl_nr_open; nothing to do */
+-              if (unlikely(new_fdt->max_fds < open_files)) {
+-                      __free_fdtable(new_fdt);
+-                      error = -EMFILE;
+-                      goto out_release;
++              new_fdt = alloc_fdtable(open_files);
++              if (IS_ERR(new_fdt)) {
++                      kmem_cache_free(files_cachep, newf);
++                      return ERR_CAST(new_fdt);
+               }
+               /*
+@@ -408,10 +395,6 @@ struct files_struct *dup_fd(struct files_struct *oldf, struct fd_range *punch_ho
+       rcu_assign_pointer(newf->fdt, new_fdt);
+       return newf;
+-
+-out_release:
+-      kmem_cache_free(files_cachep, newf);
+-      return ERR_PTR(error);
+ }
+ static struct fdtable *close_files(struct files_struct * files)
+-- 
+2.50.1
+
index bd93fbf9ee3b99b2645e5d16c4d5787440a686e8..358bc3d8d520b8f46b7b292763a01458f1d0b1ab 100644 (file)
@@ -480,3 +480,4 @@ alsa-usb-audio-use-correct-sub-type-for-uac3-feature.patch
 s390-hypfs-avoid-unnecessary-ioctl-registration-in-d.patch
 s390-hypfs-enable-limited-access-during-lockdown.patch
 netfilter-nf_reject-don-t-leak-dst-refcount-for-loop.patch
+alloc_fdtable-change-calling-conventions.patch
diff --git a/queue-6.6/alloc_fdtable-change-calling-conventions.patch b/queue-6.6/alloc_fdtable-change-calling-conventions.patch
new file mode 100644 (file)
index 0000000..6da50ed
--- /dev/null
@@ -0,0 +1,185 @@
+From 5e3a95cfae7081f09c3c534d066d9d4597d25638 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 6 Aug 2024 22:14:07 -0400
+Subject: alloc_fdtable(): change calling conventions.
+
+From: Al Viro <viro@zeniv.linux.org.uk>
+
+[ Upstream commit 1d3b4bec3ce55e0c46cdce7d0402dbd6b4af3a3d ]
+
+First of all, tell it how many slots do we want, not which slot
+is wanted.  It makes one caller (dup_fd()) more straightforward
+and doesn't harm another (expand_fdtable()).
+
+Furthermore, make it return ERR_PTR() on failure rather than
+returning NULL.  Simplifies the callers.
+
+Simplify the size calculation, while we are at it - note that we
+always have slots_wanted greater than BITS_PER_LONG.  What the
+rules boil down to is
+       * use the smallest power of two large enough to give us
+that many slots
+       * on 32bit skip 64 and 128 - the minimal capacity we want
+there is 256 slots (i.e. 1Kb fd array).
+       * on 64bit don't skip anything, the minimal capacity is
+128 - and we'll never be asked for 64 or less.  128 slots means
+1Kb fd array, again.
+       * on 128bit, if that ever happens, don't skip anything -
+we'll never be asked for 128 or less, so the fd array allocation
+will be at least 2Kb.
+
+Reviewed-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/file.c | 75 +++++++++++++++++++++----------------------------------
+ 1 file changed, 29 insertions(+), 46 deletions(-)
+
+diff --git a/fs/file.c b/fs/file.c
+index 255645b20dca..0ce6a6930276 100644
+--- a/fs/file.c
++++ b/fs/file.c
+@@ -90,18 +90,11 @@ static void copy_fdtable(struct fdtable *nfdt, struct fdtable *ofdt)
+  * 'unsigned long' in some places, but simply because that is how the Linux
+  * kernel bitmaps are defined to work: they are not "bits in an array of bytes",
+  * they are very much "bits in an array of unsigned long".
+- *
+- * The ALIGN(nr, BITS_PER_LONG) here is for clarity: since we just multiplied
+- * by that "1024/sizeof(ptr)" before, we already know there are sufficient
+- * clear low bits. Clang seems to realize that, gcc ends up being confused.
+- *
+- * On a 128-bit machine, the ALIGN() would actually matter. In the meantime,
+- * let's consider it documentation (and maybe a test-case for gcc to improve
+- * its code generation ;)
+  */
+-static struct fdtable * alloc_fdtable(unsigned int nr)
++static struct fdtable *alloc_fdtable(unsigned int slots_wanted)
+ {
+       struct fdtable *fdt;
++      unsigned int nr;
+       void *data;
+       /*
+@@ -109,22 +102,32 @@ static struct fdtable * alloc_fdtable(unsigned int nr)
+        * Allocation steps are keyed to the size of the fdarray, since it
+        * grows far faster than any of the other dynamic data. We try to fit
+        * the fdarray into comfortable page-tuned chunks: starting at 1024B
+-       * and growing in powers of two from there on.
++       * and growing in powers of two from there on.  Since we called only
++       * with slots_wanted > BITS_PER_LONG (embedded instance in files->fdtab
++       * already gives BITS_PER_LONG slots), the above boils down to
++       * 1.  use the smallest power of two large enough to give us that many
++       * slots.
++       * 2.  on 32bit skip 64 and 128 - the minimal capacity we want there is
++       * 256 slots (i.e. 1Kb fd array).
++       * 3.  on 64bit don't skip anything, 1Kb fd array means 128 slots there
++       * and we are never going to be asked for 64 or less.
+        */
+-      nr /= (1024 / sizeof(struct file *));
+-      nr = roundup_pow_of_two(nr + 1);
+-      nr *= (1024 / sizeof(struct file *));
+-      nr = ALIGN(nr, BITS_PER_LONG);
++      if (IS_ENABLED(CONFIG_32BIT) && slots_wanted < 256)
++              nr = 256;
++      else
++              nr = roundup_pow_of_two(slots_wanted);
+       /*
+        * Note that this can drive nr *below* what we had passed if sysctl_nr_open
+-       * had been set lower between the check in expand_files() and here.  Deal
+-       * with that in caller, it's cheaper that way.
++       * had been set lower between the check in expand_files() and here.
+        *
+        * We make sure that nr remains a multiple of BITS_PER_LONG - otherwise
+        * bitmaps handling below becomes unpleasant, to put it mildly...
+        */
+-      if (unlikely(nr > sysctl_nr_open))
+-              nr = ((sysctl_nr_open - 1) | (BITS_PER_LONG - 1)) + 1;
++      if (unlikely(nr > sysctl_nr_open)) {
++              nr = round_down(sysctl_nr_open, BITS_PER_LONG);
++              if (nr < slots_wanted)
++                      return ERR_PTR(-EMFILE);
++      }
+       /*
+        * Check if the allocation size would exceed INT_MAX. kvmalloc_array()
+@@ -168,7 +171,7 @@ static struct fdtable * alloc_fdtable(unsigned int nr)
+ out_fdt:
+       kfree(fdt);
+ out:
+-      return NULL;
++      return ERR_PTR(-ENOMEM);
+ }
+ /*
+@@ -185,7 +188,7 @@ static int expand_fdtable(struct files_struct *files, unsigned int nr)
+       struct fdtable *new_fdt, *cur_fdt;
+       spin_unlock(&files->file_lock);
+-      new_fdt = alloc_fdtable(nr);
++      new_fdt = alloc_fdtable(nr + 1);
+       /* make sure all fd_install() have seen resize_in_progress
+        * or have finished their rcu_read_lock_sched() section.
+@@ -194,16 +197,8 @@ static int expand_fdtable(struct files_struct *files, unsigned int nr)
+               synchronize_rcu();
+       spin_lock(&files->file_lock);
+-      if (!new_fdt)
+-              return -ENOMEM;
+-      /*
+-       * extremely unlikely race - sysctl_nr_open decreased between the check in
+-       * caller and alloc_fdtable().  Cheaper to catch it here...
+-       */
+-      if (unlikely(new_fdt->max_fds <= nr)) {
+-              __free_fdtable(new_fdt);
+-              return -EMFILE;
+-      }
++      if (IS_ERR(new_fdt))
++              return PTR_ERR(new_fdt);
+       cur_fdt = files_fdtable(files);
+       BUG_ON(nr < cur_fdt->max_fds);
+       copy_fdtable(new_fdt, cur_fdt);
+@@ -317,7 +312,6 @@ struct files_struct *dup_fd(struct files_struct *oldf, struct fd_range *punch_ho
+       struct file **old_fds, **new_fds;
+       unsigned int open_files, i;
+       struct fdtable *old_fdt, *new_fdt;
+-      int error;
+       newf = kmem_cache_alloc(files_cachep, GFP_KERNEL);
+       if (!newf)
+@@ -349,17 +343,10 @@ struct files_struct *dup_fd(struct files_struct *oldf, struct fd_range *punch_ho
+               if (new_fdt != &newf->fdtab)
+                       __free_fdtable(new_fdt);
+-              new_fdt = alloc_fdtable(open_files - 1);
+-              if (!new_fdt) {
+-                      error = -ENOMEM;
+-                      goto out_release;
+-              }
+-
+-              /* beyond sysctl_nr_open; nothing to do */
+-              if (unlikely(new_fdt->max_fds < open_files)) {
+-                      __free_fdtable(new_fdt);
+-                      error = -EMFILE;
+-                      goto out_release;
++              new_fdt = alloc_fdtable(open_files);
++              if (IS_ERR(new_fdt)) {
++                      kmem_cache_free(files_cachep, newf);
++                      return ERR_CAST(new_fdt);
+               }
+               /*
+@@ -408,10 +395,6 @@ struct files_struct *dup_fd(struct files_struct *oldf, struct fd_range *punch_ho
+       rcu_assign_pointer(newf->fdt, new_fdt);
+       return newf;
+-
+-out_release:
+-      kmem_cache_free(files_cachep, newf);
+-      return ERR_PTR(error);
+ }
+ static struct fdtable *close_files(struct files_struct * files)
+-- 
+2.50.1
+
index 95883029a6b5696770cbe44e77d88a68fe970080..c89920678d1f02f7c6cc5f7e0b38668162194b31 100644 (file)
@@ -585,3 +585,4 @@ alsa-usb-audio-use-correct-sub-type-for-uac3-feature.patch
 s390-hypfs-avoid-unnecessary-ioctl-registration-in-d.patch
 s390-hypfs-enable-limited-access-during-lockdown.patch
 netfilter-nf_reject-don-t-leak-dst-refcount-for-loop.patch
+alloc_fdtable-change-calling-conventions.patch