Commit 0cc5543f authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
parents 4b06c990 8b12017c
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -2664,8 +2664,9 @@ int attr_set_compress(struct ntfs_inode *ni, bool compr)
		attr->nres.run_off = cpu_to_le16(run_off);
	}

	/* Update data attribute flags. */
	/* Update attribute flags. */
	if (compr) {
		attr->flags &= ~ATTR_FLAG_SPARSED;
		attr->flags |= ATTR_FLAG_COMPRESSED;
		attr->nres.c_unit = NTFS_LZNT_CUNIT;
	} else {
+31 −11
Original line number Diff line number Diff line
@@ -101,8 +101,26 @@ int ntfs_fileattr_set(struct mnt_idmap *idmap, struct dentry *dentry,
	/* Allowed to change compression for empty files and for directories only. */
	if (!is_dedup(ni) && !is_encrypted(ni) &&
	    (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))) {
		int err = 0;
		struct address_space *mapping = inode->i_mapping;

		/* write out all data and wait. */
		filemap_invalidate_lock(mapping);
		err = filemap_write_and_wait(mapping);

		if (err >= 0) {
			/* Change compress state. */
		int err = ni_set_compress(inode, flags & FS_COMPR_FL);
			bool compr = flags & FS_COMPR_FL;
			err = ni_set_compress(inode, compr);

			/* For files change a_ops too. */
			if (!err)
				mapping->a_ops = compr ? &ntfs_aops_cmpr :
							 &ntfs_aops;
		}

		filemap_invalidate_unlock(mapping);

		if (err)
			return err;
	}
@@ -412,6 +430,7 @@ static int ntfs_extend(struct inode *inode, loff_t pos, size_t count,
	}

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

	err = check_write_restriction(inode);
	if (err)
		return err;

	if (is_compressed(ni) && (iocb->ki_flags & IOCB_DIRECT)) {
		ntfs_inode_warn(inode, "direct i/o + compressed not supported");
		return -EOPNOTSUPP;
	}

	if (!inode_trylock(inode)) {
		if (iocb->ki_flags & IOCB_NOWAIT)
			return -EAGAIN;
		inode_lock(inode);
	}

	ret = check_write_restriction(inode);
	if (ret)
		goto out;

	if (is_compressed(ni) && (iocb->ki_flags & IOCB_DIRECT)) {
		ntfs_inode_warn(inode, "direct i/o + compressed not supported");
		ret = -EOPNOTSUPP;
		goto out;
	}

	ret = generic_write_checks(iocb, from);
	if (ret <= 0)
		goto out;
+4 −59
Original line number Diff line number Diff line
@@ -280,63 +280,6 @@ struct ATTRIB *ni_enum_attr_ex(struct ntfs_inode *ni, struct ATTRIB *attr,
	return rec_find_attr_le(ni, mi2, le2);
}

/*
 * ni_load_attr - Load attribute that contains given VCN.
 */
struct ATTRIB *ni_load_attr(struct ntfs_inode *ni, enum ATTR_TYPE type,
			    const __le16 *name, u8 name_len, CLST vcn,
			    struct mft_inode **pmi)
{
	struct ATTR_LIST_ENTRY *le;
	struct ATTRIB *attr;
	struct mft_inode *mi;
	struct ATTR_LIST_ENTRY *next;

	if (!ni->attr_list.size) {
		if (pmi)
			*pmi = &ni->mi;
		return mi_find_attr(ni, &ni->mi, NULL, type, name, name_len,
				    NULL);
	}

	le = al_find_ex(ni, NULL, type, name, name_len, NULL);
	if (!le)
		return NULL;

	/*
	 * Unfortunately ATTR_LIST_ENTRY contains only start VCN.
	 * So to find the ATTRIB segment that contains 'vcn' we should
	 * enumerate some entries.
	 */
	if (vcn) {
		for (;; le = next) {
			next = al_find_ex(ni, le, type, name, name_len, NULL);
			if (!next || le64_to_cpu(next->vcn) > vcn)
				break;
		}
	}

	if (ni_load_mi(ni, le, &mi))
		return NULL;

	if (pmi)
		*pmi = mi;

	attr = mi_find_attr(ni, mi, NULL, type, name, name_len, &le->id);
	if (!attr)
		return NULL;

	if (!attr->non_res)
		return attr;

	if (le64_to_cpu(attr->nres.svcn) <= vcn &&
	    vcn <= le64_to_cpu(attr->nres.evcn))
		return attr;

	_ntfs_bad_inode(&ni->vfs_inode);
	return NULL;
}

/*
 * ni_load_all_mi - Load all subrecords.
 */
@@ -3434,10 +3377,12 @@ int ni_set_compress(struct inode *inode, bool compr)
	}

	ni->std_fa = std->fa;
	if (compr)
	if (compr) {
		std->fa &= ~FILE_ATTRIBUTE_SPARSE_FILE;
		std->fa |= FILE_ATTRIBUTE_COMPRESSED;
	else
	} else {
		std->fa &= ~FILE_ATTRIBUTE_COMPRESSED;
	}

	if (ni->std_fa != std->fa) {
		ni->std_fa = std->fa;
+0 −28
Original line number Diff line number Diff line
@@ -1035,34 +1035,6 @@ struct buffer_head *ntfs_bread(struct super_block *sb, sector_t block)
	return NULL;
}

int ntfs_sb_read(struct super_block *sb, u64 lbo, size_t bytes, void *buffer)
{
	struct block_device *bdev = sb->s_bdev;
	u32 blocksize = sb->s_blocksize;
	u64 block = lbo >> sb->s_blocksize_bits;
	u32 off = lbo & (blocksize - 1);
	u32 op = blocksize - off;

	for (; bytes; block += 1, off = 0, op = blocksize) {
		struct buffer_head *bh = __bread(bdev, block, blocksize);

		if (!bh)
			return -EIO;

		if (op > bytes)
			op = bytes;

		memcpy(buffer, bh->b_data + off, op);

		put_bh(bh);

		bytes -= op;
		buffer = Add2Ptr(buffer, op);
	}

	return 0;
}

int ntfs_sb_write(struct super_block *sb, u64 lbo, size_t bytes,
		  const void *buf, int wait)
{
+2 −2
Original line number Diff line number Diff line
@@ -618,7 +618,7 @@ static bool index_hdr_check(const struct INDEX_HDR *hdr, u32 bytes)
	u32 off = le32_to_cpu(hdr->de_off);

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

	if (off + sizeof(struct NTFS_DE) > end)
	if (size_add(off, sizeof(struct NTFS_DE)) > end)
		return NULL;

	e = Add2Ptr(hdr, off);
Loading