From: Chengguang Xu <cgxu519@gmx.com>
Date: Thu, 19 Jul 2018 22:15:26 +0800
Subject: ceph: add additional offset check in ceph_write_iter()
Git-commit: 8687a3e2c7a026c173ac2e0d65d869c98c154a3a
Patch-mainline: v4.19-rc1
References: FATE#324714
If the offset is larger or equal to both real file size and
max file size, then return -EFBIG.
Signed-off-by: Chengguang Xu <cgxu519@gmx.com>
Reviewed-by: "Yan, Zheng" <zyan@redhat.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Acked-by: Luis Henriques <lhenriques@suse.com>
---
fs/ceph/file.c | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
--- a/fs/ceph/file.c
+++ b/fs/ceph/file.c
@@ -1344,12 +1344,12 @@ static ssize_t ceph_write_iter(struct ki
struct ceph_file_info *fi = file->private_data;
struct inode *inode = file_inode(file);
struct ceph_inode_info *ci = ceph_inode(inode);
- struct ceph_osd_client *osdc =
- &ceph_sb_to_client(inode->i_sb)->client->osdc;
+ struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
struct ceph_cap_flush *prealloc_cf;
ssize_t count, written = 0;
int err, want, got;
loff_t pos;
+ loff_t limit = max(i_size_read(inode), fsc->max_file_size);
if (ceph_snap(inode) != CEPH_NOSNAP)
return -EROFS;
@@ -1375,6 +1375,13 @@ retry_snap:
goto out;
pos = iocb->ki_pos;
+ if (unlikely(pos >= limit)) {
+ err = -EFBIG;
+ goto out;
+ } else {
+ iov_iter_truncate(from, limit - pos);
+ }
+
count = iov_iter_count(from);
if (ceph_quota_is_max_bytes_exceeded(inode, pos + count)) {
err = -EDQUOT;
@@ -1396,7 +1403,7 @@ retry_snap:
}
/* 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;
goto out;
}
@@ -1486,7 +1493,7 @@ retry_snap:
}
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;
written = generic_write_sync(iocb, written);
}