Skip to content

Commit 736fc7b

Browse files
Vitaly Grigoryevaalexandrovich
authored andcommitted
fs: ntfs3: Fix integer overflow in run_unpack()
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: 4342306 ("fs/ntfs3: Add file operations and implementation") Signed-off-by: Vitaly Grigoryev <[email protected]> Signed-off-by: Konstantin Komarov <[email protected]>
1 parent 4e8011f commit 736fc7b

File tree

1 file changed

+9
-3
lines changed

1 file changed

+9
-3
lines changed

fs/ntfs3/run.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <linux/blkdev.h>
1010
#include <linux/fs.h>
1111
#include <linux/log2.h>
12+
#include <linux/overflow.h>
1213

1314
#include "debug.h"
1415
#include "ntfs.h"
@@ -982,14 +983,18 @@ int run_unpack(struct runs_tree *run, struct ntfs_sb_info *sbi, CLST ino,
982983

983984
if (!dlcn)
984985
return -EINVAL;
985-
lcn = prev_lcn + dlcn;
986+
987+
if (check_add_overflow(prev_lcn, dlcn, &lcn))
988+
return -EINVAL;
986989
prev_lcn = lcn;
987990
} else {
988991
/* The size of 'dlcn' can't be > 8. */
989992
return -EINVAL;
990993
}
991994

992-
next_vcn = vcn64 + len;
995+
if (check_add_overflow(vcn64, len, &next_vcn))
996+
return -EINVAL;
997+
993998
/* Check boundary. */
994999
if (next_vcn > evcn + 1)
9951000
return -EINVAL;
@@ -1153,7 +1158,8 @@ int run_get_highest_vcn(CLST vcn, const u8 *run_buf, u64 *highest_vcn)
11531158
return -EINVAL;
11541159

11551160
run_buf += size_size + offset_size;
1156-
vcn64 += len;
1161+
if (check_add_overflow(vcn64, len, &vcn64))
1162+
return -EINVAL;
11571163

11581164
#ifndef CONFIG_NTFS3_64BIT_CLUSTER
11591165
if (vcn64 > 0x100000000ull)

0 commit comments

Comments
 (0)