From a289a24accc39d8b5dd9be6caf336ded6298f345 Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Tue, 6 Nov 2018 00:48:53 +0100 Subject: [PATCH 1/3] fuse-overlayfs: read correctly inode for dangling symlinks do not follow symlinks when stat'ing a path, so that we read the inode of the symlink itself. Closes: https://github.com/containers/fuse-overlayfs/issues/23 Signed-off-by: Giuseppe Scrivano --- main.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/main.c b/main.c index 5cdf566..38a5602 100644 --- a/main.c +++ b/main.c @@ -765,13 +765,18 @@ make_ovl_node (const char *path, struct ovl_layer *layer, const char *name, ino_ for (it = layer; it; it = it->next) { ssize_t s; - int fd = TEMP_FAILURE_RETRY (openat (it->fd, path, O_RDONLY|O_NONBLOCK)); + int fd = TEMP_FAILURE_RETRY (openat (it->fd, path, O_RDONLY|O_NONBLOCK|O_NOFOLLOW|O_PATH)); if (fd < 0) continue; if (fstat (fd, &st) == 0) ret->ino = st.st_ino; + close (fd); + + fd = TEMP_FAILURE_RETRY (openat (it->fd, path, O_RDONLY|O_NONBLOCK|O_NOFOLLOW)); + if (fd < 0) + continue; s = fgetxattr (fd, PRIVILEGED_ORIGIN_XATTR, path, sizeof (path) - 1); if (s > 0) { From a147df9b112added19fc91e93e690fd411bec6de Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Tue, 6 Nov 2018 21:48:42 +0100 Subject: [PATCH 2/3] fuse-overlayfs: reset times struct before using it Signed-off-by: Giuseppe Scrivano --- main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/main.c b/main.c index 38a5602..f9c352d 100644 --- a/main.c +++ b/main.c @@ -2512,6 +2512,7 @@ ovl_setattr (fuse_req_t req, fuse_ino_t ino, struct stat *attr, int to_set, stru return; } + memset (times, 0, sizeof (times)); times[0].tv_sec = UTIME_OMIT; times[1].tv_sec = UTIME_OMIT; if (to_set & FUSE_SET_ATTR_ATIME) From b54426b6c351c3a4fcc93b7be7c4e18695f10e6f Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Tue, 6 Nov 2018 21:48:07 +0100 Subject: [PATCH 3/3] fuse-overlayfs: honor .wh. whiteout files Signed-off-by: Giuseppe Scrivano --- main.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/main.c b/main.c index f9c352d..f35157b 100644 --- a/main.c +++ b/main.c @@ -1104,6 +1104,7 @@ do_lookup_file (struct ovl_data *lo, fuse_ino_t parent, const char *name) { int ret; char path[PATH_MAX]; + char whpath[PATH_MAX]; struct ovl_layer *it; struct stat st; struct ovl_layer *upper_layer = get_upper_layer (lo); @@ -1146,11 +1147,20 @@ do_lookup_file (struct ovl_data *lo, fuse_ino_t parent, const char *name) } } - wh_name = get_whiteout_name (name, &st); - if (wh_name) - node = make_whiteout_node (path, wh_name); + sprintf (whpath, "%s/.wh.%s", pnode->path, name); + ret = TEMP_FAILURE_RETRY (fstatat (it->fd, whpath, &st, AT_SYMLINK_NOFOLLOW)); + if (ret < 0 && errno != ENOENT) + return NULL; + if (ret == 0) + node = make_whiteout_node (path, name); else - node = make_ovl_node (path, it, name, 0, st.st_mode & S_IFDIR, pnode); + { + wh_name = get_whiteout_name (name, &st); + if (wh_name) + node = make_whiteout_node (path, wh_name); + else + node = make_ovl_node (path, it, name, 0, st.st_mode & S_IFDIR, pnode); + } if (node == NULL) { errno = ENOMEM;