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 <odaki@rsg.ci.i.u-tokyo.ac.jp>
This commit is contained in:
Akihiko Odaki 2024-06-10 17:19:19 +09:00
parent e16818c042
commit 90bea22c73
3 changed files with 34 additions and 17 deletions

View File

@ -6,12 +6,12 @@ import stat
import errno import errno
XATTR_OVERRIDE_STAT_PRIVILEGED = "security.fuseoverlayfs.override_stat" 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: if os.geteuid() == 0:
xattr_name = XATTR_OVERRIDE_STAT_PRIVILEGED xattr_name = XATTR_OVERRIDE_STAT_PRIVILEGED
else: else:
xattr_name = XATTR_OVERRIDE_STAT xattr_name = XATTR_OVERRIDE_CONTAINERS_STAT
cwd_fd = os.open(".", os.O_PATH) cwd_fd = os.open(".", os.O_PATH)

View File

@ -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) if (fgetxattr (l->fd, XATTR_PRIVILEGED_OVERRIDE_STAT, tmp, sizeof (tmp)) >= 0)
l->stat_override_mode = STAT_OVERRIDE_PRIVILEGED; 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) else if (fgetxattr (l->fd, XATTR_OVERRIDE_CONTAINERS_STAT, tmp, sizeof (tmp)) >= 0)
l->stat_override_mode = STAT_OVERRIDE_CONTAINERS; 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; return 0;
} }

43
main.c
View File

@ -539,17 +539,21 @@ write_permission_xattr (struct ovl_data *lo, int fd, const char *path, uid_t uid
int ret; int ret;
const char *name = NULL; const char *name = NULL;
switch (lo->xattr_permissions) switch (get_upper_layer (lo)->stat_override_mode)
{ {
case 0: case STAT_OVERRIDE_NONE:
return 0; return 0;
case 1: case STAT_OVERRIDE_USER:
name = XATTR_OVERRIDE_STAT;
break;
case STAT_OVERRIDE_PRIVILEGED:
name = XATTR_PRIVILEGED_OVERRIDE_STAT; name = XATTR_PRIVILEGED_OVERRIDE_STAT;
break; break;
case 2: case STAT_OVERRIDE_CONTAINERS:
name = XATTR_OVERRIDE_STAT; name = XATTR_OVERRIDE_CONTAINERS_STAT;
break; break;
default: default:
@ -5792,13 +5796,22 @@ main (int argc, char *argv[])
} }
else if (lo.xattr_permissions == 2) else if (lo.xattr_permissions == 2)
{ {
get_upper_layer (&lo)->stat_override_mode = STAT_OVERRIDE_USER; get_upper_layer (&lo)->stat_override_mode = STAT_OVERRIDE_CONTAINERS;
name = XATTR_OVERRIDE_STAT; name = XATTR_OVERRIDE_CONTAINERS_STAT;
} }
else else
error (EXIT_FAILURE, 0, "invalid value for xattr_permissions"); error (EXIT_FAILURE, 0, "invalid value for xattr_permissions");
s = fgetxattr (get_upper_layer (&lo)->fd, name, data, sizeof (data)); 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) if (s < 0)
{ {
bool found = false; bool found = false;
@ -5809,15 +5822,19 @@ main (int argc, char *argv[])
for (l = get_lower_layers (&lo); l; l = l->next) for (l = get_lower_layers (&lo); l; l = l->next)
{ {
s = fgetxattr (l->fd, name, data, sizeof (data)); switch (lo.xattr_permissions)
if (s < 0 && errno != ENODATA)
error (EXIT_FAILURE, errno, "fgetxattr mode from lower layer");
if (s < 0 && lo.xattr_permissions == 2)
{ {
case 1:
s = fgetxattr (l->fd, name, data, sizeof (data));
break;
case 2:
s = fgetxattr (l->fd, XATTR_OVERRIDE_CONTAINERS_STAT, data, sizeof (data)); s = fgetxattr (l->fd, XATTR_OVERRIDE_CONTAINERS_STAT, data, sizeof (data));
if (s < 0 && errno != ENODATA) if (s < 0 && errno == ENODATA)
error (EXIT_FAILURE, errno, "fgetxattr mode from lower layer"); s = fgetxattr (l->fd, XATTR_OVERRIDE_STAT, data, sizeof (data));
break;
} }
if (s > 0) if (s > 0)
{ {
ret = fsetxattr (get_upper_layer (&lo)->fd, name, data, s, 0); ret = fsetxattr (get_upper_layer (&lo)->fd, name, data, s, 0);