Skip to content

Commit 0cc5543

Browse files
committed
Pull ntfs3 updates from Konstantin Komarov: - Fix integer overflows on 32-bit systems and in hdr_first_de() - Fix 'proc_info_root' leak on NTFS initialization failure - Remove unused functions ni_load_attr, ntfs_sb_read, ntfs_flush_inodes - update inode->i_mapping->a_ops on compression state - ensure atomicity of write operations - refactor ntfs_{create/remove}_{procdir,proc_root}() * tag 'ntfs3_for_6.15' of https://github.com/Paragon-Software-Group/linux-ntfs3: fs/ntfs3: Remove unused ntfs_flush_inodes fs/ntfs3: Remove unused ntfs_sb_read fs/ntfs3: Remove unused ni_load_attr fs/ntfs3: Prevent integer overflow in hdr_first_de() fs/ntfs3: Fix a couple integer overflows on 32bit systems fs/ntfs3: Update inode->i_mapping->a_ops on compression state fs/ntfs3: Fix WARNING in ntfs_extend_initialized_size fs/ntfs3: Fix 'proc_info_root' leak when init ntfs failed fs/ntfs3: Factor out ntfs_{create/remove}_proc_root() fs/ntfs3: Factor out ntfs_{create/remove}_procdir() fs/ntfs3: Keep write operations atomic
2 parents 4b06c99 + 8b12017 commit 0cc5543

File tree

9 files changed

+96
-181
lines changed

9 files changed

+96
-181
lines changed

fs/ntfs3/attrib.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2664,8 +2664,9 @@ int attr_set_compress(struct ntfs_inode *ni, bool compr)
26642664
attr->nres.run_off = cpu_to_le16(run_off);
26652665
}
26662666

2667-
/* Update data attribute flags. */
2667+
/* Update attribute flags. */
26682668
if (compr) {
2669+
attr->flags &= ~ATTR_FLAG_SPARSED;
26692670
attr->flags |= ATTR_FLAG_COMPRESSED;
26702671
attr->nres.c_unit = NTFS_LZNT_CUNIT;
26712672
} else {

fs/ntfs3/file.c

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,26 @@ int ntfs_fileattr_set(struct mnt_idmap *idmap, struct dentry *dentry,
101101
/* Allowed to change compression for empty files and for directories only. */
102102
if (!is_dedup(ni) && !is_encrypted(ni) &&
103103
(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))) {
104-
/* Change compress state. */
105-
int err = ni_set_compress(inode, flags & FS_COMPR_FL);
104+
int err = 0;
105+
struct address_space *mapping = inode->i_mapping;
106+
107+
/* write out all data and wait. */
108+
filemap_invalidate_lock(mapping);
109+
err = filemap_write_and_wait(mapping);
110+
111+
if (err >= 0) {
112+
/* Change compress state. */
113+
bool compr = flags & FS_COMPR_FL;
114+
err = ni_set_compress(inode, compr);
115+
116+
/* For files change a_ops too. */
117+
if (!err)
118+
mapping->a_ops = compr ? &ntfs_aops_cmpr :
119+
&ntfs_aops;
120+
}
121+
122+
filemap_invalidate_unlock(mapping);
123+
106124
if (err)
107125
return err;
108126
}
@@ -412,6 +430,7 @@ static int ntfs_extend(struct inode *inode, loff_t pos, size_t count,
412430
}
413431

414432
if (extend_init && !is_compressed(ni)) {
433+
WARN_ON(ni->i_valid >= pos);
415434
err = ntfs_extend_initialized_size(file, ni, ni->i_valid, pos);
416435
if (err)
417436
goto out;
@@ -1228,21 +1247,22 @@ static ssize_t ntfs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
12281247
ssize_t ret;
12291248
int err;
12301249

1231-
err = check_write_restriction(inode);
1232-
if (err)
1233-
return err;
1234-
1235-
if (is_compressed(ni) && (iocb->ki_flags & IOCB_DIRECT)) {
1236-
ntfs_inode_warn(inode, "direct i/o + compressed not supported");
1237-
return -EOPNOTSUPP;
1238-
}
1239-
12401250
if (!inode_trylock(inode)) {
12411251
if (iocb->ki_flags & IOCB_NOWAIT)
12421252
return -EAGAIN;
12431253
inode_lock(inode);
12441254
}
12451255

1256+
ret = check_write_restriction(inode);
1257+
if (ret)
1258+
goto out;
1259+
1260+
if (is_compressed(ni) && (iocb->ki_flags & IOCB_DIRECT)) {
1261+
ntfs_inode_warn(inode, "direct i/o + compressed not supported");
1262+
ret = -EOPNOTSUPP;
1263+
goto out;
1264+
}
1265+
12461266
ret = generic_write_checks(iocb, from);
12471267
if (ret <= 0)
12481268
goto out;

fs/ntfs3/frecord.c

Lines changed: 4 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -280,63 +280,6 @@ struct ATTRIB *ni_enum_attr_ex(struct ntfs_inode *ni, struct ATTRIB *attr,
280280
return rec_find_attr_le(ni, mi2, le2);
281281
}
282282

283-
/*
284-
* ni_load_attr - Load attribute that contains given VCN.
285-
*/
286-
struct ATTRIB *ni_load_attr(struct ntfs_inode *ni, enum ATTR_TYPE type,
287-
const __le16 *name, u8 name_len, CLST vcn,
288-
struct mft_inode **pmi)
289-
{
290-
struct ATTR_LIST_ENTRY *le;
291-
struct ATTRIB *attr;
292-
struct mft_inode *mi;
293-
struct ATTR_LIST_ENTRY *next;
294-
295-
if (!ni->attr_list.size) {
296-
if (pmi)
297-
*pmi = &ni->mi;
298-
return mi_find_attr(ni, &ni->mi, NULL, type, name, name_len,
299-
NULL);
300-
}
301-
302-
le = al_find_ex(ni, NULL, type, name, name_len, NULL);
303-
if (!le)
304-
return NULL;
305-
306-
/*
307-
* Unfortunately ATTR_LIST_ENTRY contains only start VCN.
308-
* So to find the ATTRIB segment that contains 'vcn' we should
309-
* enumerate some entries.
310-
*/
311-
if (vcn) {
312-
for (;; le = next) {
313-
next = al_find_ex(ni, le, type, name, name_len, NULL);
314-
if (!next || le64_to_cpu(next->vcn) > vcn)
315-
break;
316-
}
317-
}
318-
319-
if (ni_load_mi(ni, le, &mi))
320-
return NULL;
321-
322-
if (pmi)
323-
*pmi = mi;
324-
325-
attr = mi_find_attr(ni, mi, NULL, type, name, name_len, &le->id);
326-
if (!attr)
327-
return NULL;
328-
329-
if (!attr->non_res)
330-
return attr;
331-
332-
if (le64_to_cpu(attr->nres.svcn) <= vcn &&
333-
vcn <= le64_to_cpu(attr->nres.evcn))
334-
return attr;
335-
336-
_ntfs_bad_inode(&ni->vfs_inode);
337-
return NULL;
338-
}
339-
340283
/*
341284
* ni_load_all_mi - Load all subrecords.
342285
*/
@@ -3434,10 +3377,12 @@ int ni_set_compress(struct inode *inode, bool compr)
34343377
}
34353378

34363379
ni->std_fa = std->fa;
3437-
if (compr)
3380+
if (compr) {
3381+
std->fa &= ~FILE_ATTRIBUTE_SPARSE_FILE;
34383382
std->fa |= FILE_ATTRIBUTE_COMPRESSED;
3439-
else
3383+
} else {
34403384
std->fa &= ~FILE_ATTRIBUTE_COMPRESSED;
3385+
}
34413386

34423387
if (ni->std_fa != std->fa) {
34433388
ni->std_fa = std->fa;

fs/ntfs3/fsntfs.c

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1035,34 +1035,6 @@ struct buffer_head *ntfs_bread(struct super_block *sb, sector_t block)
10351035
return NULL;
10361036
}
10371037

1038-
int ntfs_sb_read(struct super_block *sb, u64 lbo, size_t bytes, void *buffer)
1039-
{
1040-
struct block_device *bdev = sb->s_bdev;
1041-
u32 blocksize = sb->s_blocksize;
1042-
u64 block = lbo >> sb->s_blocksize_bits;
1043-
u32 off = lbo & (blocksize - 1);
1044-
u32 op = blocksize - off;
1045-
1046-
for (; bytes; block += 1, off = 0, op = blocksize) {
1047-
struct buffer_head *bh = __bread(bdev, block, blocksize);
1048-
1049-
if (!bh)
1050-
return -EIO;
1051-
1052-
if (op > bytes)
1053-
op = bytes;
1054-
1055-
memcpy(buffer, bh->b_data + off, op);
1056-
1057-
put_bh(bh);
1058-
1059-
bytes -= op;
1060-
buffer = Add2Ptr(buffer, op);
1061-
}
1062-
1063-
return 0;
1064-
}
1065-
10661038
int ntfs_sb_write(struct super_block *sb, u64 lbo, size_t bytes,
10671039
const void *buf, int wait)
10681040
{

fs/ntfs3/index.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -618,7 +618,7 @@ static bool index_hdr_check(const struct INDEX_HDR *hdr, u32 bytes)
618618
u32 off = le32_to_cpu(hdr->de_off);
619619

620620
if (!IS_ALIGNED(off, 8) || tot > bytes || end > tot ||
621-
off + sizeof(struct NTFS_DE) > end) {
621+
size_add(off, sizeof(struct NTFS_DE)) > end) {
622622
/* incorrect index buffer. */
623623
return false;
624624
}
@@ -736,7 +736,7 @@ static struct NTFS_DE *hdr_find_e(const struct ntfs_index *indx,
736736
if (end > total)
737737
return NULL;
738738

739-
if (off + sizeof(struct NTFS_DE) > end)
739+
if (size_add(off, sizeof(struct NTFS_DE)) > end)
740740
return NULL;
741741

742742
e = Add2Ptr(hdr, off);

fs/ntfs3/inode.c

Lines changed: 0 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1024,46 +1024,6 @@ int ntfs_sync_inode(struct inode *inode)
10241024
return _ni_write_inode(inode, 1);
10251025
}
10261026

1027-
/*
1028-
* writeback_inode - Helper function for ntfs_flush_inodes().
1029-
*
1030-
* This writes both the inode and the file data blocks, waiting
1031-
* for in flight data blocks before the start of the call. It
1032-
* does not wait for any io started during the call.
1033-
*/
1034-
static int writeback_inode(struct inode *inode)
1035-
{
1036-
int ret = sync_inode_metadata(inode, 0);
1037-
1038-
if (!ret)
1039-
ret = filemap_fdatawrite(inode->i_mapping);
1040-
return ret;
1041-
}
1042-
1043-
/*
1044-
* ntfs_flush_inodes
1045-
*
1046-
* Write data and metadata corresponding to i1 and i2. The io is
1047-
* started but we do not wait for any of it to finish.
1048-
*
1049-
* filemap_flush() is used for the block device, so if there is a dirty
1050-
* page for a block already in flight, we will not wait and start the
1051-
* io over again.
1052-
*/
1053-
int ntfs_flush_inodes(struct super_block *sb, struct inode *i1,
1054-
struct inode *i2)
1055-
{
1056-
int ret = 0;
1057-
1058-
if (i1)
1059-
ret = writeback_inode(i1);
1060-
if (!ret && i2)
1061-
ret = writeback_inode(i2);
1062-
if (!ret)
1063-
ret = filemap_flush(sb->s_bdev_file->f_mapping);
1064-
return ret;
1065-
}
1066-
10671027
/*
10681028
* Helper function to read file.
10691029
*/

fs/ntfs3/ntfs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -717,7 +717,7 @@ static inline struct NTFS_DE *hdr_first_de(const struct INDEX_HDR *hdr)
717717
struct NTFS_DE *e;
718718
u16 esize;
719719

720-
if (de_off >= used || de_off + sizeof(struct NTFS_DE) > used )
720+
if (de_off >= used || size_add(de_off, sizeof(struct NTFS_DE)) > used)
721721
return NULL;
722722

723723
e = Add2Ptr(hdr, de_off);

fs/ntfs3/ntfs_fs.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -530,9 +530,6 @@ struct ATTRIB *ni_find_attr(struct ntfs_inode *ni, struct ATTRIB *attr,
530530
struct ATTRIB *ni_enum_attr_ex(struct ntfs_inode *ni, struct ATTRIB *attr,
531531
struct ATTR_LIST_ENTRY **le,
532532
struct mft_inode **mi);
533-
struct ATTRIB *ni_load_attr(struct ntfs_inode *ni, enum ATTR_TYPE type,
534-
const __le16 *name, u8 name_len, CLST vcn,
535-
struct mft_inode **pmi);
536533
int ni_load_all_mi(struct ntfs_inode *ni);
537534
bool ni_add_subrecord(struct ntfs_inode *ni, CLST rno, struct mft_inode **mi);
538535
int ni_remove_attr(struct ntfs_inode *ni, enum ATTR_TYPE type,
@@ -619,7 +616,6 @@ enum NTFS_DIRTY_FLAGS {
619616
NTFS_DIRTY_ERROR = 2,
620617
};
621618
int ntfs_set_state(struct ntfs_sb_info *sbi, enum NTFS_DIRTY_FLAGS dirty);
622-
int ntfs_sb_read(struct super_block *sb, u64 lbo, size_t bytes, void *buffer);
623619
int ntfs_sb_write(struct super_block *sb, u64 lbo, size_t bytes,
624620
const void *buffer, int wait);
625621
int ntfs_sb_write_run(struct ntfs_sb_info *sbi, const struct runs_tree *run,
@@ -717,8 +713,6 @@ int ntfs_write_end(struct file *file, struct address_space *mapping, loff_t pos,
717713
u32 len, u32 copied, struct folio *folio, void *fsdata);
718714
int ntfs3_write_inode(struct inode *inode, struct writeback_control *wbc);
719715
int ntfs_sync_inode(struct inode *inode);
720-
int ntfs_flush_inodes(struct super_block *sb, struct inode *i1,
721-
struct inode *i2);
722716
int inode_read_data(struct inode *inode, void *data, size_t bytes);
723717
int ntfs_create_inode(struct mnt_idmap *idmap, struct inode *dir,
724718
struct dentry *dentry, const struct cpu_str *uni,

0 commit comments

Comments
 (0)