diff --git a/Fix-readdir-bug-when-a-non-zero-offset-is-specified-.patch b/Fix-readdir-bug-when-a-non-zero-offset-is-specified-.patch new file mode 100644 index 0000000..3b73c9f --- /dev/null +++ b/Fix-readdir-bug-when-a-non-zero-offset-is-specified-.patch @@ -0,0 +1,173 @@ +From 06fc40705f23cb7e9af4df2febae8e6889b1a95d Mon Sep 17 00:00:00 2001 +From: Rostislav Skudnov +Date: Wed, 25 Jul 2018 10:36:38 +0000 +Subject: [PATCH 4/7] Fix readdir() bug when a non-zero offset is specified in + filler + +The bug occurs when a filesystem client reads a directory until the end, +seeks using seekdir() to some valid non-zero position and calls +readdir(). A valid 'struct dirent *' is expected, but NULL is returned +instead. Pseudocode demonstrating the bug: + +DIR *dp = opendir("some_dir"); +struct dirent *de = readdir(dp); + +/* Get offset of the second entry */ +long offset = telldir(dp); + +/* Read directory until the end */ +while (de) + de = readdir(de); + +seekdir(dp, offset); +de = readdir(dp); +/* de must contain the second entry, but NULL is returned instead */ + +The reason of the bug is that when the end of directory is reached, the +kernel calls FUSE_READDIR op with an offset at the end of directory, so +the filesystem's .readdir callback never calls the filler function, and +we end up with dh->filled set to 1. After seekdir(), FUSE_READDIR is +called again with a new offset, but this time the filesystem's .readdir +callback is never called, and an empty reply is returned. + +Fix by setting dh->filled to 1 only when zero offsets are given to +filler function. + +This commit is backported from the following commit in 'master' branch: + +commit 5f125c5e6be24c8d216a4d3c623dc73d742c8c86 +Author: Rostislav +Date: Sat Jul 21 12:57:09 2018 +0300 + + Fix readdir() bug when a non-zero offset is specified in filler (#269) + +diff -urNp a/lib/fuse.c b/lib/fuse.c +--- a/lib/fuse.c 2019-07-22 00:00:00.000000000 +0000 ++++ b/lib/fuse.c 2019-07-22 00:00:00.000000000 +0000 +@@ -3444,10 +3444,14 @@ static int fill_dir(void *dh_, const cha + } + + if (off) { ++ if (dh->filled) { ++ dh->error = -EIO; ++ return 1; ++ } ++ + if (extend_contents(dh, dh->needlen) == -1) + return 1; + +- dh->filled = 0; + newlen = dh->len + + fuse_add_direntry(dh->req, dh->contents + dh->len, + dh->needlen - dh->len, name, +@@ -3455,6 +3459,8 @@ static int fill_dir(void *dh_, const cha + if (newlen > dh->needlen) + return 1; + } else { ++ dh->filled = 1; ++ + newlen = dh->len + + fuse_add_direntry(dh->req, NULL, 0, name, NULL, 0); + if (extend_contents(dh, newlen) == -1) +@@ -3484,7 +3490,7 @@ static int readdir_fill(struct fuse *f, + dh->len = 0; + dh->error = 0; + dh->needlen = size; +- dh->filled = 1; ++ dh->filled = 0; + dh->req = req; + fuse_prepare_interrupt(f, req, &d); + err = fuse_fs_readdir(f->fs, path, dh, fill_dir, off, fi); +diff -urNp a/test/test.c b/test/test.c +--- a/test/test.c 2019-07-22 00:00:00.000000000 +0000 ++++ b/test/test.c 2019-07-22 00:00:00.000000000 +0000 +@@ -21,6 +21,7 @@ static char testname[256]; + static char testdata[] = "abcdefghijklmnopqrstuvwxyz"; + static char testdata2[] = "1234567890-=qwertyuiop[]\asdfghjkl;'zxcvbnm,./"; + static const char *testdir_files[] = { "f1", "f2", NULL}; ++static long seekdir_offsets[4]; + static char zerodata[4096]; + static int testdatalen = sizeof(testdata) - 1; + static int testdata2len = sizeof(testdata2) - 1; +@@ -79,6 +80,8 @@ static void __start_test(const char *fmt + + #define PERROR(msg) test_perror(__FUNCTION__, msg) + #define ERROR(msg, args...) test_error(__FUNCTION__, msg, ##args) ++#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) ++ + + static int check_size(const char *path, int len) + { +@@ -644,6 +647,63 @@ static int test_ftruncate(int len, int m + return 0; + } + ++static int test_seekdir(void) ++{ ++ int i; ++ int res; ++ DIR *dp; ++ struct dirent *de; ++ ++ start_test("seekdir"); ++ res = create_dir(testdir, testdir_files); ++ if (res == -1) ++ return res; ++ ++ dp = opendir(testdir); ++ if (dp == NULL) { ++ PERROR("opendir"); ++ return -1; ++ } ++ ++ /* Remember dir offsets */ ++ for (i = 0; i < ARRAY_SIZE(seekdir_offsets); i++) { ++ seekdir_offsets[i] = telldir(dp); ++ errno = 0; ++ de = readdir(dp); ++ if (de == NULL) { ++ if (errno) { ++ PERROR("readdir"); ++ goto fail; ++ } ++ break; ++ } ++ } ++ ++ /* Walk until the end of directory */ ++ while (de) ++ de = readdir(dp); ++ ++ /* Start from the last valid dir offset and seek backwards */ ++ for (i--; i >= 0; i--) { ++ seekdir(dp, seekdir_offsets[i]); ++ de = readdir(dp); ++ if (de == NULL) { ++ ERROR("Unexpected end of directory after seekdir()"); ++ goto fail; ++ } ++ } ++ ++ closedir(dp); ++ res = cleanup_dir(testdir, testdir_files, 0); ++ if (!res) ++ success(); ++ return res; ++fail: ++ closedir(dp); ++ cleanup_dir(testdir, testdir_files, 1); ++ return -1; ++} ++ + static int test_utime(void) + { + struct utimbuf utm; +@@ -1425,6 +1485,7 @@ int main(int argc, char *argv[]) + err += test_mkdir(); + err += test_rename_file(); + err += test_rename_dir(); ++ err += test_seekdir(); + err += test_utime(); + err += test_truncate(0); + err += test_truncate(testdatalen / 2); + diff --git a/fuse.spec b/fuse.spec index 202857e..62d9e55 100644 --- a/fuse.spec +++ b/fuse.spec @@ -3,7 +3,7 @@ Name: fuse Version: %{fuse2ver} -Release: 22 +Release: 23 Summary: User space File System of fuse2 License: GPL+ and LGPLv2+ URL: http://fuse.sf.net @@ -26,6 +26,7 @@ Patch6004: 0531-fusermount-whitelist-known-good-filesystems-for-moun.patch Patch6005: 0533-fusermount-Fix-memory-leaks.patch Patch6006: 0545-Fix-invalid-free-of-memory-pointer-in-struct-fuse_bu.patch Patch6007: 0546-Fix-memory-leak-of-FUSE-modules.patch +Patch6008: Fix-readdir-bug-when-a-non-zero-offset-is-specified-.patch Patch9000: bugfix-increase-idle-thread.patch Patch9001: bugfix-invalid-free-and-core.patch @@ -102,6 +103,7 @@ pushd lib%{name}-%{name}-%{fuse2ver} ./makeconf.sh %patch2 -p1 %patch3 -p1 +%patch6008 -p1 popd # fuse 3 @@ -206,6 +208,12 @@ install -p -m 0644 %{SOURCE2} %{buildroot}%{_sysconfdir} %changelog +* Sat Dec 28 2019 openEuler Buildteam - 2.9.7-23 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC:sync bugfix from community + * Wed Sep 4 2019 zoujing - 2.9.7-22 - Type:enhancemnet - ID:NA