mirror of
https://github.com/opnsense/src.git
synced 2026-05-20 08:56:47 -04:00
fusefs: fix an uninitialized memory access in fuse_vnop_deallocate
If the FUSE_GETATTR issued to query a file's size during fuse_vnop_deallocate failed for any reason, then fuse_vnop_deallocate would attempt to destroy an uninitialized fuse_dispatcher struct, with a crash the likely result. This bug only affects FUSE file systems that implement FUSE_FALLOCATE, and is unlikely to be seen on those that don't disable attribute caching. Reported by: Coverity Scan CID: 1505308 (cherry picked from commit f93a50d69df2e996ff1d4f793d0dcb9de655ebdc)
This commit is contained in:
parent
f37dc94abc
commit
cf2ed0edae
2 changed files with 52 additions and 1 deletions
|
|
@ -3082,8 +3082,8 @@ fuse_vnop_deallocate(struct vop_deallocate_args *ap)
|
|||
false);
|
||||
}
|
||||
|
||||
out:
|
||||
fdisp_destroy(&fdi);
|
||||
out:
|
||||
if (closefufh)
|
||||
fuse_filehandle_close(vp, fufh, curthread, cred);
|
||||
|
||||
|
|
|
|||
|
|
@ -310,6 +310,57 @@ TEST_F(Fspacectl, erofs)
|
|||
leak(fd);
|
||||
}
|
||||
|
||||
/*
|
||||
* If FUSE_GETATTR fails when determining the size of the file, fspacectl
|
||||
* should fail gracefully. This failure mode is easiest to trigger when
|
||||
* attribute caching is disabled.
|
||||
*/
|
||||
TEST_F(Fspacectl, getattr_fails)
|
||||
{
|
||||
const char FULLPATH[] = "mountpoint/some_file.txt";
|
||||
const char RELPATH[] = "some_file.txt";
|
||||
Sequence seq;
|
||||
struct spacectl_range rqsr;
|
||||
const uint64_t ino = 42;
|
||||
const uint64_t fsize = 2000;
|
||||
int fd;
|
||||
|
||||
expect_lookup(RELPATH, ino, S_IFREG | 0644, fsize, 1, 0);
|
||||
expect_open(ino, 0, 1);
|
||||
EXPECT_CALL(*m_mock, process(
|
||||
ResultOf([](auto in) {
|
||||
return (in.header.opcode == FUSE_GETATTR &&
|
||||
in.header.nodeid == ino);
|
||||
}, Eq(true)),
|
||||
_)
|
||||
).Times(1)
|
||||
.InSequence(seq)
|
||||
.WillOnce(Invoke(ReturnImmediate([](auto i __unused, auto& out) {
|
||||
SET_OUT_HEADER_LEN(out, attr);
|
||||
out.body.attr.attr.ino = ino;
|
||||
out.body.attr.attr.mode = S_IFREG | 0644;
|
||||
out.body.attr.attr.size = fsize;
|
||||
out.body.attr.attr_valid = 0;
|
||||
})));
|
||||
EXPECT_CALL(*m_mock, process(
|
||||
ResultOf([](auto in) {
|
||||
return (in.header.opcode == FUSE_GETATTR &&
|
||||
in.header.nodeid == ino);
|
||||
}, Eq(true)),
|
||||
_)
|
||||
).InSequence(seq)
|
||||
.WillOnce(ReturnErrno(EIO));
|
||||
|
||||
fd = open(FULLPATH, O_RDWR);
|
||||
ASSERT_LE(0, fd) << strerror(errno);
|
||||
rqsr.r_offset = 500;
|
||||
rqsr.r_len = 1000;
|
||||
EXPECT_EQ(-1, fspacectl(fd, SPACECTL_DEALLOC, &rqsr, 0, NULL));
|
||||
EXPECT_EQ(EIO, errno);
|
||||
|
||||
leak(fd);
|
||||
}
|
||||
|
||||
TEST_F(Fspacectl, ok)
|
||||
{
|
||||
const char FULLPATH[] = "mountpoint/some_file.txt";
|
||||
|
|
|
|||
Loading…
Reference in a new issue