aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRandy Dunlap <[email protected]>2022-05-12 20:38:37 -0700
committerAndrew Morton <[email protected]>2022-05-12 20:38:37 -0700
commita3b774342fa752a5290c0de36375289dfcf4a260 (patch)
treef48108dace8ad58195207d2f8b5242127ce69657
parentcd290a9839cee2f6641558877e707bd373c8f6f1 (diff)
fs/ntfs3: validate BOOT sectors_per_clusters
When the NTFS BOOT sectors_per_clusters field is > 0x80, it represents a shift value. Make sure that the shift value is not too large before using it (NTFS max cluster size is 2MB). Return -EVINVAL if it too large. This prevents negative shift values and shift values that are larger than the field size. Prevents this UBSAN error: UBSAN: shift-out-of-bounds in ../fs/ntfs3/super.c:673:16 shift exponent -192 is negative Link: https://lkml.kernel.org/r/[email protected] Fixes: 82cae269cfa9 ("fs/ntfs3: Add initialization of super block") Signed-off-by: Randy Dunlap <[email protected]> Reported-by: [email protected] Reviewed-by: Namjae Jeon <[email protected]> Cc: Konstantin Komarov <[email protected]> Cc: Alexander Viro <[email protected]> Cc: Kari Argillander <[email protected]> Cc: Namjae Jeon <[email protected]> Cc: Matthew Wilcox <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
-rw-r--r--fs/ntfs3/super.c10
1 files changed, 7 insertions, 3 deletions
diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c
index 278dcf502410..b2b54c4553f9 100644
--- a/fs/ntfs3/super.c
+++ b/fs/ntfs3/super.c
@@ -668,9 +668,11 @@ static u32 format_size_gb(const u64 bytes, u32 *mb)
static u32 true_sectors_per_clst(const struct NTFS_BOOT *boot)
{
- return boot->sectors_per_clusters <= 0x80
- ? boot->sectors_per_clusters
- : (1u << (0 - boot->sectors_per_clusters));
+ if (boot->sectors_per_clusters <= 0x80)
+ return boot->sectors_per_clusters;
+ if (boot->sectors_per_clusters >= 0xf4) /* limit shift to 2MB max */
+ return 1U << (0 - boot->sectors_per_clusters);
+ return -EINVAL;
}
/*
@@ -713,6 +715,8 @@ static int ntfs_init_from_boot(struct super_block *sb, u32 sector_size,
/* cluster size: 512, 1K, 2K, 4K, ... 2M */
sct_per_clst = true_sectors_per_clst(boot);
+ if ((int)sct_per_clst < 0)
+ goto out;
if (!is_power_of_2(sct_per_clst))
goto out;