From: Sasha Levin Date: Wed, 27 Aug 2025 03:27:56 +0000 (-0400) Subject: Fixes for all trees X-Git-Tag: v5.4.297~2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=6c13d1c93c4aa470da288b0acf5668aad219a8ac;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for all trees Signed-off-by: Sasha Levin --- 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 index 0000000000..134355b9fb --- /dev/null +++ b/queue-5.10/alloc_fdtable-change-calling-conventions.patch @@ -0,0 +1,164 @@ +From b452d7883a5e165999fc57720a32cef809a134d4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 26 Aug 2025 17:27:47 -0400 +Subject: alloc_fdtable(): change calling conventions. + +From: Al Viro + +[ 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 +Signed-off-by: Al Viro +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.10/series b/queue-5.10/series index 8dbcdf5c1c..07ce3a2f57 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -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 index 0000000000..a215f41cad --- /dev/null +++ b/queue-5.15/alloc_fdtable-change-calling-conventions.patch @@ -0,0 +1,185 @@ +From c5114b0875a73ef7ada0de96e4bc19d94ead727a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 6 Aug 2024 22:14:07 -0400 +Subject: alloc_fdtable(): change calling conventions. + +From: Al Viro + +[ 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 +Signed-off-by: Al Viro +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/series b/queue-5.15/series index d91d0dad6f..86ee57d5be 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -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 index 0000000000..d90819c013 --- /dev/null +++ b/queue-5.4/alloc_fdtable-change-calling-conventions.patch @@ -0,0 +1,161 @@ +From 70d092d36ea4dc7da3427d8d691c10fc3fddc8cb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 26 Aug 2025 17:27:47 -0400 +Subject: alloc_fdtable(): change calling conventions. + +From: Al Viro + +[ 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 +Signed-off-by: Al Viro +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.4/series b/queue-5.4/series index ca21709792..32eee1a33e 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -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 index 0000000000..1ac8552299 --- /dev/null +++ b/queue-6.1/alloc_fdtable-change-calling-conventions.patch @@ -0,0 +1,185 @@ +From 3b83cce5beddba8f5162940142f9723fba6b7873 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 6 Aug 2024 22:14:07 -0400 +Subject: alloc_fdtable(): change calling conventions. + +From: Al Viro + +[ 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 +Signed-off-by: Al Viro +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/series b/queue-6.1/series index bd93fbf9ee..358bc3d8d5 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -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 index 0000000000..6da50ed1f6 --- /dev/null +++ b/queue-6.6/alloc_fdtable-change-calling-conventions.patch @@ -0,0 +1,185 @@ +From 5e3a95cfae7081f09c3c534d066d9d4597d25638 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 6 Aug 2024 22:14:07 -0400 +Subject: alloc_fdtable(): change calling conventions. + +From: Al Viro + +[ 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 +Signed-off-by: Al Viro +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.6/series b/queue-6.6/series index 95883029a6..c89920678d 100644 --- a/queue-6.6/series +++ b/queue-6.6/series @@ -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