diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 73b0741..e22d4bf 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -5,7 +5,7 @@ on: jobs: release: - runs-on: ubuntu-22.04 + runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 5bc3a69..155279b 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -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: @@ -49,7 +49,7 @@ jobs: fuse-overlayfs Test: - runs-on: ubuntu-22.04 + runs-on: ubuntu-latest strategy: fail-fast: false matrix: @@ -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' }} diff --git a/main.c b/main.c index 965f8f4..f0f24a6 100644 --- a/main.c +++ b/main.c @@ -508,43 +508,26 @@ 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; @@ -552,18 +535,18 @@ static const char *decode_xattr_name (const struct ovl_layer *l, const char *nam 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; } @@ -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; @@ -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; @@ -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); @@ -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); diff --git a/tests/fedora-installs.sh b/tests/fedora-installs.sh index 8a30fdf..6eaecfb 100755 --- a/tests/fedora-installs.sh +++ b/tests/fedora-installs.sh @@ -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 @@ -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/' @@ -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 diff --git a/utils.c b/utils.c index fbe06a4..b9317bb 100644 --- a/utils.c +++ b/utils.c @@ -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) { @@ -296,8 +318,45 @@ 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; @@ -305,7 +364,24 @@ override_mode (struct ovl_layer *l, int fd, const char *abs_path, const char *pa 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; +} diff --git a/utils.h b/utils.h index a9176f9..284b451 100644 --- a/utils.h +++ b/utils.h @@ -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