Skip to content

Commit 5fc982f

Browse files
fs/ntfs3: Fix case when unmarked clusters intersect with zone
Reported-by: syzbot+7f3761b790fa41d0f3d5@syzkaller.appspotmail.com Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
1 parent e2705dd commit 5fc982f

File tree

1 file changed

+30
-10
lines changed

1 file changed

+30
-10
lines changed

fs/ntfs3/run.c

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1055,8 +1055,8 @@ int run_unpack_ex(struct runs_tree *run, struct ntfs_sb_info *sbi, CLST ino,
10551055
{
10561056
int ret, err;
10571057
CLST next_vcn, lcn, len;
1058-
size_t index;
1059-
bool ok;
1058+
size_t index, done;
1059+
bool ok, zone;
10601060
struct wnd_bitmap *wnd;
10611061

10621062
ret = run_unpack(run, sbi, ino, svcn, evcn, vcn, run_buf, run_buf_size);
@@ -1087,23 +1087,43 @@ int run_unpack_ex(struct runs_tree *run, struct ntfs_sb_info *sbi, CLST ino,
10871087
continue;
10881088

10891089
down_read_nested(&wnd->rw_lock, BITMAP_MUTEX_CLUSTERS);
1090+
zone = max(wnd->zone_bit, lcn) < min(wnd->zone_end, lcn + len);
10901091
/* Check for free blocks. */
1091-
ok = wnd_is_used(wnd, lcn, len);
1092+
ok = !zone && wnd_is_used(wnd, lcn, len);
10921093
up_read(&wnd->rw_lock);
10931094
if (ok)
10941095
continue;
10951096

10961097
/* Looks like volume is corrupted. */
10971098
ntfs_set_state(sbi, NTFS_DIRTY_ERROR);
10981099

1099-
if (down_write_trylock(&wnd->rw_lock)) {
1100-
/* Mark all zero bits as used in range [lcn, lcn+len). */
1101-
size_t done;
1102-
err = wnd_set_used_safe(wnd, lcn, len, &done);
1103-
up_write(&wnd->rw_lock);
1104-
if (err)
1105-
return err;
1100+
if (!down_write_trylock(&wnd->rw_lock))
1101+
continue;
1102+
1103+
if (zone) {
1104+
/*
1105+
* Range [lcn, lcn + len) intersects with zone.
1106+
* To avoid complex with zone just turn it off.
1107+
*/
1108+
wnd_zone_set(wnd, 0, 0);
1109+
}
1110+
1111+
/* Mark all zero bits as used in range [lcn, lcn+len). */
1112+
err = wnd_set_used_safe(wnd, lcn, len, &done);
1113+
if (zone) {
1114+
/* Restore zone. Lock mft run. */
1115+
struct rw_semaphore *lock;
1116+
lock = is_mounted(sbi) ? &sbi->mft.ni->file.run_lock :
1117+
NULL;
1118+
if (lock)
1119+
down_read(lock);
1120+
ntfs_refresh_zone(sbi);
1121+
if (lock)
1122+
up_read(lock);
11061123
}
1124+
up_write(&wnd->rw_lock);
1125+
if (err)
1126+
return err;
11071127
}
11081128

11091129
return ret;

0 commit comments

Comments
 (0)