Skip to content

Commit 6516147

Browse files
joannekoongMiklos Szeredi
authored andcommitted
fuse: validate outarg offset and size in notify store/retrieve
Add validation checking for outarg offset and outarg size values passed in by the server. MAX_LFS_FILESIZE is the maximum file size supported. The fuse_notify_store_out and fuse_notify_retrieve_out structs take in a uint64_t offset. Add logic to ensure: * outarg.offset is less than MAX_LFS_FILESIZE * outarg.offset + outarg.size cannot exceed MAX_LFS_FILESIZE * potential uint64_t overflow is fixed when adding outarg.offset and outarg.size. Signed-off-by: Joanne Koong <joannelkoong@gmail.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
1 parent 59ba47b commit 6516147

1 file changed

Lines changed: 10 additions & 4 deletions

File tree

fs/fuse/dev.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1783,7 +1783,11 @@ static int fuse_notify_store(struct fuse_conn *fc, unsigned int size,
17831783
if (size - sizeof(outarg) != outarg.size)
17841784
return -EINVAL;
17851785

1786+
if (outarg.offset >= MAX_LFS_FILESIZE)
1787+
return -EINVAL;
1788+
17861789
nodeid = outarg.nodeid;
1790+
num = min(outarg.size, MAX_LFS_FILESIZE - outarg.offset);
17871791

17881792
down_read(&fc->killsb);
17891793

@@ -1796,13 +1800,12 @@ static int fuse_notify_store(struct fuse_conn *fc, unsigned int size,
17961800
index = outarg.offset >> PAGE_SHIFT;
17971801
offset = outarg.offset & ~PAGE_MASK;
17981802
file_size = i_size_read(inode);
1799-
end = outarg.offset + outarg.size;
1803+
end = outarg.offset + num;
18001804
if (end > file_size) {
18011805
file_size = end;
1802-
fuse_write_update_attr(inode, file_size, outarg.size);
1806+
fuse_write_update_attr(inode, file_size, num);
18031807
}
18041808

1805-
num = outarg.size;
18061809
while (num) {
18071810
struct folio *folio;
18081811
unsigned int folio_offset;
@@ -1882,7 +1885,7 @@ static int fuse_retrieve(struct fuse_mount *fm, struct inode *inode,
18821885
num = min(outarg->size, fc->max_write);
18831886
if (outarg->offset > file_size)
18841887
num = 0;
1885-
else if (outarg->offset + num > file_size)
1888+
else if (num > file_size - outarg->offset)
18861889
num = file_size - outarg->offset;
18871890

18881891
num_pages = (num + offset + PAGE_SIZE - 1) >> PAGE_SHIFT;
@@ -1964,6 +1967,9 @@ static int fuse_notify_retrieve(struct fuse_conn *fc, unsigned int size,
19641967

19651968
fuse_copy_finish(cs);
19661969

1970+
if (outarg.offset >= MAX_LFS_FILESIZE)
1971+
return -EINVAL;
1972+
19671973
down_read(&fc->killsb);
19681974
err = -ENOENT;
19691975
nodeid = outarg.nodeid;

0 commit comments

Comments
 (0)