In memfd_luo_preserve_folios(), two variables had types that could cause
silent data loss with large files:
1. 'size' was declared as 'long', truncating the 64-bit result of
i_size_read(). On 32-bit systems a 4GB file would be truncated to 0,
causing the function to return early and discard all data.
2. 'max_folios' was declared as 'unsigned int', causing overflow for
sparse files larger than 4TB. For example, a 16TB+4KB file would
calculate 0x100000001 folios but truncate to 1 when assigned to
max_folios, causing memfd_pin_folios() to pin only the first folio.
Fix by changing both variables to 'u64' to match the types returned
by i_size_read() and the folio count calculations.
This issue was identified by the AI review.
https://sashiko.dev/#/patchset/20260323110747.193569-1-duanchenghao@kylinos.cn
Signed-off-by: Chenghao Duan <duanchenghao@kylinos.cn>
---
mm/memfd_luo.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/mm/memfd_luo.c b/mm/memfd_luo.c
index f8e8f99b1848..4b4fa2f658d9 100644
--- a/mm/memfd_luo.c
+++ b/mm/memfd_luo.c
@@ -88,8 +88,8 @@ static int memfd_luo_preserve_folios(struct file *file,
{
struct inode *inode = file_inode(file);
struct memfd_luo_folio_ser *folios_ser;
- unsigned int max_folios;
- long i, size, nr_pinned;
+ u64 size, max_folios;
+ long i, nr_pinned;
struct folio **folios;
int err = -EINVAL;
pgoff_t offset;
--
2.25.1
On Thu, Mar 26 2026, Chenghao Duan wrote: > In memfd_luo_preserve_folios(), two variables had types that could cause > silent data loss with large files: > > 1. 'size' was declared as 'long', truncating the 64-bit result of > i_size_read(). On 32-bit systems a 4GB file would be truncated to 0, > causing the function to return early and discard all data. As Pasha said, KHO and LUO are not expected to run on 32-bit systems. Plus, since i_size_read() returns loff_t, why use u64 when you can just match the type and just use loff_t (which on 64-bit is long anyway)? I don't get why u64 is any better than long or loff_t. > > 2. 'max_folios' was declared as 'unsigned int', causing overflow for > sparse files larger than 4TB. For example, a 16TB+4KB file would > calculate 0x100000001 folios but truncate to 1 when assigned to > max_folios, causing memfd_pin_folios() to pin only the first folio. Using unsigned int was intentional. We pass max_folios to memfd_pin_folios(), which expects an unsigned int. So this change is pointless unless you go and update memfd_pin_folios() too. I think making memfd_pin_folios() use unsigned long for max_folios makes a lot of sense, so can you please go update that first before making this change? And when you do, please match the type of the argument to the type you use here instead of using u64. This can be a separate, independent patch series. > > Fix by changing both variables to 'u64' to match the types returned > by i_size_read() and the folio count calculations. > > This issue was identified by the AI review. > https://sashiko.dev/#/patchset/20260323110747.193569-1-duanchenghao@kylinos.cn > > Signed-off-by: Chenghao Duan <duanchenghao@kylinos.cn> [...] -- Regards, Pratyush Yadav
On Thu, 02 Apr 2026 12:06:58 +0000 Pratyush Yadav <pratyush@kernel.org> wrote: > On Thu, Mar 26 2026, Chenghao Duan wrote: > > > In memfd_luo_preserve_folios(), two variables had types that could cause > > silent data loss with large files: > > > > 1. 'size' was declared as 'long', truncating the 64-bit result of > > i_size_read(). On 32-bit systems a 4GB file would be truncated to 0, > > causing the function to return early and discard all data. > > As Pasha said, KHO and LUO are not expected to run on 32-bit systems. > Plus, since i_size_read() returns loff_t, why use u64 when you can just > match the type and just use loff_t (which on 64-bit is long anyway)? I > don't get why u64 is any better than long or loff_t. > > > > > 2. 'max_folios' was declared as 'unsigned int', causing overflow for > > sparse files larger than 4TB. For example, a 16TB+4KB file would > > calculate 0x100000001 folios but truncate to 1 when assigned to > > max_folios, causing memfd_pin_folios() to pin only the first folio. > > Using unsigned int was intentional. We pass max_folios to > memfd_pin_folios(), which expects an unsigned int. So this change is > pointless unless you go and update memfd_pin_folios() too. > > I think making memfd_pin_folios() use unsigned long for max_folios makes > a lot of sense, so can you please go update that first before making > this change? And when you do, please match the type of the argument to > the type you use here instead of using u64. This can be a separate, > independent patch series. Thanks. I'll drop this patch. The preceding six patches are looking well-reviewed and ready to go? Chenghao, please prepare any update for this patch against the preceding six. Or against tomorrow's mm-unstable or mm-new or linux-next.
On Thu, Mar 26, 2026 at 4:48 AM Chenghao Duan <duanchenghao@kylinos.cn> wrote: > > In memfd_luo_preserve_folios(), two variables had types that could cause > silent data loss with large files: > > 1. 'size' was declared as 'long', truncating the 64-bit result of > i_size_read(). On 32-bit systems a 4GB file would be truncated to 0, This is not an issue, KHO only supports 64-bit systems, but using the correct type is a good idea anyway. > causing the function to return early and discard all data. > > 2. 'max_folios' was declared as 'unsigned int', causing overflow for > sparse files larger than 4TB. For example, a 16TB+4KB file would > calculate 0x100000001 folios but truncate to 1 when assigned to > max_folios, causing memfd_pin_folios() to pin only the first folio. > > Fix by changing both variables to 'u64' to match the types returned > by i_size_read() and the folio count calculations. Strictly speaking, i_size_read() returns loff_t which is 'long long', so s64 not u64, but anyways u64 works here. Reviewed-by: Pasha Tatashin <pasha.tatashin@soleen.com>
© 2016 - 2026 Red Hat, Inc.