Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8687a3e2 authored by Chengguang Xu's avatar Chengguang Xu Committed by Ilya Dryomov
Browse files

ceph: add additional offset check in ceph_write_iter()



If the offset is larger or equal to both real file size and
max file size, then return -EFBIG.

Signed-off-by: default avatarChengguang Xu <cgxu519@gmx.com>
Reviewed-by: default avatar"Yan, Zheng" <zyan@redhat.com>
Signed-off-by: default avatarIlya Dryomov <idryomov@gmail.com>
parent 0671e996
Loading
Loading
Loading
Loading
+11 −4
Original line number Original line Diff line number Diff line
@@ -1384,12 +1384,12 @@ static ssize_t ceph_write_iter(struct kiocb *iocb, struct iov_iter *from)
	struct ceph_file_info *fi = file->private_data;
	struct ceph_file_info *fi = file->private_data;
	struct inode *inode = file_inode(file);
	struct inode *inode = file_inode(file);
	struct ceph_inode_info *ci = ceph_inode(inode);
	struct ceph_inode_info *ci = ceph_inode(inode);
	struct ceph_osd_client *osdc =
	struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
		&ceph_sb_to_client(inode->i_sb)->client->osdc;
	struct ceph_cap_flush *prealloc_cf;
	struct ceph_cap_flush *prealloc_cf;
	ssize_t count, written = 0;
	ssize_t count, written = 0;
	int err, want, got;
	int err, want, got;
	loff_t pos;
	loff_t pos;
	loff_t limit = max(i_size_read(inode), fsc->max_file_size);


	if (ceph_snap(inode) != CEPH_NOSNAP)
	if (ceph_snap(inode) != CEPH_NOSNAP)
		return -EROFS;
		return -EROFS;
@@ -1415,6 +1415,13 @@ static ssize_t ceph_write_iter(struct kiocb *iocb, struct iov_iter *from)
		goto out;
		goto out;


	pos = iocb->ki_pos;
	pos = iocb->ki_pos;
	if (unlikely(pos >= limit)) {
		err = -EFBIG;
		goto out;
	} else {
		iov_iter_truncate(from, limit - pos);
	}

	count = iov_iter_count(from);
	count = iov_iter_count(from);
	if (ceph_quota_is_max_bytes_exceeded(inode, pos + count)) {
	if (ceph_quota_is_max_bytes_exceeded(inode, pos + count)) {
		err = -EDQUOT;
		err = -EDQUOT;
@@ -1436,7 +1443,7 @@ static ssize_t ceph_write_iter(struct kiocb *iocb, struct iov_iter *from)
	}
	}


	/* FIXME: not complete since it doesn't account for being at quota */
	/* FIXME: not complete since it doesn't account for being at quota */
	if (ceph_osdmap_flag(osdc, CEPH_OSDMAP_FULL)) {
	if (ceph_osdmap_flag(&fsc->client->osdc, CEPH_OSDMAP_FULL)) {
		err = -ENOSPC;
		err = -ENOSPC;
		goto out;
		goto out;
	}
	}
@@ -1526,7 +1533,7 @@ static ssize_t ceph_write_iter(struct kiocb *iocb, struct iov_iter *from)
	}
	}


	if (written >= 0) {
	if (written >= 0) {
		if (ceph_osdmap_flag(osdc, CEPH_OSDMAP_NEARFULL))
		if (ceph_osdmap_flag(&fsc->client->osdc, CEPH_OSDMAP_NEARFULL))
			iocb->ki_flags |= IOCB_DSYNC;
			iocb->ki_flags |= IOCB_DSYNC;
		written = generic_write_sync(iocb, written);
		written = generic_write_sync(iocb, written);
	}
	}