Skip to content

Commit e2705dd

Browse files
fs/ntfs3: Fix warning in ni_fiemap
Use local runs_tree instead of cached. This way excludes rw_semaphore lock. Reported-by: syzbot+1c25748a40fe79b8a119@syzkaller.appspotmail.com Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
1 parent 8e929cb commit e2705dd

File tree

3 files changed

+21
-94
lines changed

3 files changed

+21
-94
lines changed

fs/ntfs3/attrib.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -977,7 +977,7 @@ int attr_data_get_block(struct ntfs_inode *ni, CLST vcn, CLST clen, CLST *lcn,
977977

978978
/* Check for compressed frame. */
979979
err = attr_is_frame_compressed(ni, attr_b, vcn >> NTFS_LZNT_CUNIT,
980-
&hint);
980+
&hint, run);
981981
if (err)
982982
goto out;
983983

@@ -1521,16 +1521,16 @@ int attr_wof_frame_info(struct ntfs_inode *ni, struct ATTRIB *attr,
15211521
* attr_is_frame_compressed - Used to detect compressed frame.
15221522
*
15231523
* attr - base (primary) attribute segment.
1524+
* run - run to use, usually == &ni->file.run.
15241525
* Only base segments contains valid 'attr->nres.c_unit'
15251526
*/
15261527
int attr_is_frame_compressed(struct ntfs_inode *ni, struct ATTRIB *attr,
1527-
CLST frame, CLST *clst_data)
1528+
CLST frame, CLST *clst_data, struct runs_tree *run)
15281529
{
15291530
int err;
15301531
u32 clst_frame;
15311532
CLST clen, lcn, vcn, alen, slen, vcn_next;
15321533
size_t idx;
1533-
struct runs_tree *run;
15341534

15351535
*clst_data = 0;
15361536

@@ -1542,7 +1542,6 @@ int attr_is_frame_compressed(struct ntfs_inode *ni, struct ATTRIB *attr,
15421542

15431543
clst_frame = 1u << attr->nres.c_unit;
15441544
vcn = frame * clst_frame;
1545-
run = &ni->file.run;
15461545

15471546
if (!run_lookup_entry(run, vcn, &lcn, &clen, &idx)) {
15481547
err = attr_load_runs_vcn(ni, attr->type, attr_name(attr),
@@ -1678,7 +1677,7 @@ int attr_allocate_frame(struct ntfs_inode *ni, CLST frame, size_t compr_size,
16781677
if (err)
16791678
goto out;
16801679

1681-
err = attr_is_frame_compressed(ni, attr_b, frame, &clst_data);
1680+
err = attr_is_frame_compressed(ni, attr_b, frame, &clst_data, run);
16821681
if (err)
16831682
goto out;
16841683

fs/ntfs3/frecord.c

Lines changed: 15 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -1900,46 +1900,6 @@ enum REPARSE_SIGN ni_parse_reparse(struct ntfs_inode *ni, struct ATTRIB *attr,
19001900
return REPARSE_LINK;
19011901
}
19021902

1903-
/*
1904-
* fiemap_fill_next_extent_k - a copy of fiemap_fill_next_extent
1905-
* but it uses 'fe_k' instead of fieinfo->fi_extents_start
1906-
*/
1907-
static int fiemap_fill_next_extent_k(struct fiemap_extent_info *fieinfo,
1908-
struct fiemap_extent *fe_k, u64 logical,
1909-
u64 phys, u64 len, u32 flags)
1910-
{
1911-
struct fiemap_extent extent;
1912-
1913-
/* only count the extents */
1914-
if (fieinfo->fi_extents_max == 0) {
1915-
fieinfo->fi_extents_mapped++;
1916-
return (flags & FIEMAP_EXTENT_LAST) ? 1 : 0;
1917-
}
1918-
1919-
if (fieinfo->fi_extents_mapped >= fieinfo->fi_extents_max)
1920-
return 1;
1921-
1922-
if (flags & FIEMAP_EXTENT_DELALLOC)
1923-
flags |= FIEMAP_EXTENT_UNKNOWN;
1924-
if (flags & FIEMAP_EXTENT_DATA_ENCRYPTED)
1925-
flags |= FIEMAP_EXTENT_ENCODED;
1926-
if (flags & (FIEMAP_EXTENT_DATA_TAIL | FIEMAP_EXTENT_DATA_INLINE))
1927-
flags |= FIEMAP_EXTENT_NOT_ALIGNED;
1928-
1929-
memset(&extent, 0, sizeof(extent));
1930-
extent.fe_logical = logical;
1931-
extent.fe_physical = phys;
1932-
extent.fe_length = len;
1933-
extent.fe_flags = flags;
1934-
1935-
memcpy(fe_k + fieinfo->fi_extents_mapped, &extent, sizeof(extent));
1936-
1937-
fieinfo->fi_extents_mapped++;
1938-
if (fieinfo->fi_extents_mapped == fieinfo->fi_extents_max)
1939-
return 1;
1940-
return (flags & FIEMAP_EXTENT_LAST) ? 1 : 0;
1941-
}
1942-
19431903
/*
19441904
* ni_fiemap - Helper for file_fiemap().
19451905
*
@@ -1950,11 +1910,9 @@ int ni_fiemap(struct ntfs_inode *ni, struct fiemap_extent_info *fieinfo,
19501910
__u64 vbo, __u64 len)
19511911
{
19521912
int err = 0;
1953-
struct fiemap_extent *fe_k = NULL;
19541913
struct ntfs_sb_info *sbi = ni->mi.sbi;
19551914
u8 cluster_bits = sbi->cluster_bits;
1956-
struct runs_tree *run;
1957-
struct rw_semaphore *run_lock;
1915+
struct runs_tree run;
19581916
struct ATTRIB *attr;
19591917
CLST vcn = vbo >> cluster_bits;
19601918
CLST lcn, clen;
@@ -1965,13 +1923,11 @@ int ni_fiemap(struct ntfs_inode *ni, struct fiemap_extent_info *fieinfo,
19651923
u32 flags;
19661924
bool ok;
19671925

1926+
run_init(&run);
19681927
if (S_ISDIR(ni->vfs_inode.i_mode)) {
1969-
run = &ni->dir.alloc_run;
19701928
attr = ni_find_attr(ni, NULL, NULL, ATTR_ALLOC, I30_NAME,
19711929
ARRAY_SIZE(I30_NAME), NULL, NULL);
1972-
run_lock = &ni->dir.run_lock;
19731930
} else {
1974-
run = &ni->file.run;
19751931
attr = ni_find_attr(ni, NULL, NULL, ATTR_DATA, NULL, 0, NULL,
19761932
NULL);
19771933
if (!attr) {
@@ -1986,7 +1942,6 @@ int ni_fiemap(struct ntfs_inode *ni, struct fiemap_extent_info *fieinfo,
19861942
"fiemap is not supported for compressed file (cp -r)");
19871943
goto out;
19881944
}
1989-
run_lock = &ni->file.run_lock;
19901945
}
19911946

19921947
if (!attr || !attr->non_res) {
@@ -1998,51 +1953,33 @@ int ni_fiemap(struct ntfs_inode *ni, struct fiemap_extent_info *fieinfo,
19981953
goto out;
19991954
}
20001955

2001-
/*
2002-
* To avoid lock problems replace pointer to user memory by pointer to kernel memory.
2003-
*/
2004-
fe_k = kmalloc_array(fieinfo->fi_extents_max,
2005-
sizeof(struct fiemap_extent),
2006-
GFP_NOFS | __GFP_ZERO);
2007-
if (!fe_k) {
2008-
err = -ENOMEM;
2009-
goto out;
2010-
}
2011-
20121956
end = vbo + len;
20131957
alloc_size = le64_to_cpu(attr->nres.alloc_size);
20141958
if (end > alloc_size)
20151959
end = alloc_size;
20161960

2017-
down_read(run_lock);
20181961

20191962
while (vbo < end) {
20201963
if (idx == -1) {
2021-
ok = run_lookup_entry(run, vcn, &lcn, &clen, &idx);
1964+
ok = run_lookup_entry(&run, vcn, &lcn, &clen, &idx);
20221965
} else {
20231966
CLST vcn_next = vcn;
20241967

2025-
ok = run_get_entry(run, ++idx, &vcn, &lcn, &clen) &&
1968+
ok = run_get_entry(&run, ++idx, &vcn, &lcn, &clen) &&
20261969
vcn == vcn_next;
20271970
if (!ok)
20281971
vcn = vcn_next;
20291972
}
20301973

20311974
if (!ok) {
2032-
up_read(run_lock);
2033-
down_write(run_lock);
2034-
20351975
err = attr_load_runs_vcn(ni, attr->type,
20361976
attr_name(attr),
2037-
attr->name_len, run, vcn);
2038-
2039-
up_write(run_lock);
2040-
down_read(run_lock);
1977+
attr->name_len, &run, vcn);
20411978

20421979
if (err)
20431980
break;
20441981

2045-
ok = run_lookup_entry(run, vcn, &lcn, &clen, &idx);
1982+
ok = run_lookup_entry(&run, vcn, &lcn, &clen, &idx);
20461983

20471984
if (!ok) {
20481985
err = -EINVAL;
@@ -2067,8 +2004,9 @@ int ni_fiemap(struct ntfs_inode *ni, struct fiemap_extent_info *fieinfo,
20672004
} else if (is_attr_compressed(attr)) {
20682005
CLST clst_data;
20692006

2070-
err = attr_is_frame_compressed(
2071-
ni, attr, vcn >> attr->nres.c_unit, &clst_data);
2007+
err = attr_is_frame_compressed(ni, attr,
2008+
vcn >> attr->nres.c_unit,
2009+
&clst_data, &run);
20722010
if (err)
20732011
break;
20742012
if (clst_data < NTFS_LZNT_CLUSTERS)
@@ -2097,8 +2035,8 @@ int ni_fiemap(struct ntfs_inode *ni, struct fiemap_extent_info *fieinfo,
20972035
if (vbo + dlen >= end)
20982036
flags |= FIEMAP_EXTENT_LAST;
20992037

2100-
err = fiemap_fill_next_extent_k(fieinfo, fe_k, vbo, lbo,
2101-
dlen, flags);
2038+
err = fiemap_fill_next_extent(fieinfo, vbo, lbo, dlen,
2039+
flags);
21022040

21032041
if (err < 0)
21042042
break;
@@ -2119,8 +2057,7 @@ int ni_fiemap(struct ntfs_inode *ni, struct fiemap_extent_info *fieinfo,
21192057
if (vbo + bytes >= end)
21202058
flags |= FIEMAP_EXTENT_LAST;
21212059

2122-
err = fiemap_fill_next_extent_k(fieinfo, fe_k, vbo, lbo, bytes,
2123-
flags);
2060+
err = fiemap_fill_next_extent(fieinfo, vbo, lbo, bytes, flags);
21242061
if (err < 0)
21252062
break;
21262063
if (err == 1) {
@@ -2131,19 +2068,8 @@ int ni_fiemap(struct ntfs_inode *ni, struct fiemap_extent_info *fieinfo,
21312068
vbo += bytes;
21322069
}
21332070

2134-
up_read(run_lock);
2135-
2136-
/*
2137-
* Copy to user memory out of lock
2138-
*/
2139-
if (copy_to_user(fieinfo->fi_extents_start, fe_k,
2140-
fieinfo->fi_extents_max *
2141-
sizeof(struct fiemap_extent))) {
2142-
err = -EFAULT;
2143-
}
2144-
21452071
out:
2146-
kfree(fe_k);
2072+
run_close(&run);
21472073
return err;
21482074
}
21492075

@@ -2672,7 +2598,8 @@ int ni_read_frame(struct ntfs_inode *ni, u64 frame_vbo, struct page **pages,
26722598
down_write(&ni->file.run_lock);
26732599
run_truncate_around(run, le64_to_cpu(attr->nres.svcn));
26742600
frame = frame_vbo >> (cluster_bits + NTFS_LZNT_CUNIT);
2675-
err = attr_is_frame_compressed(ni, attr, frame, &clst_data);
2601+
err = attr_is_frame_compressed(ni, attr, frame, &clst_data,
2602+
run);
26762603
up_write(&ni->file.run_lock);
26772604
if (err)
26782605
goto out1;

fs/ntfs3/ntfs_fs.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,8 @@ int attr_wof_frame_info(struct ntfs_inode *ni, struct ATTRIB *attr,
446446
struct runs_tree *run, u64 frame, u64 frames,
447447
u8 frame_bits, u32 *ondisk_size, u64 *vbo_data);
448448
int attr_is_frame_compressed(struct ntfs_inode *ni, struct ATTRIB *attr,
449-
CLST frame, CLST *clst_data);
449+
CLST frame, CLST *clst_data,
450+
struct runs_tree *run);
450451
int attr_allocate_frame(struct ntfs_inode *ni, CLST frame, size_t compr_size,
451452
u64 new_valid);
452453
int attr_collapse_range(struct ntfs_inode *ni, u64 vbo, u64 bytes);

0 commit comments

Comments
 (0)