]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for all trees
authorSasha Levin <sashal@kernel.org>
Mon, 25 Aug 2025 19:47:48 +0000 (15:47 -0400)
committerSasha Levin <sashal@kernel.org>
Mon, 25 Aug 2025 19:47:48 +0000 (15:47 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-6.12/alloc_fdtable-change-calling-conventions.patch [new file with mode: 0644]
queue-6.12/series

diff --git a/queue-6.12/alloc_fdtable-change-calling-conventions.patch b/queue-6.12/alloc_fdtable-change-calling-conventions.patch
new file mode 100644 (file)
index 0000000..cbf033b
--- /dev/null
@@ -0,0 +1,185 @@
+From 192e8b8d7e2f4ce941a89c1b5a5f3334fe8387d9 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 4579c3296498..bfc9eb9e7229 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);
+@@ -322,7 +317,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)
+@@ -354,17 +348,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);
+               }
+               /*
+@@ -413,10 +400,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 1ed50ef6895e2e9284aa5d835a938dd415644eb8..ca5dd2f08c4b4a783545298c573bf290f0744f11 100644 (file)
@@ -319,3 +319,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