Skip to content

Commit

Permalink
Merge pull request #434 from giuseppe/use-extended-override-xattr
Browse files Browse the repository at this point in the history
main: use extended override xattr
  • Loading branch information
rhatdan authored Dec 2, 2024
2 parents ab0b0f6 + 6bbd62b commit a54a9f2
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 61 deletions.
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/checkout@v2.1.0
- 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

0 comments on commit a54a9f2

Please sign in to comment.