Page MenuHomeFreeBSD

D34931.diff
No OneTemporary

D34931.diff

diff --git a/sys/fs/fuse/fuse_device.c b/sys/fs/fuse/fuse_device.c
--- a/sys/fs/fuse/fuse_device.c
+++ b/sys/fs/fuse/fuse_device.c
@@ -518,8 +518,18 @@
"pass ticket to a callback");
/* Sanitize the linuxism of negative errnos */
ohead.error *= -1;
- memcpy(&tick->tk_aw_ohead, &ohead, sizeof(ohead));
- err = tick->tk_aw_handler(tick, uio);
+ if (ohead.error < 0 || ohead.error > ELAST) {
+ /* Illegal error code */
+ ohead.error = EIO;
+ memcpy(&tick->tk_aw_ohead, &ohead,
+ sizeof(ohead));
+ tick->tk_aw_handler(tick, uio);
+ err = EINVAL;
+ } else {
+ memcpy(&tick->tk_aw_ohead, &ohead,
+ sizeof(ohead));
+ err = tick->tk_aw_handler(tick, uio);
+ }
} else {
/* pretender doesn't wanna do anything with answer */
SDT_PROBE2(fusefs, , device, trace, 1,
diff --git a/tests/sys/fs/fusefs/lookup.cc b/tests/sys/fs/fusefs/lookup.cc
--- a/tests/sys/fs/fusefs/lookup.cc
+++ b/tests/sys/fs/fusefs/lookup.cc
@@ -276,6 +276,27 @@
EXPECT_EQ(ESTALE, errno);
}
+/*
+ * A daemon that returns an illegal error value should be handled gracefully.
+ * Regression test for https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=263220
+ */
+TEST_F(Lookup, ejustreturn)
+{
+ const char FULLPATH[] = "mountpoint/does_not_exist";
+ const char RELPATH[] = "does_not_exist";
+
+ EXPECT_LOOKUP(FUSE_ROOT_ID, RELPATH)
+ .WillOnce(Invoke(ReturnImmediate([=](auto in __unused, auto& out) {
+ out.header.len = sizeof(out.header);
+ out.header.error = 2;
+ m_mock->m_expected_write_errno = EINVAL;
+ })));
+
+ EXPECT_NE(0, access(FULLPATH, F_OK));
+
+ EXPECT_EQ(EIO, errno);
+}
+
TEST_F(Lookup, enoent)
{
const char FULLPATH[] = "mountpoint/does_not_exist";
diff --git a/tests/sys/fs/fusefs/mockfs.hh b/tests/sys/fs/fusefs/mockfs.hh
--- a/tests/sys/fs/fusefs/mockfs.hh
+++ b/tests/sys/fs/fusefs/mockfs.hh
@@ -340,6 +340,9 @@
/* pid of child process, for two-process test cases */
pid_t m_child_pid;
+ /* the expected errno of the next write to /dev/fuse */
+ int m_expected_write_errno;
+
/* Maximum size of a FUSE_WRITE write */
uint32_t m_maxwrite;
diff --git a/tests/sys/fs/fusefs/mockfs.cc b/tests/sys/fs/fusefs/mockfs.cc
--- a/tests/sys/fs/fusefs/mockfs.cc
+++ b/tests/sys/fs/fusefs/mockfs.cc
@@ -418,6 +418,7 @@
const bool trueval = true;
m_daemon_id = NULL;
+ m_expected_write_errno = 0;
m_kernel_minor_version = kernel_minor_version;
m_maxreadahead = max_readahead;
m_maxwrite = MIN(max_write, max_max_write);
@@ -779,6 +780,7 @@
bzero(in.get(), sizeof(*in));
read_request(*in, buflen);
+ m_expected_write_errno = 0;
if (m_quit)
break;
if (verbosity > 0)
@@ -1011,7 +1013,12 @@
FAIL() << "not yet implemented";
}
r = write(m_fuse_fd, &out, out.header.len);
- ASSERT_TRUE(r > 0 || errno == EAGAIN) << strerror(errno);
+ if (m_expected_write_errno) {
+ ASSERT_EQ(-1, r);
+ ASSERT_EQ(m_expected_write_errno, errno) << strerror(errno);
+ } else {
+ ASSERT_TRUE(r > 0 || errno == EAGAIN) << strerror(errno);
+ }
}
void* MockFS::service(void *pthr_data) {
diff --git a/tests/sys/fs/fusefs/utils.cc b/tests/sys/fs/fusefs/utils.cc
--- a/tests/sys/fs/fusefs/utils.cc
+++ b/tests/sys/fs/fusefs/utils.cc
@@ -217,7 +217,7 @@
return (in.header.opcode == FUSE_DESTROY);
}, Eq(true)),
_)
- ).WillOnce(Invoke( ReturnImmediate([&](auto in, auto& out) {
+ ).WillOnce(Invoke(ReturnImmediate([=](auto in, auto& out) {
m_mock->m_quit = true;
out.header.len = sizeof(out.header);
out.header.unique = in.header.unique;

File Metadata

Mime Type
text/plain
Expires
Thu, Apr 2, 6:13 AM (10 h, 6 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
30710923
Default Alt Text
D34931.diff (3 KB)

Event Timeline