From 791dd18e4d070d61af8826ade6cafaa6be400947 Mon Sep 17 00:00:00 2001 From: Akihiko Odaki Date: Mon, 10 Jun 2024 17:19:19 +0900 Subject: [PATCH] Prefer user.containers.override_stat over user.fuseoverlayfs. Previously, fuse-overlayfs always used user.fuseoverlayfs.override_stat for the upper layer while honoring user.containers.override_stat for lower layers so that it can consume a layer created by containers/storage. It turned out that containers/storage also needs to get the overriding extended attribute set by fuse-overlayfs and to set one for the upper layer to make the root directory of the upper layer inherit the mode of a lower layer. Adding code to get and to set user.fuseoverlayfs.override_stat to containers/storage is a bit ugly. The underlying problem is that fuse-overlayfs changes what name to use ad hoc. Fix it by always preferring user.containers.override_stat, which containers/storage honors, over user.fuseoverlayfs.overlayfs, which is specific to fuse-overlayfs. Signed-off-by: Akihiko Odaki --- contrib/fix-mode.py | 4 ++-- direct.c | 4 ++-- main.c | 43 ++++++++++++++++++++++++++++++------------- 3 files changed, 34 insertions(+), 17 deletions(-) diff --git a/contrib/fix-mode.py b/contrib/fix-mode.py index 533002a..ed0e024 100755 --- a/contrib/fix-mode.py +++ b/contrib/fix-mode.py @@ -6,12 +6,12 @@ import errno XATTR_OVERRIDE_STAT_PRIVILEGED = "security.fuseoverlayfs.override_stat" -XATTR_OVERRIDE_STAT = "user.fuseoverlayfs.override_stat" +XATTR_OVERRIDE_CONTAINERS_STAT = "user.fuseoverlayfs.override_stat" if os.geteuid() == 0: xattr_name = XATTR_OVERRIDE_STAT_PRIVILEGED else: - xattr_name = XATTR_OVERRIDE_STAT + xattr_name = XATTR_OVERRIDE_CONTAINERS_STAT cwd_fd = os.open(".", os.O_PATH) diff --git a/direct.c b/direct.c index a1a5d7d..272631f 100644 --- a/direct.c +++ b/direct.c @@ -186,10 +186,10 @@ direct_load_data_source (struct ovl_layer *l, const char *opaque, const char *pa if (fgetxattr (l->fd, XATTR_PRIVILEGED_OVERRIDE_STAT, tmp, sizeof (tmp)) >= 0) l->stat_override_mode = STAT_OVERRIDE_PRIVILEGED; - else if (fgetxattr (l->fd, XATTR_OVERRIDE_STAT, tmp, sizeof (tmp)) >= 0) - l->stat_override_mode = STAT_OVERRIDE_USER; else if (fgetxattr (l->fd, XATTR_OVERRIDE_CONTAINERS_STAT, tmp, sizeof (tmp)) >= 0) l->stat_override_mode = STAT_OVERRIDE_CONTAINERS; + else if (fgetxattr (l->fd, XATTR_OVERRIDE_STAT, tmp, sizeof (tmp)) >= 0) + l->stat_override_mode = STAT_OVERRIDE_USER; return 0; } diff --git a/main.c b/main.c index 5bd1993..85abb01 100644 --- a/main.c +++ b/main.c @@ -539,17 +539,21 @@ write_permission_xattr (struct ovl_data *lo, int fd, const char *path, uid_t uid int ret; const char *name = NULL; - switch (lo->xattr_permissions) + switch (get_upper_layer (lo)->stat_override_mode) { - case 0: + case STAT_OVERRIDE_NONE: return 0; - case 1: + case STAT_OVERRIDE_USER: + name = XATTR_OVERRIDE_STAT; + break; + + case STAT_OVERRIDE_PRIVILEGED: name = XATTR_PRIVILEGED_OVERRIDE_STAT; break; - case 2: - name = XATTR_OVERRIDE_STAT; + case STAT_OVERRIDE_CONTAINERS: + name = XATTR_OVERRIDE_CONTAINERS_STAT; break; default: @@ -5792,13 +5796,22 @@ main (int argc, char *argv[]) } else if (lo.xattr_permissions == 2) { - get_upper_layer (&lo)->stat_override_mode = STAT_OVERRIDE_USER; - name = XATTR_OVERRIDE_STAT; + get_upper_layer (&lo)->stat_override_mode = STAT_OVERRIDE_CONTAINERS; + name = XATTR_OVERRIDE_CONTAINERS_STAT; } else error (EXIT_FAILURE, 0, "invalid value for xattr_permissions"); s = fgetxattr (get_upper_layer (&lo)->fd, name, data, sizeof (data)); + if (s < 0 && errno == ENODATA && lo.xattr_permissions == 2) + { + s = fgetxattr (get_upper_layer (&lo)->fd, XATTR_OVERRIDE_STAT, data, sizeof (data)); + if (s >= 0) + { + get_upper_layer (&lo)->stat_override_mode = STAT_OVERRIDE_USER; + name = XATTR_OVERRIDE_STAT; + } + } if (s < 0) { bool found = false; @@ -5809,15 +5822,19 @@ main (int argc, char *argv[]) for (l = get_lower_layers (&lo); l; l = l->next) { - s = fgetxattr (l->fd, name, data, sizeof (data)); - if (s < 0 && errno != ENODATA) - error (EXIT_FAILURE, errno, "fgetxattr mode from lower layer"); - if (s < 0 && lo.xattr_permissions == 2) + switch (lo.xattr_permissions) { + case 1: + s = fgetxattr (l->fd, name, data, sizeof (data)); + break; + + case 2: s = fgetxattr (l->fd, XATTR_OVERRIDE_CONTAINERS_STAT, data, sizeof (data)); - if (s < 0 && errno != ENODATA) - error (EXIT_FAILURE, errno, "fgetxattr mode from lower layer"); + if (s < 0 && errno == ENODATA) + s = fgetxattr (l->fd, XATTR_OVERRIDE_STAT, data, sizeof (data)); + break; } + if (s > 0) { ret = fsetxattr (get_upper_layer (&lo)->fd, name, data, s, 0);