Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

exfat driver may fail to write files with a size > 4GB when used in a 32bit kernel #32

Open
jerryatpb opened this issue Jan 24, 2022 · 5 comments

Comments

@jerryatpb
Copy link

The exfat driver fails to write files with a size > 4GB when these conditions are met:

  • The kernel is built for a 32bit system
  • The kernel config switch CONFIG_LBDAF is not set (i.e. no files > 2TB are supported)

We stumbled upon this when integrating the driver into our 32bit embedded Linux ecosystem.

The reason for this is an integer overflow when converting number of blocks into a file position, as for instance here:
https://github.com/namjaejeon/linux-exfat-oot/blob/5.14.1/inode.c#L338
Line:
pos = EXFAT_BLK_TO_B((iblock + 1), sb);
which translates to:
pos = (iblock + 1) << sb->s_blocksize_bits;

iblock is of type sector_t. Normally this is a 64bit integer, but on a 32bit system without CONFIG_LBDAF being set, it is just 32bit.
pos, on the other hand is a full 64bit integer

Unfortunately, the compiler performs the calculation in 32bit range without issuing a warning. As a result, an overflow will occur as soon as the file size reaches 4GB

A simple fix would be:
pos = EXFAT_BLK_TO_B((loff_t)(iblock + 1), sb);
This makes sure that the left side is cast to 64bit before shifting it.

Attention:
We've located a few more such lines where potentially 32bit-overflow-prone left-shifts are done, namely:
https://github.com/namjaejeon/linux-exfat-oot/blob/5.14.1/dir.c#L171
https://github.com/namjaejeon/linux-exfat-oot/blob/5.14.1/dir.c#L187
https://github.com/namjaejeon/linux-exfat-oot/blob/5.14.1/inode.c#L249
https://github.com/namjaejeon/linux-exfat-oot/blob/5.14.1/inode.c#L338
https://github.com/namjaejeon/linux-exfat-oot/blob/5.14.1/inode.c#L357
https://github.com/namjaejeon/linux-exfat-oot/blob/5.14.1/namei.c#L402
https://github.com/namjaejeon/linux-exfat-oot/blob/5.14.1/namei.c#L1292
https://github.com/namjaejeon/linux-exfat-oot/blob/5.14.1/super.c#L592
In general, all lines where types sector_t or blkcnt_t are used with a left-shift operator should be considered.

@namjaejeon
Copy link
Owner

Thanks for your suggestion! Can you send the patch to me ?

@jerryatpb
Copy link
Author

jerryatpb commented Jan 24, 2022 via email

@namjaejeon
Copy link
Owner

@jerryatpb Okay!

@namjaejeon
Copy link
Owner

Ah, I can see this patch (https://patchwork.kernel.org/project/linux-block/patch/[email protected]/)
So there is no issue with this patch since linux 5.2 kernel. What kernel version do you used ?
And can you make the patch like this ?

#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0)
pos = EXFAT_BLK_TO_B((loff_t)(iblock + 1), sb);
#else
pos = EXFAT_BLK_TO_B((iblock + 1), sb);
#endif

@jerryatpb
Copy link
Author

Our patch is based on your commit 1c014cb. Since it is really, really small I've simply attached it here. We're using Kernel version 4.14.

linux-exfat-oot-master_1c014cb_32bit.patch.txt

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants