Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

main: use extended override xattr #434

Merged
merged 4 commits into from
Dec 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ on:

jobs:
release:
runs-on: ubuntu-22.04
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
Expand Down
16 changes: 8 additions & 8 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,23 @@ on: [push, pull_request]

jobs:
build_job:
runs-on: ubuntu-22.04
runs-on: ubuntu-latest
name: Build on ${{ matrix.arch }}

strategy:
matrix:
include:
- arch: armv7
distro: ubuntu22.04
distro: ubuntu_latest
- arch: aarch64
distro: ubuntu22.04
distro: ubuntu_latest
- arch: s390x
distro: ubuntu22.04
distro: ubuntu_latest
- arch: ppc64le
distro: ubuntu22.04
distro: ubuntu_latest
steps:
- uses: actions/[email protected]
- uses: uraimo/run-on-arch-action@v2.7.2
- uses: uraimo/run-on-arch-action@v2.8.1
name: Build
id: build
with:
Expand Down Expand Up @@ -49,7 +49,7 @@ jobs:
fuse-overlayfs

Test:
runs-on: ubuntu-22.04
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
Expand Down Expand Up @@ -90,7 +90,7 @@ jobs:
- name: Archive build artifacts
uses: actions/upload-artifact@v3
with:
name: fuse-overlayfs-x86_64-ubuntu22.04
name: fuse-overlayfs-x86_64-ubuntu-latest
path: |
fuse-overlayfs
if: ${{ matrix.test == 'ovl-whiteouts' }}
Expand Down
72 changes: 27 additions & 45 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -508,62 +508,45 @@ node_dirfd (struct ovl_node *n)
return n->layer->fd;
}

static bool
has_prefix (const char *str, const char *pref)
{
while (1)
{
if (*pref == '\0')
return true;
if (*str == '\0')
return false;
if (*pref != *str)
return false;
str++;
pref++;
}
return false;
}

static bool
can_access_xattr (const struct ovl_layer *l, const char *name)
{
return ! (has_prefix (name, XATTR_PREFIX)
|| has_prefix (name, PRIVILEGED_XATTR_PREFIX)
|| has_prefix (name, UNPRIVILEGED_XATTR_PREFIX)
|| (l->stat_override_mode == STAT_OVERRIDE_CONTAINERS &&
has_prefix (name, XATTR_SECURITY_PREFIX)));
|| (l->stat_override_mode == STAT_OVERRIDE_CONTAINERS && has_prefix (name, XATTR_SECURITY_PREFIX)));
}

static bool encoded_xattr_name (const struct ovl_layer *l, const char *name)
static bool
encoded_xattr_name (const struct ovl_layer *l, const char *name)
{
return has_prefix (name, XATTR_CONTAINERS_OVERRIDE_PREFIX) &&
! can_access_xattr (l, name + sizeof(XATTR_CONTAINERS_OVERRIDE_PREFIX) - 1);
return has_prefix (name, XATTR_CONTAINERS_OVERRIDE_PREFIX) && ! can_access_xattr (l, name + sizeof (XATTR_CONTAINERS_OVERRIDE_PREFIX) - 1);
}

static const char *decode_xattr_name (const struct ovl_layer *l, const char *name)
static const char *
decode_xattr_name (const struct ovl_layer *l, const char *name)
{
if (encoded_xattr_name (l, name))
return name + sizeof(XATTR_CONTAINERS_OVERRIDE_PREFIX) - 1;
return name + sizeof (XATTR_CONTAINERS_OVERRIDE_PREFIX) - 1;

if (can_access_xattr (l, name))
return name;

return NULL;
}

static const char *encode_xattr_name (const struct ovl_layer *l, char *buf,
const char *name)
static const char *
encode_xattr_name (const struct ovl_layer *l, char *buf,
const char *name)
{
if (can_access_xattr (l, name))
return name;

if (l->stat_override_mode != STAT_OVERRIDE_CONTAINERS ||
strlen(name) > XATTR_NAME_MAX + 1 - sizeof(XATTR_CONTAINERS_OVERRIDE_PREFIX))
if (l->stat_override_mode != STAT_OVERRIDE_CONTAINERS || strlen (name) > XATTR_NAME_MAX + 1 - sizeof (XATTR_CONTAINERS_OVERRIDE_PREFIX))
return NULL;

strcpy(buf, XATTR_CONTAINERS_OVERRIDE_PREFIX);
strcpy(buf + sizeof(XATTR_CONTAINERS_OVERRIDE_PREFIX) - 1, name);
strcpy (buf, XATTR_CONTAINERS_OVERRIDE_PREFIX);
strcpy (buf + sizeof (XATTR_CONTAINERS_OVERRIDE_PREFIX) - 1, name);

return buf;
}
Expand Down Expand Up @@ -2645,8 +2628,7 @@ filter_xattrs_list (struct ovl_layer *l, char *buf, ssize_t len)
{
char *next = it;

next += encoded_xattr_name (l, it) ?
sizeof(XATTR_CONTAINERS_OVERRIDE_PREFIX) - 1 : it_len;
next += encoded_xattr_name (l, it) ? sizeof (XATTR_CONTAINERS_OVERRIDE_PREFIX) - 1 : it_len;

memmove (it, next, buf + len - next);
len -= it_len;
Expand Down Expand Up @@ -2742,7 +2724,7 @@ ovl_getxattr (fuse_req_t req, fuse_ino_t ino, const char *name, size_t size)
}

name = encode_xattr_name (node->layer, name_buf, name);
if (!name)
if (! name)
{
fuse_reply_err (req, ENODATA);
return;
Expand Down Expand Up @@ -3551,12 +3533,12 @@ ovl_setxattr (fuse_req_t req, fuse_ino_t ino, const char *name,
return;
}

name = encode_xattr_name (node->layer, name_buf, name);
if (!name)
{
fuse_reply_err (req, EPERM);
return;
}
name = encode_xattr_name (node->layer, name_buf, name);
if (! name)
{
fuse_reply_err (req, EPERM);
return;
}

if (! node->hidden)
ret = direct_setxattr (node->layer, node->path, name, value, size, flags);
Expand Down Expand Up @@ -3619,12 +3601,12 @@ ovl_removexattr (fuse_req_t req, fuse_ino_t ino, const char *name)
return;
}

name = encode_xattr_name (node->layer, name_buf, name);
if (!name)
{
fuse_reply_err (req, EPERM);
return;
}
name = encode_xattr_name (node->layer, name_buf, name);
if (! name)
{
fuse_reply_err (req, EPERM);
return;
}

if (! node->hidden)
ret = direct_removexattr (node->layer, node->path, name);
Expand Down
6 changes: 3 additions & 3 deletions tests/fedora-installs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ mkdir lower upper workdir merged

fuse-overlayfs -o sync=0,lowerdir=lower,upperdir=upper,workdir=workdir,suid,dev merged

docker run --rm -v $(pwd)/merged:/merged fedora dnf --installroot /merged --releasever 30 install -y glibc-common gedit
docker run --rm -v $(pwd)/merged:/merged fedora dnf --use-host-config --installroot /merged --releasever 41 install -y glibc-common gedit

umount merged

Expand All @@ -30,7 +30,7 @@ stat -c %A upper/suid | grep s
stat -c %a upper/nosuid | grep -v s

# Install some big packages
docker run --rm -v $(pwd)/merged:/merged fedora dnf --installroot /merged --releasever 30 install -y emacs texlive
docker run --rm -v $(pwd)/merged:/merged fedora dnf --use-host-config --installroot /merged --releasever 41 install -y emacs texlive

docker run --rm -v $(pwd)/merged:/merged fedora sh -c 'rm /merged/usr/share/glib-2.0/schemas/gschemas.compiled; glib-compile-schemas /merged/usr/share/glib-2.0/schemas/'

Expand All @@ -48,7 +48,7 @@ mkdir upper workdir lower
# fast_ino_check
fuse-overlayfs -o fast_ino_check=1,sync=0,lowerdir=lower,upperdir=upper,workdir=workdir,suid,dev merged

docker run --rm -v $(pwd)/merged:/merged fedora dnf --installroot /merged --releasever 30 install -y glibc-common gedit
docker run --rm -v $(pwd)/merged:/merged fedora dnf --use-host-config --installroot /merged --releasever 41 install -y glibc-common gedit

mkdir merged/a-directory

Expand Down
84 changes: 80 additions & 4 deletions utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -224,16 +224,38 @@ open_fd_or_get_path (struct ovl_layer *l, const char *path, char *out, int *fd,
return *fd;
}

int
read_device (const char *s, dev_t *dev)
{
unsigned int major, minor;
int ret;

while (*s == '-')
s++;

ret = sscanf (s, "%u-%u", &major, &minor);
if (ret != 2)
{
errno = EINVAL;
return -1;
}

*dev = makedev (major, minor);

return 0;
}

int
override_mode (struct ovl_layer *l, int fd, const char *abs_path, const char *path, struct stat *st)
{
int ret;
uid_t uid;
gid_t gid;
mode_t mode;
mode_t mode = 0;
char buf[64];
cleanup_close int cleanup_fd = -1;
const char *xattr_name;
cleanup_free char *type = NULL;

switch (st->st_mode & S_IFMT)
{
Expand Down Expand Up @@ -296,16 +318,70 @@ override_mode (struct ovl_layer *l, int fd, const char *abs_path, const char *pa

buf[ret] = '\0';

ret = sscanf (buf, "%d:%d:%o", &uid, &gid, &mode);
if (ret != 3)
ret = sscanf (buf, "%d:%d:%o:%ms", &uid, &gid, &mode, &type);
if (ret == 4)
{
if (has_prefix (type, "dir"))
mode |= S_IFDIR;
else if (has_prefix (type, "file"))
mode |= S_IFREG;
else if (has_prefix (type, "symlink"))
mode |= S_IFLNK;
else if (has_prefix (type, "pipe"))
mode |= S_IFIFO;
else if (has_prefix (type, "socket"))
mode |= S_IFSOCK;
else if (has_prefix (type, "block"))
{
mode |= S_IFBLK;
ret = read_device (type + strlen ("block"), &st->st_rdev);
if (ret < 0)
return ret;
}
else if (has_prefix (type, "char"))
{
mode |= S_IFCHR;
ret = read_device (type + strlen ("char"), &st->st_rdev);
if (ret < 0)
return ret;
}
else
{
errno = EINVAL;
return -1;
}
}
else if (ret == 3)
{
/* If a type is not specified, keep the original one. */
mode |= (st->st_mode & S_IFMT);
}
else
{
errno = EINVAL;
return -1;
}

st->st_uid = uid;
st->st_gid = gid;
st->st_mode = (st->st_mode & S_IFMT) | mode;
st->st_mode = mode;

return 0;
}

bool
has_prefix (const char *str, const char *pref)
{
while (1)
{
if (*pref == '\0')
return true;
if (*str == '\0')
return false;
if (*pref != *str)
return false;
str++;
pref++;
}
return false;
}
2 changes: 2 additions & 0 deletions utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,6 @@ int safe_openat (int dirfd, const char *pathname, int flags, mode_t mode);

int override_mode (struct ovl_layer *l, int fd, const char *abs_path, const char *path, struct stat *st);

bool has_prefix (const char *str, const char *pref);

#endif
Loading