Skip to content

Commit ff9726d

Browse files
committed
Merge tag 'ntfs-for-7.1-rc1-part2' of git://git.kernel.org/pub/scm/linux/kernel/git/linkinjeon/ntfs
Pull ntfs updates from Namjae Jeon: - Fix potential data leakage by zeroing the portion of the straddle block beyond initialized_size when reading non-resident attributes - Remove unnecessary zeroing in ntfs_punch_hole() for ranges beyond initialized_size, as they are already returned as zeros on read - Fix writable check in ntfs_file_mmap_prepare() to correctly handle shared mappings using VMA_SHARED_BIT | VMA_MAYWRITE_BIT - Use page allocation instead of kmemdup() for IOMAP_INLINE data to ensure page-aligned address and avoid BUG trap in iomap_inline_data_valid() caused by the page boundary check - Add a size check before memory allocation in ntfs_attr_readall() and reject overly large attributes - Remove unneeded noop_direct_IO from ntfs_aops as it is no longer required following the FMODE_CAN_ODIRECT flag - Fix seven static analysis warnings reported by Smatch * tag 'ntfs-for-7.1-rc1-part2' of git://git.kernel.org/pub/scm/linux/kernel/git/linkinjeon/ntfs: ntfs: use page allocation for resident attribute inline data ntfs: fix mmap_prepare writable check for shared mappings ntfs: fix potential 32-bit truncation in ntfs_write_cb() ntfs: fix uninitialized variable in ntfs_map_runlist_nolock ntfs: delete dead code ntfs: add missing error code in ntfs_mft_record_alloc() ntfs: fix uninitialized variables in ntfs_ea_set_wsl_inode() ntfs: fix uninitialized pointer in ntfs_write_mft_block ntfs: fix uninitialized variable in ntfs_write_simple_iomap_begin_non_resident ntfs: remove noop_direct_IO from address_space_operations ntfs: limit memory allocation in ntfs_attr_readall ntfs: not zero out range beyond init in punch_hole ntfs: zero out stale data in straddle block beyond initialized_size
2 parents bdcb864 + 36ee131 commit ff9726d

7 files changed

Lines changed: 114 additions & 42 deletions

File tree

fs/ntfs/aops.c

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,41 @@
1515
#include "debug.h"
1616
#include "iomap.h"
1717

18+
static void ntfs_iomap_read_end_io(struct bio *bio)
19+
{
20+
int error = blk_status_to_errno(bio->bi_status);
21+
struct folio_iter iter;
22+
23+
bio_for_each_folio_all(iter, bio) {
24+
struct folio *folio = iter.folio;
25+
struct ntfs_inode *ni = NTFS_I(folio->mapping->host);
26+
s64 init_size;
27+
loff_t pos = folio_pos(folio);
28+
29+
init_size = ni->initialized_size;
30+
if (pos + iter.offset < init_size &&
31+
pos + iter.offset + iter.length > init_size)
32+
folio_zero_segment(folio, offset_in_folio(folio, init_size),
33+
iter.offset + iter.length);
34+
35+
iomap_finish_folio_read(folio, iter.offset, iter.length, error);
36+
}
37+
bio_put(bio);
38+
}
39+
40+
static void ntfs_iomap_bio_submit_read(const struct iomap_iter *iter,
41+
struct iomap_read_folio_ctx *ctx)
42+
{
43+
struct bio *bio = ctx->read_ctx;
44+
bio->bi_end_io = ntfs_iomap_read_end_io;
45+
submit_bio(bio);
46+
}
47+
48+
static const struct iomap_read_ops ntfs_iomap_bio_read_ops = {
49+
.read_folio_range = iomap_bio_read_folio_range,
50+
.submit_read = ntfs_iomap_bio_submit_read,
51+
};
52+
1853
/*
1954
* ntfs_read_folio - Read data for a folio from the device
2055
* @file: open file to which the folio @folio belongs or NULL
@@ -35,6 +70,10 @@
3570
static int ntfs_read_folio(struct file *file, struct folio *folio)
3671
{
3772
struct ntfs_inode *ni = NTFS_I(folio->mapping->host);
73+
struct iomap_read_folio_ctx ctx = {
74+
.cur_folio = folio,
75+
.ops = &ntfs_iomap_bio_read_ops,
76+
};
3877

3978
/*
4079
* Only $DATA attributes can be encrypted and only unnamed $DATA
@@ -58,7 +97,7 @@ static int ntfs_read_folio(struct file *file, struct folio *folio)
5897
return ntfs_read_compressed_block(folio);
5998
}
6099

61-
iomap_bio_read_folio(folio, &ntfs_read_iomap_ops);
100+
iomap_read_folio(&ntfs_read_iomap_ops, &ctx, NULL);
62101
return 0;
63102
}
64103

@@ -188,14 +227,18 @@ static void ntfs_readahead(struct readahead_control *rac)
188227
struct address_space *mapping = rac->mapping;
189228
struct inode *inode = mapping->host;
190229
struct ntfs_inode *ni = NTFS_I(inode);
230+
struct iomap_read_folio_ctx ctx = {
231+
.ops = &ntfs_iomap_bio_read_ops,
232+
.rac = rac,
233+
};
191234

192235
/*
193236
* Resident files are not cached in the page cache,
194237
* and readahead is not implemented for compressed files.
195238
*/
196239
if (!NInoNonResident(ni) || NInoCompressed(ni))
197240
return;
198-
iomap_bio_readahead(rac, &ntfs_read_iomap_ops);
241+
iomap_readahead(&ntfs_read_iomap_ops, &ctx, NULL);
199242
}
200243

201244
static int ntfs_writepages(struct address_space *mapping,
@@ -238,7 +281,6 @@ const struct address_space_operations ntfs_aops = {
238281
.read_folio = ntfs_read_folio,
239282
.readahead = ntfs_readahead,
240283
.writepages = ntfs_writepages,
241-
.direct_IO = noop_direct_IO,
242284
.dirty_folio = iomap_dirty_folio,
243285
.bmap = ntfs_bmap,
244286
.migrate_folio = filemap_migrate_folio,

fs/ntfs/attrib.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,13 @@
2929

3030
__le16 AT_UNNAMED[] = { cpu_to_le16('\0') };
3131

32+
/*
33+
* Maximum size allowed for reading attributes by ntfs_attr_readall().
34+
* Extended attribute, reparse point are not expected to be larger than this size.
35+
*/
36+
37+
#define NTFS_ATTR_READALL_MAX_SIZE (64 * 1024)
38+
3239
/*
3340
* ntfs_map_runlist_nolock - map (a part of) a runlist of an ntfs inode
3441
* @ni: ntfs inode for which to map (part of) a runlist
@@ -85,7 +92,7 @@ int ntfs_map_runlist_nolock(struct ntfs_inode *ni, s64 vcn, struct ntfs_attr_sea
8592
struct runlist_element *rl;
8693
struct folio *put_this_folio = NULL;
8794
int err = 0;
88-
bool ctx_is_temporary = false, ctx_needs_reset;
95+
bool ctx_is_temporary = false, ctx_needs_reset = false;
8996
struct ntfs_attr_search_ctx old_ctx = { NULL, };
9097
size_t new_rl_count;
9198

@@ -5117,6 +5124,13 @@ void *ntfs_attr_readall(struct ntfs_inode *ni, const __le32 type,
51175124
}
51185125
bmp_ni = NTFS_I(bmp_vi);
51195126

5127+
if (bmp_ni->data_size > NTFS_ATTR_READALL_MAX_SIZE &&
5128+
(bmp_ni->type != AT_BITMAP ||
5129+
bmp_ni->data_size > ((ni->vol->nr_clusters + 7) >> 3))) {
5130+
ntfs_error(sb, "Invalid attribute data size");
5131+
goto out;
5132+
}
5133+
51205134
data = kvmalloc(bmp_ni->data_size, GFP_NOFS);
51215135
if (!data)
51225136
goto out;

fs/ntfs/compress.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1374,7 +1374,8 @@ static int ntfs_write_cb(struct ntfs_inode *ni, loff_t pos, struct page **pages,
13741374
bio_size = insz;
13751375
}
13761376

1377-
new_vcn = ntfs_bytes_to_cluster(vol, pos & ~(ni->itype.compressed.block_size - 1));
1377+
new_vcn = ntfs_bytes_to_cluster(vol,
1378+
pos & ~((loff_t)ni->itype.compressed.block_size - 1));
13781379
new_length = ntfs_bytes_to_cluster(vol, round_up(bio_size, vol->cluster_size));
13791380

13801381
err = ntfs_non_resident_attr_punch_hole(ni, new_vcn, ni->itype.compressed.block_clusters);

fs/ntfs/ea.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,10 @@ int ntfs_ea_set_wsl_inode(struct inode *inode, dev_t rdev, __le16 *ea_size,
406406
unsigned int flags)
407407
{
408408
__le32 v;
409-
int err;
409+
int err = 0;
410+
411+
if (ea_size)
412+
*ea_size = 0;
410413

411414
if (flags & NTFS_EA_UID) {
412415
/* Store uid to lxuid EA */

fs/ntfs/file.c

Lines changed: 25 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -267,15 +267,6 @@ static int ntfs_setattr_size(struct inode *vi, struct iattr *attr)
267267
return err;
268268

269269
inode_dio_wait(vi);
270-
/* Serialize against page faults */
271-
if (NInoNonResident(NTFS_I(vi)) && attr->ia_size < old_size) {
272-
err = iomap_truncate_page(vi, attr->ia_size, NULL,
273-
&ntfs_read_iomap_ops,
274-
&ntfs_iomap_folio_ops, NULL);
275-
if (err)
276-
return err;
277-
}
278-
279270
truncate_setsize(vi, attr->ia_size);
280271
err = ntfs_truncate_vfs(vi, attr->ia_size, old_size);
281272
if (err) {
@@ -534,10 +525,9 @@ static ssize_t ntfs_dio_write_iter(struct kiocb *iocb, struct iov_iter *from)
534525
ret = -EIO;
535526
goto out;
536527
}
537-
if (!ret2)
538-
invalidate_mapping_pages(iocb->ki_filp->f_mapping,
539-
offset >> PAGE_SHIFT,
540-
end >> PAGE_SHIFT);
528+
invalidate_mapping_pages(iocb->ki_filp->f_mapping,
529+
offset >> PAGE_SHIFT,
530+
end >> PAGE_SHIFT);
541531
}
542532

543533
out:
@@ -654,7 +644,7 @@ static int ntfs_file_mmap_prepare(struct vm_area_desc *desc)
654644
if (NInoCompressed(NTFS_I(inode)))
655645
return -EOPNOTSUPP;
656646

657-
if (vma_desc_test(desc, VMA_WRITE_BIT)) {
647+
if (vma_desc_test_all(desc, VMA_SHARED_BIT, VMA_MAYWRITE_BIT)) {
658648
struct inode *inode = file_inode(file);
659649
loff_t from, to;
660650
int err;
@@ -885,14 +875,19 @@ static int ntfs_punch_hole(struct ntfs_inode *ni, int mode, loff_t offset,
885875
end_vcn = ntfs_bytes_to_cluster(vol, end_offset - 1) + 1;
886876

887877
if (offset & vol->cluster_size_mask) {
888-
loff_t to;
889-
890-
to = min_t(loff_t, ntfs_cluster_to_bytes(vol, start_vcn + 1),
891-
end_offset);
892-
err = iomap_zero_range(vi, offset, to - offset, NULL,
893-
&ntfs_seek_iomap_ops,
894-
&ntfs_iomap_folio_ops, NULL);
895-
if (err < 0 || (end_vcn - start_vcn) == 1)
878+
if (offset < ni->initialized_size) {
879+
loff_t to;
880+
881+
to = min_t(loff_t,
882+
ntfs_cluster_to_bytes(vol, start_vcn + 1),
883+
end_offset);
884+
err = iomap_zero_range(vi, offset, to - offset,
885+
NULL, &ntfs_seek_iomap_ops,
886+
&ntfs_iomap_folio_ops, NULL);
887+
if (err < 0)
888+
goto out;
889+
}
890+
if (end_vcn - start_vcn == 1)
896891
goto out;
897892
start_vcn++;
898893
}
@@ -901,10 +896,14 @@ static int ntfs_punch_hole(struct ntfs_inode *ni, int mode, loff_t offset,
901896
loff_t from;
902897

903898
from = ntfs_cluster_to_bytes(vol, end_vcn - 1);
904-
err = iomap_zero_range(vi, from, end_offset - from, NULL,
905-
&ntfs_seek_iomap_ops,
906-
&ntfs_iomap_folio_ops, NULL);
907-
if (err < 0 || (end_vcn - start_vcn) == 1)
899+
if (from < ni->initialized_size) {
900+
err = iomap_zero_range(vi, from, end_offset - from,
901+
NULL, &ntfs_seek_iomap_ops,
902+
&ntfs_iomap_folio_ops, NULL);
903+
if (err < 0)
904+
goto out;
905+
}
906+
if (end_vcn - start_vcn == 1)
908907
goto out;
909908
end_vcn--;
910909
}

fs/ntfs/iomap.c

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ static int ntfs_read_iomap_begin_resident(struct inode *inode, loff_t offset, lo
8989
u32 attr_len;
9090
int err = 0;
9191
char *kattr;
92+
struct page *ipage;
9293

9394
if (NInoAttr(ni))
9495
base_ni = ni->ext.base_ntfs_ino;
@@ -129,15 +130,18 @@ static int ntfs_read_iomap_begin_resident(struct inode *inode, loff_t offset, lo
129130

130131
kattr = (u8 *)ctx->attr + le16_to_cpu(ctx->attr->data.resident.value_offset);
131132

132-
iomap->inline_data = kmemdup(kattr, attr_len, GFP_KERNEL);
133-
if (!iomap->inline_data) {
133+
ipage = alloc_page(GFP_NOFS | __GFP_ZERO);
134+
if (!ipage) {
134135
err = -ENOMEM;
135136
goto out;
136137
}
137138

139+
memcpy(page_address(ipage), kattr, attr_len);
138140
iomap->type = IOMAP_INLINE;
141+
iomap->inline_data = page_address(ipage);
139142
iomap->offset = 0;
140143
iomap->length = attr_len;
144+
iomap->private = ipage;
141145

142146
out:
143147
if (ctx)
@@ -285,8 +289,11 @@ static int ntfs_read_iomap_begin(struct inode *inode, loff_t offset, loff_t leng
285289
static int ntfs_read_iomap_end(struct inode *inode, loff_t pos, loff_t length,
286290
ssize_t written, unsigned int flags, struct iomap *iomap)
287291
{
288-
if (iomap->type == IOMAP_INLINE)
289-
kfree(iomap->inline_data);
292+
if (iomap->type == IOMAP_INLINE) {
293+
struct page *ipage = iomap->private;
294+
295+
put_page(ipage);
296+
}
290297

291298
return written;
292299
}
@@ -384,7 +391,7 @@ static int ntfs_write_simple_iomap_begin_non_resident(struct inode *inode, loff_
384391
loff_t vcn_ofs, rl_length;
385392
struct runlist_element *rl, *rlc;
386393
bool is_retry = false;
387-
int err;
394+
int err = 0;
388395
s64 vcn, lcn;
389396
s64 max_clu_count =
390397
ntfs_bytes_to_cluster(vol, round_up(length, vol->cluster_size));
@@ -652,6 +659,7 @@ static int ntfs_write_iomap_begin_resident(struct inode *inode, loff_t offset,
652659
u32 attr_len;
653660
int err = 0;
654661
char *kattr;
662+
struct page *ipage;
655663

656664
ctx = ntfs_attr_get_search_ctx(ni, NULL);
657665
if (!ctx) {
@@ -672,16 +680,19 @@ static int ntfs_write_iomap_begin_resident(struct inode *inode, loff_t offset,
672680
attr_len = le32_to_cpu(a->data.resident.value_length);
673681
kattr = (u8 *)a + le16_to_cpu(a->data.resident.value_offset);
674682

675-
iomap->inline_data = kmemdup(kattr, attr_len, GFP_KERNEL);
676-
if (!iomap->inline_data) {
683+
ipage = alloc_page(GFP_NOFS | __GFP_ZERO);
684+
if (!ipage) {
677685
err = -ENOMEM;
678686
goto out;
679687
}
680688

689+
memcpy(page_address(ipage), kattr, attr_len);
681690
iomap->type = IOMAP_INLINE;
691+
iomap->inline_data = page_address(ipage);
682692
iomap->offset = 0;
683693
/* iomap requires there is only one INLINE_DATA extent */
684694
iomap->length = attr_len;
695+
iomap->private = ipage;
685696

686697
out:
687698
if (ctx)
@@ -771,6 +782,7 @@ static int ntfs_write_iomap_end_resident(struct inode *inode, loff_t pos,
771782
u32 attr_len;
772783
int err;
773784
char *kattr;
785+
struct page *ipage = iomap->private;
774786

775787
mutex_lock(&ni->mrec_lock);
776788
ctx = ntfs_attr_get_search_ctx(ni, NULL);
@@ -799,7 +811,7 @@ static int ntfs_write_iomap_end_resident(struct inode *inode, loff_t pos,
799811
mark_mft_record_dirty(ctx->ntfs_ino);
800812
err_out:
801813
ntfs_attr_put_search_ctx(ctx);
802-
kfree(iomap->inline_data);
814+
put_page(ipage);
803815
mutex_unlock(&ni->mrec_lock);
804816
return written;
805817

fs/ntfs/mft.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2503,6 +2503,7 @@ int ntfs_mft_record_alloc(struct ntfs_volume *vol, const int mode,
25032503
folio_unlock(folio);
25042504
kunmap_local(m);
25052505
folio_put(folio);
2506+
err = -ENOMEM;
25062507
goto undo_mftbmp_alloc;
25072508
}
25082509

@@ -2714,7 +2715,7 @@ static int ntfs_write_mft_block(struct folio *folio, struct writeback_control *w
27142715
s64 vcn = ntfs_pidx_to_cluster(vol, folio->index);
27152716
s64 end_vcn = ntfs_bytes_to_cluster(vol, ni->allocated_size);
27162717
unsigned int folio_sz;
2717-
struct runlist_element *rl;
2718+
struct runlist_element *rl = NULL;
27182719
loff_t i_size = i_size_read(vi);
27192720

27202721
ntfs_debug("Entering for inode 0x%llx, attribute type 0x%x, folio index 0x%lx.",
@@ -2820,7 +2821,7 @@ static int ntfs_write_mft_block(struct folio *folio, struct writeback_control *w
28202821

28212822
if (vol->cluster_size == NTFS_BLOCK_SIZE &&
28222823
(mft_record_off ||
2823-
rl->length - (vcn_off - rl->vcn) == 1 ||
2824+
(rl && rl->length - (vcn_off - rl->vcn) == 1) ||
28242825
mft_ofs + NTFS_BLOCK_SIZE >= PAGE_SIZE))
28252826
folio_sz = NTFS_BLOCK_SIZE;
28262827
else

0 commit comments

Comments
 (0)