Skip to content

Commit

Permalink
fs/ntfs3: Validate data run offset
Browse files Browse the repository at this point in the history
This adds sanity checks for data run offset. We should make sure data
run offset is legit before trying to unpack them, otherwise we may
encounter use-after-free or some unexpected memory access behaviors.

[   82.940342] BUG: KASAN: use-after-free in run_unpack+0x2e3/0x570
[   82.941180] Read of size 1 at addr ffff888008a8487f by task mount/240
[   82.941670]
[   82.942069] CPU: 0 PID: 240 Comm: mount Not tainted 5.19.0+ linux-sunxi#15
[   82.942482] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.14.0-0-g155821a1990b-prebuilt.qemu.org 04/01/2014
[   82.943720] Call Trace:
[   82.944204]  <TASK>
[   82.944471]  dump_stack_lvl+0x49/0x63
[   82.944908]  print_report.cold+0xf5/0x67b
[   82.945141]  ? __wait_on_bit+0x106/0x120
[   82.945750]  ? run_unpack+0x2e3/0x570
[   82.946626]  kasan_report+0xa7/0x120
[   82.947046]  ? run_unpack+0x2e3/0x570
[   82.947280]  __asan_load1+0x51/0x60
[   82.947483]  run_unpack+0x2e3/0x570
[   82.947709]  ? memcpy+0x4e/0x70
[   82.947927]  ? run_pack+0x7a0/0x7a0
[   82.948158]  run_unpack_ex+0xad/0x3f0
[   82.948399]  ? mi_enum_attr+0x14a/0x200
[   82.948717]  ? run_unpack+0x570/0x570
[   82.949072]  ? ni_enum_attr_ex+0x1b2/0x1c0
[   82.949332]  ? ni_fname_type.part.0+0xd0/0xd0
[   82.949611]  ? mi_read+0x262/0x2c0
[   82.949970]  ? ntfs_cmp_names_cpu+0x125/0x180
[   82.950249]  ntfs_iget5+0x632/0x1870
[   82.950621]  ? ntfs_get_block_bmap+0x70/0x70
[   82.951192]  ? evict+0x223/0x280
[   82.951525]  ? iput.part.0+0x286/0x320
[   82.951969]  ntfs_fill_super+0x1321/0x1e20
[   82.952436]  ? put_ntfs+0x1d0/0x1d0
[   82.952822]  ? vsprintf+0x20/0x20
[   82.953188]  ? mutex_unlock+0x81/0xd0
[   82.953379]  ? set_blocksize+0x95/0x150
[   82.954001]  get_tree_bdev+0x232/0x370
[   82.954438]  ? put_ntfs+0x1d0/0x1d0
[   82.954700]  ntfs_fs_get_tree+0x15/0x20
[   82.955049]  vfs_get_tree+0x4c/0x130
[   82.955292]  path_mount+0x645/0xfd0
[   82.955615]  ? putname+0x80/0xa0
[   82.955955]  ? finish_automount+0x2e0/0x2e0
[   82.956310]  ? kmem_cache_free+0x110/0x390
[   82.956723]  ? putname+0x80/0xa0
[   82.957023]  do_mount+0xd6/0xf0
[   82.957411]  ? path_mount+0xfd0/0xfd0
[   82.957638]  ? __kasan_check_write+0x14/0x20
[   82.957948]  __x64_sys_mount+0xca/0x110
[   82.958310]  do_syscall_64+0x3b/0x90
[   82.958719]  entry_SYSCALL_64_after_hwframe+0x63/0xcd
[   82.959341] RIP: 0033:0x7fd0d1ce948a
[   82.960193] Code: 48 8b 0d 11 fa 2a 00 f7 d8 64 89 01 48 83 c8 ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 49 89 ca b8 a5 00 00 008
[   82.961532] RSP: 002b:00007ffe59ff69a8 EFLAGS: 00000202 ORIG_RAX: 00000000000000a5
[   82.962527] RAX: ffffffffffffffda RBX: 0000564dcc107060 RCX: 00007fd0d1ce948a
[   82.963266] RDX: 0000564dcc107260 RSI: 0000564dcc1072e0 RDI: 0000564dcc10fce0
[   82.963686] RBP: 0000000000000000 R08: 0000564dcc107280 R09: 0000000000000020
[   82.964272] R10: 00000000c0ed0000 R11: 0000000000000202 R12: 0000564dcc10fce0
[   82.964785] R13: 0000564dcc107260 R14: 0000000000000000 R15: 00000000ffffffff

Signed-off-by: Edward Lo <edward.lo@ambergroup.io>
Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
  • Loading branch information
Elden-Ring authored and aalexandrovich committed Sep 30, 2022
1 parent e19c627 commit 6db6208
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 0 deletions.
13 changes: 13 additions & 0 deletions fs/ntfs3/attrib.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,10 @@ static int attr_load_runs(struct ATTRIB *attr, struct ntfs_inode *ni,

asize = le32_to_cpu(attr->size);
run_off = le16_to_cpu(attr->nres.run_off);

if (run_off > asize)
return -EINVAL;

err = run_unpack_ex(run, ni->mi.sbi, ni->mi.rno, svcn, evcn,
vcn ? *vcn : svcn, Add2Ptr(attr, run_off),
asize - run_off);
Expand Down Expand Up @@ -1232,6 +1236,10 @@ int attr_load_runs_vcn(struct ntfs_inode *ni, enum ATTR_TYPE type,
}

ro = le16_to_cpu(attr->nres.run_off);

if (ro > le32_to_cpu(attr->size))
return -EINVAL;

err = run_unpack_ex(run, ni->mi.sbi, ni->mi.rno, svcn, evcn, svcn,
Add2Ptr(attr, ro), le32_to_cpu(attr->size) - ro);
if (err < 0)
Expand Down Expand Up @@ -1901,6 +1909,11 @@ int attr_collapse_range(struct ntfs_inode *ni, u64 vbo, u64 bytes)
u16 le_sz;
u16 roff = le16_to_cpu(attr->nres.run_off);

if (roff > le32_to_cpu(attr->size)) {
err = -EINVAL;
goto out;
}

run_unpack_ex(RUN_DEALLOCATE, sbi, ni->mi.rno, svcn,
evcn1 - 1, svcn, Add2Ptr(attr, roff),
le32_to_cpu(attr->size) - roff);
Expand Down
5 changes: 5 additions & 0 deletions fs/ntfs3/attrlist.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,11 @@ int ntfs_load_attr_list(struct ntfs_inode *ni, struct ATTRIB *attr)

run_init(&ni->attr_list.run);

if (run_off > le32_to_cpu(attr->size)) {
err = -EINVAL;
goto out;
}

err = run_unpack_ex(&ni->attr_list.run, ni->mi.sbi, ni->mi.rno,
0, le64_to_cpu(attr->nres.evcn), 0,
Add2Ptr(attr, run_off),
Expand Down
14 changes: 14 additions & 0 deletions fs/ntfs3/frecord.c
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,12 @@ static int ni_repack(struct ntfs_inode *ni)
}

roff = le16_to_cpu(attr->nres.run_off);

if (roff > le32_to_cpu(attr->size)) {
err = -EINVAL;
break;
}

err = run_unpack(&run, sbi, ni->mi.rno, svcn, evcn, svcn,
Add2Ptr(attr, roff),
le32_to_cpu(attr->size) - roff);
Expand Down Expand Up @@ -1589,6 +1595,9 @@ int ni_delete_all(struct ntfs_inode *ni)
asize = le32_to_cpu(attr->size);
roff = le16_to_cpu(attr->nres.run_off);

if (roff > asize)
return -EINVAL;

/* run==1 means unpack and deallocate. */
run_unpack_ex(RUN_DEALLOCATE, sbi, ni->mi.rno, svcn, evcn, svcn,
Add2Ptr(attr, roff), asize - roff);
Expand Down Expand Up @@ -2291,6 +2300,11 @@ int ni_decompress_file(struct ntfs_inode *ni)
asize = le32_to_cpu(attr->size);
roff = le16_to_cpu(attr->nres.run_off);

if (roff > asize) {
err = -EINVAL;
goto out;
}

/*run==1 Means unpack and deallocate. */
run_unpack_ex(RUN_DEALLOCATE, sbi, ni->mi.rno, svcn, evcn, svcn,
Add2Ptr(attr, roff), asize - roff);
Expand Down
9 changes: 9 additions & 0 deletions fs/ntfs3/fslog.c
Original file line number Diff line number Diff line change
Expand Up @@ -2727,6 +2727,9 @@ static inline bool check_attr(const struct MFT_REC *rec,
return false;
}

if (run_off > asize)
return false;

if (run_unpack(NULL, sbi, 0, svcn, evcn, svcn,
Add2Ptr(attr, run_off), asize - run_off) < 0) {
return false;
Expand Down Expand Up @@ -4769,6 +4772,12 @@ int log_replay(struct ntfs_inode *ni, bool *initialized)
u16 roff = le16_to_cpu(attr->nres.run_off);
CLST svcn = le64_to_cpu(attr->nres.svcn);

if (roff > t32) {
kfree(oa->attr);
oa->attr = NULL;
goto fake_attr;
}

err = run_unpack(&oa->run0, sbi, inode->i_ino, svcn,
le64_to_cpu(attr->nres.evcn), svcn,
Add2Ptr(attr, roff), t32 - roff);
Expand Down
5 changes: 5 additions & 0 deletions fs/ntfs3/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,11 @@ static struct inode *ntfs_read_mft(struct inode *inode,
attr_unpack_run:
roff = le16_to_cpu(attr->nres.run_off);

if (roff > asize) {
err = -EINVAL;
goto out;
}

t64 = le64_to_cpu(attr->nres.svcn);
err = run_unpack_ex(run, sbi, ino, t64, le64_to_cpu(attr->nres.evcn),
t64, Add2Ptr(attr, roff), asize - roff);
Expand Down

0 comments on commit 6db6208

Please sign in to comment.