Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package fuse-overlayfs for openSUSE:Factory checked in at 2021-10-05 22:33:31 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/fuse-overlayfs (Old) and /work/SRC/openSUSE:Factory/.fuse-overlayfs.new.2443 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "fuse-overlayfs" Tue Oct 5 22:33:31 2021 rev:16 rq:922140 version:1.7.1 Changes: -------- --- /work/SRC/openSUSE:Factory/fuse-overlayfs/fuse-overlayfs.changes 2021-03-02 15:15:02.653502844 +0100 +++ /work/SRC/openSUSE:Factory/.fuse-overlayfs.new.2443/fuse-overlayfs.changes 2021-10-05 22:33:47.046862203 +0200 @@ -1,0 +2,26 @@ +Tue Sep 28 12:30:08 UTC 2021 - Klaus K??mpf <kkae...@suse.com> + +- Update to version 1.7.1 + * set FUSE_CAP_POSIX_ACL only when it is supported by FUSE. + * treat statx failure with EINVAL as ENOSYS, so that the fallback + is attempted. + +- Update to version 1.7.0 + * fix read xattrs for device files + * don't create whiteout files in opaque dirs. + * fix reading files when running with euid != 0. + * enable POSIX ACLs. + +- Update to version 1.6.0 + * fix an invalid access when filtering internal xattrs that could + deal to a segfault. + +- Update to version 1.5.0 + * honor FUSE_OVERLAYFS_DISABLE_OVL_WHITEOUT also for renames + * use strncpy instead of strcpy + * fix renameat2(RENAME_NOREPLACE) on older kernels that lack + device whiteouts for unprivileged users. + * fix creating a symlink on top of a removed file. + * fix copyup of xattrs longer than 256 bytes. + +------------------------------------------------------------------- Old: ---- v1.4.0.tar.gz New: ---- v1.7.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ fuse-overlayfs.spec ++++++ --- /var/tmp/diff_new_pack.mHrtpf/_old 2021-10-05 22:33:47.666863282 +0200 +++ /var/tmp/diff_new_pack.mHrtpf/_new 2021-10-05 22:33:47.666863282 +0200 @@ -17,7 +17,7 @@ Name: fuse-overlayfs -Version: 1.4.0 +Version: 1.7.1 Release: 0 Summary: FUSE implementation for overlayfs License: GPL-3.0-only ++++++ v1.4.0.tar.gz -> v1.7.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fuse-overlayfs-1.4.0/.github/workflows/test.yaml new/fuse-overlayfs-1.7.1/.github/workflows/test.yaml --- old/fuse-overlayfs-1.4.0/.github/workflows/test.yaml 2021-01-20 09:29:06.000000000 +0100 +++ new/fuse-overlayfs-1.7.1/.github/workflows/test.yaml 2021-08-10 08:59:01.000000000 +0200 @@ -51,7 +51,7 @@ - test: ovl-whiteouts env: GOPATH: /root/go - + TAGS: exclude_graphdriver_devicemapper exclude_graphdriver_btrfs no_libsubid steps: - name: checkout uses: actions/checkout@v2 @@ -62,9 +62,9 @@ sudo apt-get install -q -y attr automake autotools-dev git make gcc pkg-config xz-utils python3.8 g++ python3-setuptools libdevmapper-dev btrfs-progs libbtrfs-dev go-md2man parallel wget libfuse3-dev bats sudo mkdir -p /lower /upper /mnt + sudo GOPATH=$GOPATH go get -d github.com/containers/storage + sudo TAGS="$TAGS" GOPATH=$GOPATH sh -c "(cd $GOPATH/src/github.com/containers/storage; sed -i -e 's|^AUTOTAGS.*$|AUTOTAGS := $TAGS|' Makefile; make GO111MODULE=on containers-storage)" sudo sh -c "(cd /; git clone https://github.com/amir73il/unionmount-testsuite.git)" - sudo go get github.com/containers/storage - sudo GOPATH=$GOPATH sh -c "(cd /root/go/src/github.com/containers/storage; sed -i -e 's|^AUTOTAGS.*$|AUTOTAGS := exclude_graphdriver_devicemapper exclude_graphdriver_btrfs|' Makefile; make GO111MODULE=on containers-storage)" - name: run autogen.sh run: | @@ -89,6 +89,7 @@ sudo tests/unlink.sh sudo tests/alpine.sh sudo sh -c "(cd /root/go/src/github.com/containers/storage/tests; JOBS=1 STORAGE_OPTION=overlay.mount_program=/sbin/fuse-overlayfs STORAGE_DRIVER=overlay unshare -m ./test_runner.bash)" + tests/unpriv.sh ;; no-ovl-whiteouts) sudo sh -c "(cd /unionmount-testsuite; FUSE_OVERLAYFS_DISABLE_OVL_WHITEOUT=1 unshare -m ./run --ov --fuse=fuse-overlayfs --xdev)" @@ -96,5 +97,6 @@ sudo FUSE_OVERLAYFS_DISABLE_OVL_WHITEOUT=1 tests/unlink.sh sudo FUSE_OVERLAYFS_DISABLE_OVL_WHITEOUT=1 tests/alpine.sh sudo sh -c "(cd /root/go/src/github.com/containers/storage/tests; JOBS=1 FUSE_OVERLAYFS_DISABLE_OVL_WHITEOUT=1 STORAGE_OPTION=overlay.mount_program=/sbin/fuse-overlayfs STORAGE_DRIVER=overlay unshare -m ./test_runner.bash)" + FUSE_OVERLAYFS_DISABLE_OVL_WHITEOUT=1 tests/unpriv.sh ;; esac diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fuse-overlayfs-1.4.0/NEWS new/fuse-overlayfs-1.7.1/NEWS --- old/fuse-overlayfs-1.4.0/NEWS 2021-01-20 09:29:06.000000000 +0100 +++ new/fuse-overlayfs-1.7.1/NEWS 2021-08-10 08:59:01.000000000 +0200 @@ -1,3 +1,30 @@ +* fuse-overlayfs-1.7.1 + +- set FUSE_CAP_POSIX_ACL only when it is supported by FUSE. +- treat statx failure with EINVAL as ENOSYS, so that the fallback + is attempted. + +* fuse-overlayfs-1.7 + +- fix read xattrs for device files +- don't create whiteout files in opaque dirs. +- fix reading files when running with euid != 0. +- enable POSIX ACLs. + +* fuse-overlayfs-1.6 + +- fix an invalid access when filtering internal xattrs that could + deal to a segfault. + +* fuse-overlayfs-1.5 + +- honor FUSE_OVERLAYFS_DISABLE_OVL_WHITEOUT also for renames +- use strncpy instead of strcpy +- fix renameat2(RENAME_NOREPLACE) on older kernels that lack + device whiteouts for unprivileged users. +- fix creating a symlink on top of a removed file. +- fix copyup of xattrs longer than 256 bytes. + * fuse-overlayfs-1.4 - add squash_to_uid and squash_to_gid diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fuse-overlayfs-1.4.0/configure.ac new/fuse-overlayfs-1.7.1/configure.ac --- old/fuse-overlayfs-1.4.0/configure.ac 2021-01-20 09:29:06.000000000 +0100 +++ new/fuse-overlayfs-1.7.1/configure.ac 2021-08-10 08:59:01.000000000 +0200 @@ -1,5 +1,5 @@ AC_PREREQ([2.69]) -AC_INIT([fuse-overlayfs], [1.4], [giuse...@scrivano.org]) +AC_INIT([fuse-overlayfs], [1.7.1], [giuse...@scrivano.org]) AC_CONFIG_SRCDIR([main.c]) AC_CONFIG_HEADERS([config.h]) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fuse-overlayfs-1.4.0/direct.c new/fuse-overlayfs-1.7.1/direct.c --- old/fuse-overlayfs-1.4.0/direct.c 2021-01-20 09:29:06.000000000 +0100 +++ new/fuse-overlayfs-1.7.1/direct.c 2021-08-10 08:59:01.000000000 +0200 @@ -43,17 +43,9 @@ static int direct_listxattr (struct ovl_layer *l, const char *path, char *buf, size_t size) { - cleanup_close int fd = -1; char full_path[PATH_MAX]; - int ret; - - full_path[0] = '\0'; - ret = open_fd_or_get_path (l, path, full_path, &fd, O_RDONLY); - if (ret < 0) - return ret; - if (fd >= 0) - return flistxattr (fd, buf, size); + strconcat3 (full_path, PATH_MAX, l->path, "/", path); return llistxattr (full_path, buf, size); } @@ -61,17 +53,9 @@ static int direct_getxattr (struct ovl_layer *l, const char *path, const char *name, char *buf, size_t size) { - cleanup_close int fd = -1; char full_path[PATH_MAX]; - int ret; - full_path[0] = '\0'; - ret = open_fd_or_get_path (l, path, full_path, &fd, O_RDONLY); - if (ret < 0) - return ret; - - if (fd >= 0) - return fgetxattr (fd, name, buf, size); + strconcat3 (full_path, PATH_MAX, l->path, "/", path); return lgetxattr (full_path, name, buf, size); } @@ -84,8 +68,7 @@ struct statx stx; ret = statx (fd, "", AT_STATX_DONT_SYNC|AT_EMPTY_PATH, mask, &stx); - - if (ret < 0 && errno == ENOSYS) + if (ret < 0 && (errno == ENOSYS || errno == EINVAL)) goto fallback; if (ret == 0) { @@ -112,8 +95,7 @@ struct statx stx; ret = statx (l->fd, path, AT_STATX_DONT_SYNC|flags, mask, &stx); - - if (ret < 0 && errno == ENOSYS) + if (ret < 0 && (errno == ENOSYS || errno == EINVAL)) goto fallback; if (ret == 0) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fuse-overlayfs-1.4.0/fuse-overlayfs.1 new/fuse-overlayfs-1.7.1/fuse-overlayfs.1 --- old/fuse-overlayfs-1.4.0/fuse-overlayfs.1 2021-01-20 09:29:06.000000000 +0100 +++ new/fuse-overlayfs-1.7.1/fuse-overlayfs.1 2021-08-10 08:59:01.000000000 +0200 @@ -43,11 +43,6 @@ system as the upper dir. .PP -\fB\-o workdir=workdir\fP -A directory used internally by fuse\-overlays, must be on the same file -system as the upper dir. - -.PP \fB\-o uidmapping=UID:MAPPED\-UID:LEN[,UID2:MAPPED\-UID2:LEN2]\fP \fB\-o gidmapping=GID:MAPPED\-GID:LEN[,GID2:MAPPED\-GID2:LEN2]\fP Specifies the dynamic UID/GID mapping used by fuse\-overlayfs when @@ -116,6 +111,16 @@ .PP It has higher precedence over \fBsquash\_to\_root\fP\&. +.PP +\fB\-o static\_nlink\fP +Set st\_nlink to the static value 1 for all directories. + +.PP +This can be useful for higher latency file systems such as NFS, where +counting the number of hard links for a directory with many files can +be a slow operation. With this option enabled, the number of hard +links reported when running stat for any directory is 1. + .SH SEE ALSO .PP diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fuse-overlayfs-1.4.0/fuse-overlayfs.1.md new/fuse-overlayfs-1.7.1/fuse-overlayfs.1.md --- old/fuse-overlayfs-1.4.0/fuse-overlayfs.1.md 2021-01-20 09:29:06.000000000 +0100 +++ new/fuse-overlayfs-1.7.1/fuse-overlayfs.1.md 2021-08-10 08:59:01.000000000 +0200 @@ -35,10 +35,6 @@ A directory used internally by fuse-overlays, must be on the same file system as the upper dir. -**-o workdir=workdir** -A directory used internally by fuse-overlays, must be on the same file -system as the upper dir. - **-o uidmapping=UID:MAPPED-UID:LEN[,UID2:MAPPED-UID2:LEN2]** **-o gidmapping=GID:MAPPED-GID:LEN[,GID2:MAPPED-GID2:LEN2]** Specifies the dynamic UID/GID mapping used by fuse-overlayfs when @@ -93,6 +89,14 @@ It has higher precedence over **squash_to_root**. +**-o static_nlink** +Set st_nlink to the static value 1 for all directories. + +This can be useful for higher latency file systems such as NFS, where +counting the number of hard links for a directory with many files can +be a slow operation. With this option enabled, the number of hard +links reported when running stat for any directory is 1. + # SEE ALSO **fuse**(8), **mount**(8), **user_namespaces**(7) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fuse-overlayfs-1.4.0/fuse-overlayfs.h new/fuse-overlayfs-1.7.1/fuse-overlayfs.h --- old/fuse-overlayfs-1.4.0/fuse-overlayfs.h 2021-01-20 09:29:06.000000000 +0100 +++ new/fuse-overlayfs-1.7.1/fuse-overlayfs.h 2021-08-10 08:59:01.000000000 +0200 @@ -99,11 +99,15 @@ int squash_to_root; int squash_to_uid; int squash_to_gid; + int static_nlink; /* current uid/gid*/ uid_t uid; uid_t gid; + /* process euid. */ + uid_t euid; + struct ovl_plugin_context *plugins_ctx; }; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fuse-overlayfs-1.4.0/main.c new/fuse-overlayfs-1.7.1/main.c --- old/fuse-overlayfs-1.4.0/main.c 2021-01-20 09:29:06.000000000 +0100 +++ new/fuse-overlayfs-1.7.1/main.c 2021-08-10 08:59:01.000000000 +0200 @@ -158,8 +158,6 @@ }; #endif -static bool disable_ovl_whiteout; - static uid_t overflow_uid; static gid_t overflow_gid; @@ -179,7 +177,7 @@ char fmt[128]; int l = snprintf (fmt, sizeof (fmt) - 1, "# INODES: %zu\n# NODES: %zu\n", stats.inodes, stats.nodes); fmt[l] = '\0'; - write (STDERR_FILENO, fmt, l + 1); + (void) write (STDERR_FILENO, fmt, l + 1); } static double @@ -225,6 +223,8 @@ offsetof (struct ovl_data, squash_to_uid), 1}, {"squash_to_gid=%d", offsetof (struct ovl_data, squash_to_gid), 1}, + {"static_nlink", + offsetof (struct ovl_data, static_nlink), 1}, {"volatile", /* native overlay supports "volatile" to mean fsync=0. */ offsetof (struct ovl_data, fsync), 0}, FUSE_OPT_END @@ -290,6 +290,12 @@ int ret; char path[PATH_MAX]; + if (getenv ("FUSE_OVERLAYFS_DISABLE_OVL_WHITEOUT")) + { + can_mknod = false; + return; + } + sprintf (path, "%lu", get_next_wd_counter ()); ret = mknodat (lo->workdir_fd, path, S_IFCHR|0700, makedev (0, 0)); @@ -421,6 +427,9 @@ if ((conn->capable & FUSE_CAP_WRITEBACK_CACHE) == 0) lo->writeback = 0; + if (conn->capable & FUSE_CAP_POSIX_ACL) + conn->want |= FUSE_CAP_POSIX_ACL; + conn->want |= FUSE_CAP_DONT_MASK | FUSE_CAP_SPLICE_READ | FUSE_CAP_SPLICE_WRITE | FUSE_CAP_SPLICE_MOVE; if (lo->writeback) conn->want |= FUSE_CAP_WRITEBACK_CACHE; @@ -723,7 +732,7 @@ return 0; } - if (!disable_ovl_whiteout && !skip_mknod && can_mknod) + if (!skip_mknod && can_mknod) { char whiteout_path[PATH_MAX]; @@ -733,6 +742,21 @@ if (ret == 0) return 0; + if (errno == EEXIST) + { + int saved_errno = errno; + struct stat st; + + /* Check whether it is already a whiteout. */ + if (TEMP_FAILURE_RETRY (fstatat (get_upper_layer (lo)->fd, whiteout_path, &st, AT_SYMLINK_NOFOLLOW)) == 0 + && (st.st_mode & S_IFMT) == S_IFCHR + && major (st.st_rdev) == 0 + && minor (st.st_rdev) == 0) + return 0; + + errno = saved_errno; + } + if (errno != EPERM && errno != ENOTSUP) return -1; @@ -742,7 +766,6 @@ strconcat3 (whiteout_wh_path, PATH_MAX, parent->path, "/.wh.", name); - fd = get_upper_layer (lo)->ds->openat (get_upper_layer (lo), whiteout_wh_path, O_CREAT|O_WRONLY|O_NONBLOCK, 0700); if (fd < 0 && errno != EEXIST) return -1; @@ -881,15 +904,20 @@ st->st_dev = node->tmp_dev; if (ret == 0 && node_dirp (node)) { - struct ovl_node *it; + if (!data->static_nlink) + { + struct ovl_node *it; - st->st_nlink = 2; + st->st_nlink = 2; - for (it = hash_get_first (node->children); it; it = hash_get_next (node->children, it)) - { - if (node_dirp (it)) - st->st_nlink++; + for (it = hash_get_first (node->children); it; it = hash_get_next (node->children, it)) + { + if (node_dirp (it)) + st->st_nlink++; + } } + else + st->st_nlink = 1; } return ret; @@ -919,7 +947,7 @@ if (n->parent) { - if (hash_lookup (n->parent->children, n) == n) + if (n->parent->children && hash_lookup (n->parent->children, n) == n) hash_delete (n->parent->children, n); n->parent->loaded = 0; n->parent = NULL; @@ -1040,6 +1068,10 @@ needs_whiteout = true; } + // if the parent directory is opaque, there's no need to put a whiteout in it. + if (node->parent != NULL) + needs_whiteout = needs_whiteout && (is_directory_opaque(get_upper_layer(lo), node->parent->path) < 1); + if (needs_whiteout) { /* If the atomic rename+mknod failed, then fallback into doing it in two steps. */ @@ -1348,9 +1380,10 @@ char *tmp; s = fgetxattr (sfd, name, buffer, current_size); - if (s < 0) + if (s >= 0 && s < current_size) break; - if (s < current_size) + + if (s < 0 && errno != ERANGE) break; current_size *= 2; @@ -1384,7 +1417,7 @@ ret = calloc (1, sizeof (*ret)); if (ret == NULL) - return NULL; + return NULL; ret->parent = parent; ret->layer = layer; @@ -1548,7 +1581,6 @@ insert_node (struct ovl_node *parent, struct ovl_node *item, bool replace) { struct ovl_node *old = NULL, *prev_parent = item->parent; - int is_dir = node_dirp (item); int ret; if (prev_parent) @@ -2088,7 +2120,7 @@ return; } - if (node_dirp (node)) + if (!lo->static_nlink && node_dirp (node)) { node = reload_dir (lo, node); if (node == NULL) @@ -2127,13 +2159,47 @@ return (struct ovl_dirp *) (uintptr_t) fi->fh; } +static int +reload_tbl (struct ovl_data *lo, struct ovl_dirp *d, struct ovl_node *node) +{ + size_t counter = 0; + struct ovl_node *it; + + node = reload_dir (lo, node); + if (node == NULL) + return -1; + + if (d->tbl) + free (d->tbl); + + d->offset = 0; + d->parent = node; + d->tbl_size = hash_get_n_entries (node->children) + 2; + d->tbl = calloc (sizeof (struct ovl_node *), d->tbl_size); + if (d->tbl == NULL) + { + errno = ENOMEM; + return -1; + } + + d->tbl[counter++] = node; + d->tbl[counter++] = node->parent; + + for (it = hash_get_first (node->children); it; it = hash_get_next (node->children, it)) + { + it->ino->lookups++; + it->node_lookups++; + d->tbl[counter++] = it; + } + + return 0; +} + static void ovl_opendir (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi) { - size_t counter = 0; struct ovl_node *node; struct ovl_data *lo = ovl_data (req); - struct ovl_node *it; struct ovl_dirp *d = calloc (1, sizeof (struct ovl_dirp)); cleanup_lock int l = enter_big_lock (); @@ -2159,29 +2225,7 @@ goto out_errno; } - node = reload_dir (lo, node); - if (node == NULL) - goto out_errno; - - d->offset = 0; d->parent = node; - d->tbl_size = hash_get_n_entries (node->children) + 2; - d->tbl = malloc (sizeof (struct ovl_node *) * d->tbl_size); - if (d->tbl == NULL) - { - errno = ENOMEM; - goto out_errno; - } - - d->tbl[counter++] = node; - d->tbl[counter++] = node->parent; - - for (it = hash_get_first (node->children); it; it = hash_get_next (node->children, it)) - { - it->ino->lookups++; - it->node_lookups++; - d->tbl[counter++] = it; - } fi->fh = (uintptr_t) d; if (get_timeout (lo) > 0) @@ -2301,6 +2345,16 @@ fuse_reply_err (req, errno); return; } + + if (offset == 0 || d->tbl == NULL) + { + if (reload_tbl (lo, d, d->parent) < 0) + { + fuse_reply_err (req, errno); + return; + } + } + p = buffer; for (; remaining > 0 && offset < d->tbl_size; offset++) { @@ -2338,7 +2392,7 @@ } else { - if (node_dirp (node)) + if (!lo->static_nlink && node_dirp (node)) { node = reload_dir (lo, node); if (node == NULL) @@ -2347,7 +2401,6 @@ return; } } - memset (&e, 0, sizeof (e)); ret = rpl_stat (req, node, -1, NULL, NULL, st); if (ret < 0) @@ -2428,6 +2481,41 @@ fuse_reply_err (req, 0); } +/* in-place filter xattrs that cannot be accessed. */ +static ssize_t +filter_xattrs_list (char *buf, ssize_t len) +{ + ssize_t ret = 0; + char *it; + + if (buf == NULL) + return len; + + it = buf; + + while (it < buf + len) + { + size_t it_len; + + it_len = strlen (it) + 1; + + if (can_access_xattr (it)) + { + it += it_len; + ret += it_len; + } + else + { + char *next = it + it_len; + + memmove (it, next, buf + len - next); + len -= it_len; + } + } + + return ret; +} + static void ovl_listxattr (fuse_req_t req, fuse_ino_t ino, size_t size) { @@ -2436,7 +2524,6 @@ struct ovl_node *node; struct ovl_data *lo = ovl_data (req); cleanup_free char *buf = NULL; - size_t i; int ret; if (UNLIKELY (ovl_debug (req))) @@ -2479,22 +2566,7 @@ return; } - len = ret; - - for (i = 0; buf && i < len;) - { - size_t current_len; - const char *cur_attr = buf + i; - - current_len = strlen (cur_attr) + 1; - if (can_access_xattr (cur_attr)) - i += current_len; - else - { - memmove (buf + i, cur_attr + current_len, len - current_len); - len -= current_len; - } - } + len = filter_xattrs_list (buf, ret); if (size == 0) fuse_reply_xattr (req, len); @@ -2907,6 +2979,8 @@ mode = st.st_mode; if (lo->xattr_permissions) mode |= 0755; + if (lo->euid > 0) + mode |= 0200; if ((mode & S_IFMT) == S_IFDIR) { @@ -3923,19 +3997,23 @@ l = release_big_lock (); memset (times, 0, sizeof (times)); - times[0].tv_sec = UTIME_OMIT; - times[1].tv_sec = UTIME_OMIT; + times[0].tv_nsec = UTIME_OMIT; + times[1].tv_nsec = UTIME_OMIT; if (to_set & FUSE_SET_ATTR_ATIME) - times[0] = attr->st_atim; - else if (to_set & FUSE_SET_ATTR_ATIME_NOW) - times[0].tv_sec = UTIME_NOW; + { + times[0] = attr->st_atim; + if (to_set & FUSE_SET_ATTR_ATIME_NOW) + times[0].tv_nsec = UTIME_NOW; + } if (to_set & FUSE_SET_ATTR_MTIME) - times[1] = attr->st_mtim; - else if (to_set & FUSE_SET_ATTR_MTIME_NOW) - times[1].tv_sec = UTIME_NOW; + { + times[1] = attr->st_mtim; + if (to_set & FUSE_SET_ATTR_MTIME_NOW) + times[1].tv_nsec = UTIME_NOW; + } - if (times[0].tv_sec != UTIME_OMIT || times[1].tv_sec != UTIME_OMIT) + if (times[0].tv_nsec != UTIME_OMIT || times[1].tv_nsec != UTIME_OMIT) { if (fd >= 0) ret = futimens (fd, times); @@ -4375,9 +4453,8 @@ struct ovl_node *pnode, *node, *destnode, *destpnode; struct ovl_data *lo = ovl_data (req); int ret; - int saved_errno; - int srcfd = -1; - int destfd = -1; + cleanup_close int srcfd = -1; + cleanup_close int destfd = -1; struct ovl_node key; bool destnode_is_whiteout = false; @@ -4515,8 +4592,19 @@ /* Try to create the whiteout atomically, if it fails do the rename+mknod separately. */ - ret = direct_renameat2 (srcfd, name, destfd, - newname, flags|RENAME_WHITEOUT); + if (! can_mknod) + { + ret = -1; + errno = EPERM; + } + else + { + ret = direct_renameat2 (srcfd, name, destfd, + newname, flags|RENAME_WHITEOUT); + } + /* If the destination is a whiteout, just overwrite it. */ + if (ret < 0 && errno == EEXIST) + ret = direct_renameat2 (srcfd, name, destfd, newname, flags & ~RENAME_NOREPLACE); if (ret < 0) { ret = direct_renameat2 (srcfd, name, destfd, @@ -4527,6 +4615,8 @@ ret = create_whiteout (lo, pnode, name, false, true); if (ret < 0) goto error; + + pnode->loaded = 0; } if (delete_whiteout (lo, destfd, NULL, newname) < 0) @@ -4549,20 +4639,12 @@ node->loaded = 0; ret = 0; - goto cleanup; + fuse_reply_err (req, 0); + return; error: ret = -1; - - cleanup: - saved_errno = errno; - if (srcfd >= 0) - close (srcfd); - if (destfd >= 0) - close (destfd); - errno = saved_errno; - - fuse_reply_err (req, ret == 0 ? 0 : errno); + fuse_reply_err (req, errno); } static void @@ -4978,7 +5060,6 @@ struct ovl_node *node; struct ovl_data *lo = ovl_data (req); cleanup_lock int l = 0; - char path[PATH_MAX]; if (!lo->fsync) { @@ -5004,9 +5085,6 @@ return; } - if (fd < 0) - strcpy (path, node->path); - if (! do_fsync) { fuse_reply_err (req, 0); @@ -5014,7 +5092,7 @@ } if (do_fsync) - ret = direct_fsync (node->layer, fd, path, datasync); + ret = direct_fsync (node->layer, fd, node->path, datasync); fuse_reply_err (req, ret == 0 ? 0 : errno); } @@ -5406,7 +5484,12 @@ if (dent->d_type != DT_DIR) { char *new_plugins = NULL; - asprintf (&new_plugins, "%s/%s:%s", PKGLIBEXECDIR, dent->d_name, plugins); + if (asprintf (&new_plugins, "%s/%s:%s", PKGLIBEXECDIR, dent->d_name, plugins) < 0) + { + free (plugins); + closedir (dp); + return NULL; + } free (plugins); plugins = new_plugins; } @@ -5434,7 +5517,9 @@ .fsync = 1, .squash_to_uid = -1, .squash_to_gid = -1, + .static_nlink = 0, .xattr_permissions = 0, + .euid = geteuid (), .timeout = 1000000000.0, .timeout_str = NULL, .writeback = 1, @@ -5448,9 +5533,6 @@ struct ovl_layer *tmp_layer = NULL; struct fuse_args args = FUSE_ARGS_INIT (argc, newargv); - if (getenv ("FUSE_OVERLAYFS_DISABLE_OVL_WHITEOUT")) - disable_ovl_whiteout = true; - memset (&opts, 0, sizeof (opts)); if (fuse_opt_parse (&args, &lo, ovl_opts, fuse_opt_proc) == -1) error (EXIT_FAILURE, 0, "error parsing options"); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fuse-overlayfs-1.4.0/tests/fedora-installs.sh new/fuse-overlayfs-1.7.1/tests/fedora-installs.sh --- old/fuse-overlayfs-1.4.0/tests/fedora-installs.sh 2021-01-20 09:29:06.000000000 +0100 +++ new/fuse-overlayfs-1.7.1/tests/fedora-installs.sh 2021-08-10 08:59:01.000000000 +0200 @@ -70,6 +70,9 @@ touch lower/file-lower-layer +# set a "big" xattr +setfattr -n user.big-xattr -v "$(seq 1000 | tr -d '\n')" lower/file-lower-layer + # no upper layer fuse-overlayfs -o lowerdir=lower merged @@ -201,8 +204,52 @@ touch merged/$(printf %${merged_max_filename_len}s | tr ' ' A}) # If a file is removed but referenced, we must still be able to access it. -echo 12345 > merged/toremove -sleep 30 < merged/toremove & +echo 12345 | tee merged/toremove +exec 3<> merged/toremove +sleep 90 & +exec 3>&- sleep_pid=$! rm merged/toremove -grep 12345 /proc/$sleep_pid/fd/0 +grep 12345 /proc/$sleep_pid/fd/3 + +touch merged/a merged/b +chmod 6 merged/a +mv merged/a merged/x +mv merged/b merged/a + +# https://github.com/containers/fuse-overlayfs/issues/279 +umount -l merged + +rm -rf lower upper workdir merged +mkdir lower upper workdir merged +mkdir lower/test +touch lower/test/a.txt + +fuse-overlayfs -o lowerdir=lower,upperdir=upper,workdir=workdir merged + +(cd merged/test; touch a.txt; mv a.txt a2.txt; touch a3.txt; ln -s a3.txt a.txt) + +if test -e upperdir/test/.wh.a.txt; then + echo "whiteout file still exists" >&2 + exit 1 +fi + +# https://github.com/containers/fuse-overlayfs/issues/306 +umount -l merged + +rm -rf lower upper workdir merged +mkdir lower upper workdir merged + +mkdir -p lower/a/b +fuse-overlayfs -o lowerdir=lower,upperdir=upper,workdir=workdir merged + +rm -rf merged/a +mkdir -p merged/a/b +rm -rf merged/a/b +test \! -e upper/a/b + +mknod merged/dev-foo c 10 175 +attr -l merged/dev-foo + +umount merged + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fuse-overlayfs-1.4.0/tests/unpriv.sh new/fuse-overlayfs-1.7.1/tests/unpriv.sh --- old/fuse-overlayfs-1.4.0/tests/unpriv.sh 1970-01-01 01:00:00.000000000 +0100 +++ new/fuse-overlayfs-1.7.1/tests/unpriv.sh 2021-08-10 08:59:01.000000000 +0200 @@ -0,0 +1,31 @@ +#!/bin/sh + +set -ex + +test $(id -u) -gt 0 + +rm -rf unpriv-test +mkdir unpriv-test + +cd unpriv-test + +mkdir lower upper workdir merged + +touch lower/a lower/b +chmod 444 lower/a lower/b + +fuse-overlayfs -o lowerdir=lower,upperdir=upper,workdir=workdir merged + +rm -f merged/a +chmod 406 merged/b + +test \! -e merged/a +test $(stat --printf=%a merged/b) -eq 406 +test $(stat --printf=%a upper/b) -eq 406 +if [ ${FUSE_OVERLAYFS_DISABLE_OVL_WHITEOUT:-0} -eq 1 ]; then + test -e upper/.wh.a +else + test -c upper/a +fi + +fusermount -u merged || [ $? -eq "${EXPECT_UMOUNT_STATUS:-0}" ] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fuse-overlayfs-1.4.0/utils.h new/fuse-overlayfs-1.7.1/utils.h --- old/fuse-overlayfs-1.4.0/utils.h 2021-01-20 09:29:06.000000000 +0100 +++ new/fuse-overlayfs-1.7.1/utils.h 2021-08-10 08:59:01.000000000 +0200 @@ -18,7 +18,9 @@ #ifndef UTILS_H # define UTILS_H +#ifndef _GNU_SOURCE # define _GNU_SOURCE +#endif # include <config.h>