Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F111092065
D34955.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
2 KB
Referenced Files
None
Subscribers
None
D34955.diff
View Options
diff --git a/sys/fs/fuse/fuse_io.c b/sys/fs/fuse/fuse_io.c
--- a/sys/fs/fuse/fuse_io.c
+++ b/sys/fs/fuse/fuse_io.c
@@ -395,8 +395,19 @@
fwo = ((struct fuse_write_out *)fdi.answ);
+ if (fwo->size > fwi->size) {
+ fuse_warn(data, FSESS_WARN_WROTE_LONG,
+ "wrote more data than we provided it.");
+ /* This is bonkers. Clear attr cache. */
+ fvdat->flag &= ~FN_SIZECHANGE;
+ fuse_vnode_clear_attr_cache(vp);
+ err = EINVAL;
+ break;
+ }
+
/* Adjust the uio in the case of short writes */
diff = fwi->size - fwo->size;
+
as_written_offset = uio->uio_offset - diff;
if (as_written_offset - diff > filesize) {
@@ -406,12 +417,7 @@
if (as_written_offset - diff >= filesize)
fvdat->flag &= ~FN_SIZECHANGE;
- if (diff < 0) {
- fuse_warn(data, FSESS_WARN_WROTE_LONG,
- "wrote more data than we provided it.");
- err = EINVAL;
- break;
- } else if (diff > 0) {
+ if (diff > 0) {
/* Short write */
if (!direct_io) {
fuse_warn(data, FSESS_WARN_SHORT_WRITE,
diff --git a/tests/sys/fs/fusefs/write.cc b/tests/sys/fs/fusefs/write.cc
--- a/tests/sys/fs/fusefs/write.cc
+++ b/tests/sys/fs/fusefs/write.cc
@@ -410,6 +410,67 @@
leak(fd);
}
+/* It is an error if the daemon claims to have written more data than we sent */
+TEST_F(Write, indirect_io_long_write)
+{
+ const char FULLPATH[] = "mountpoint/some_file.txt";
+ const char RELPATH[] = "some_file.txt";
+ const char *CONTENTS = "abcdefghijklmnop";
+ uint64_t ino = 42;
+ int fd;
+ ssize_t bufsize = strlen(CONTENTS);
+ ssize_t bufsize_out = 100;
+ off_t some_other_size = 25;
+ struct stat sb;
+
+ expect_lookup(RELPATH, ino, 0);
+ expect_open(ino, 0, 1);
+ expect_write(ino, 0, bufsize, bufsize_out, CONTENTS);
+ expect_getattr(ino, some_other_size);
+
+ fd = open(FULLPATH, O_WRONLY);
+ ASSERT_LE(0, fd) << strerror(errno);
+
+ ASSERT_EQ(-1, write(fd, CONTENTS, bufsize)) << strerror(errno);
+ ASSERT_EQ(EINVAL, errno);
+
+ /*
+ * Following such an error, we should requery the server for the file's
+ * size.
+ */
+ fstat(fd, &sb);
+ ASSERT_EQ(sb.st_size, some_other_size);
+
+ leak(fd);
+}
+
+/*
+ * Don't crash if the server returns a write that can't be represented as a
+ * signed 32 bit number. Regression test for
+ * https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=263263
+ */
+TEST_F(Write, indirect_io_very_long_write)
+{
+ const char FULLPATH[] = "mountpoint/some_file.txt";
+ const char RELPATH[] = "some_file.txt";
+ const char *CONTENTS = "abcdefghijklmnop";
+ uint64_t ino = 42;
+ int fd;
+ ssize_t bufsize = strlen(CONTENTS);
+ ssize_t bufsize_out = 3 << 30;
+
+ expect_lookup(RELPATH, ino, 0);
+ expect_open(ino, 0, 1);
+ expect_write(ino, 0, bufsize, bufsize_out, CONTENTS);
+
+ fd = open(FULLPATH, O_WRONLY);
+ ASSERT_LE(0, fd) << strerror(errno);
+
+ ASSERT_EQ(-1, write(fd, CONTENTS, bufsize)) << strerror(errno);
+ ASSERT_EQ(EINVAL, errno);
+ leak(fd);
+}
+
/*
* When the direct_io option is used, filesystems are allowed to write less
* data than requested. We should return the short write to userland.
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Feb 28, 7:46 AM (19 h, 13 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16882005
Default Alt Text
D34955.diff (2 KB)
Attached To
Mode
D34955: fusefs: correctly handle servers that report too much data written
Attached
Detach File
Event Timeline
Log In to Comment