]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
fs: ntfs3: Fix integer overflow in run_unpack()
authorVitaly Grigoryev <Vitaly.Grigoryev@kaspersky.com>
Mon, 25 Aug 2025 10:08:55 +0000 (13:08 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 15 Oct 2025 09:56:33 +0000 (11:56 +0200)
[ Upstream commit 736fc7bf5f68f6b74a0925b7e072c571838657d2 ]

The MFT record relative to the file being opened contains its runlist,
an array containing information about the file's location on the physical
disk. Analysis of all Call Stack paths showed that the values of the
runlist array, from which LCNs are calculated, are not validated before
run_unpack function.

The run_unpack function decodes the compressed runlist data format
from MFT attributes (for example, $DATA), converting them into a runs_tree
structure, which describes the mapping of virtual clusters (VCN) to
logical clusters (LCN). The NTFS3 subsystem also has a shortcut for
deleting files from MFT records - in this case, the RUN_DEALLOCATE
command is sent to the run_unpack input, and the function logic
provides that all data transferred to the runlist about file or
directory is deleted without creating a runs_tree structure.

Substituting the runlist in the $DATA attribute of the MFT record for an
arbitrary file can lead either to access to arbitrary data on the disk
bypassing access checks to them (since the inode access check
occurs above) or to destruction of arbitrary data on the disk.

Add overflow check for addition operation.

Found by Linux Verification Center (linuxtesting.org) with SVACE.

Fixes: 4342306f0f0d ("fs/ntfs3: Add file operations and implementation")
Signed-off-by: Vitaly Grigoryev <Vitaly.Grigoryev@kaspersky.com>
Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
fs/ntfs3/run.c

index 12d8682f33b538dea9dcd1120b6a59a8a7999ccd..340a4cbe8b5ca2cd731f74451e2b9169b6447245 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/blkdev.h>
 #include <linux/fs.h>
 #include <linux/log2.h>
+#include <linux/overflow.h>
 
 #include "debug.h"
 #include "ntfs.h"
@@ -982,12 +983,16 @@ int run_unpack(struct runs_tree *run, struct ntfs_sb_info *sbi, CLST ino,
 
                        if (!dlcn)
                                return -EINVAL;
-                       lcn = prev_lcn + dlcn;
+
+                       if (check_add_overflow(prev_lcn, dlcn, &lcn))
+                               return -EINVAL;
                        prev_lcn = lcn;
                } else
                        return -EINVAL;
 
-               next_vcn = vcn64 + len;
+               if (check_add_overflow(vcn64, len, &next_vcn))
+                       return -EINVAL;
+
                /* Check boundary. */
                if (next_vcn > evcn + 1)
                        return -EINVAL;
@@ -1148,7 +1153,8 @@ int run_get_highest_vcn(CLST vcn, const u8 *run_buf, u64 *highest_vcn)
                        return -EINVAL;
 
                run_buf += size_size + offset_size;
-               vcn64 += len;
+               if (check_add_overflow(vcn64, len, &vcn64))
+                       return -EINVAL;
 
 #ifndef CONFIG_NTFS3_64BIT_CLUSTER
                if (vcn64 > 0x100000000ull)