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
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)

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)
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;
}

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;
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);