mirror of
https://github.com/containers/fuse-overlayfs.git
synced 2025-09-07 22:31:21 -04:00
Merge pull request #434 from giuseppe/use-extended-override-xattr
main: use extended override xattr
This commit is contained in:
commit
a54a9f2e88
2
.github/workflows/release.yaml
vendored
2
.github/workflows/release.yaml
vendored
@ -5,7 +5,7 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
release:
|
release:
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
|
16
.github/workflows/test.yaml
vendored
16
.github/workflows/test.yaml
vendored
@ -4,23 +4,23 @@ on: [push, pull_request]
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build_job:
|
build_job:
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-latest
|
||||||
name: Build on ${{ matrix.arch }}
|
name: Build on ${{ matrix.arch }}
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- arch: armv7
|
- arch: armv7
|
||||||
distro: ubuntu22.04
|
distro: ubuntu_latest
|
||||||
- arch: aarch64
|
- arch: aarch64
|
||||||
distro: ubuntu22.04
|
distro: ubuntu_latest
|
||||||
- arch: s390x
|
- arch: s390x
|
||||||
distro: ubuntu22.04
|
distro: ubuntu_latest
|
||||||
- arch: ppc64le
|
- arch: ppc64le
|
||||||
distro: ubuntu22.04
|
distro: ubuntu_latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2.1.0
|
- 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
|
name: Build
|
||||||
id: build
|
id: build
|
||||||
with:
|
with:
|
||||||
@ -49,7 +49,7 @@ jobs:
|
|||||||
fuse-overlayfs
|
fuse-overlayfs
|
||||||
|
|
||||||
Test:
|
Test:
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
@ -90,7 +90,7 @@ jobs:
|
|||||||
- name: Archive build artifacts
|
- name: Archive build artifacts
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: fuse-overlayfs-x86_64-ubuntu22.04
|
name: fuse-overlayfs-x86_64-ubuntu-latest
|
||||||
path: |
|
path: |
|
||||||
fuse-overlayfs
|
fuse-overlayfs
|
||||||
if: ${{ matrix.test == 'ovl-whiteouts' }}
|
if: ${{ matrix.test == 'ovl-whiteouts' }}
|
||||||
|
72
main.c
72
main.c
@ -508,43 +508,26 @@ node_dirfd (struct ovl_node *n)
|
|||||||
return n->layer->fd;
|
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
|
static bool
|
||||||
can_access_xattr (const struct ovl_layer *l, const char *name)
|
can_access_xattr (const struct ovl_layer *l, const char *name)
|
||||||
{
|
{
|
||||||
return ! (has_prefix (name, XATTR_PREFIX)
|
return ! (has_prefix (name, XATTR_PREFIX)
|
||||||
|| has_prefix (name, PRIVILEGED_XATTR_PREFIX)
|
|| has_prefix (name, PRIVILEGED_XATTR_PREFIX)
|
||||||
|| has_prefix (name, UNPRIVILEGED_XATTR_PREFIX)
|
|| has_prefix (name, UNPRIVILEGED_XATTR_PREFIX)
|
||||||
|| (l->stat_override_mode == STAT_OVERRIDE_CONTAINERS &&
|
|| (l->stat_override_mode == STAT_OVERRIDE_CONTAINERS && has_prefix (name, XATTR_SECURITY_PREFIX)));
|
||||||
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) &&
|
return has_prefix (name, XATTR_CONTAINERS_OVERRIDE_PREFIX) && ! can_access_xattr (l, name + sizeof (XATTR_CONTAINERS_OVERRIDE_PREFIX) - 1);
|
||||||
! 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))
|
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))
|
if (can_access_xattr (l, name))
|
||||||
return name;
|
return name;
|
||||||
@ -552,18 +535,18 @@ static const char *decode_xattr_name (const struct ovl_layer *l, const char *nam
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *encode_xattr_name (const struct ovl_layer *l, char *buf,
|
static const char *
|
||||||
const char *name)
|
encode_xattr_name (const struct ovl_layer *l, char *buf,
|
||||||
|
const char *name)
|
||||||
{
|
{
|
||||||
if (can_access_xattr (l, name))
|
if (can_access_xattr (l, name))
|
||||||
return name;
|
return name;
|
||||||
|
|
||||||
if (l->stat_override_mode != STAT_OVERRIDE_CONTAINERS ||
|
if (l->stat_override_mode != STAT_OVERRIDE_CONTAINERS || strlen (name) > XATTR_NAME_MAX + 1 - sizeof (XATTR_CONTAINERS_OVERRIDE_PREFIX))
|
||||||
strlen(name) > XATTR_NAME_MAX + 1 - sizeof(XATTR_CONTAINERS_OVERRIDE_PREFIX))
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
strcpy(buf, XATTR_CONTAINERS_OVERRIDE_PREFIX);
|
strcpy (buf, XATTR_CONTAINERS_OVERRIDE_PREFIX);
|
||||||
strcpy(buf + sizeof(XATTR_CONTAINERS_OVERRIDE_PREFIX) - 1, name);
|
strcpy (buf + sizeof (XATTR_CONTAINERS_OVERRIDE_PREFIX) - 1, name);
|
||||||
|
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
@ -2645,8 +2628,7 @@ filter_xattrs_list (struct ovl_layer *l, char *buf, ssize_t len)
|
|||||||
{
|
{
|
||||||
char *next = it;
|
char *next = it;
|
||||||
|
|
||||||
next += encoded_xattr_name (l, it) ?
|
next += encoded_xattr_name (l, it) ? sizeof (XATTR_CONTAINERS_OVERRIDE_PREFIX) - 1 : it_len;
|
||||||
sizeof(XATTR_CONTAINERS_OVERRIDE_PREFIX) - 1 : it_len;
|
|
||||||
|
|
||||||
memmove (it, next, buf + len - next);
|
memmove (it, next, buf + len - next);
|
||||||
len -= it_len;
|
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);
|
name = encode_xattr_name (node->layer, name_buf, name);
|
||||||
if (!name)
|
if (! name)
|
||||||
{
|
{
|
||||||
fuse_reply_err (req, ENODATA);
|
fuse_reply_err (req, ENODATA);
|
||||||
return;
|
return;
|
||||||
@ -3551,12 +3533,12 @@ ovl_setxattr (fuse_req_t req, fuse_ino_t ino, const char *name,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
name = encode_xattr_name (node->layer, name_buf, name);
|
name = encode_xattr_name (node->layer, name_buf, name);
|
||||||
if (!name)
|
if (! name)
|
||||||
{
|
{
|
||||||
fuse_reply_err (req, EPERM);
|
fuse_reply_err (req, EPERM);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! node->hidden)
|
if (! node->hidden)
|
||||||
ret = direct_setxattr (node->layer, node->path, name, value, size, flags);
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
name = encode_xattr_name (node->layer, name_buf, name);
|
name = encode_xattr_name (node->layer, name_buf, name);
|
||||||
if (!name)
|
if (! name)
|
||||||
{
|
{
|
||||||
fuse_reply_err (req, EPERM);
|
fuse_reply_err (req, EPERM);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! node->hidden)
|
if (! node->hidden)
|
||||||
ret = direct_removexattr (node->layer, node->path, name);
|
ret = direct_removexattr (node->layer, node->path, name);
|
||||||
|
@ -6,7 +6,7 @@ mkdir lower upper workdir merged
|
|||||||
|
|
||||||
fuse-overlayfs -o sync=0,lowerdir=lower,upperdir=upper,workdir=workdir,suid,dev 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
|
umount merged
|
||||||
|
|
||||||
@ -30,7 +30,7 @@ stat -c %A upper/suid | grep s
|
|||||||
stat -c %a upper/nosuid | grep -v s
|
stat -c %a upper/nosuid | grep -v s
|
||||||
|
|
||||||
# Install some big packages
|
# 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/'
|
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
|
# fast_ino_check
|
||||||
fuse-overlayfs -o fast_ino_check=1,sync=0,lowerdir=lower,upperdir=upper,workdir=workdir,suid,dev merged
|
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
|
mkdir merged/a-directory
|
||||||
|
|
||||||
|
84
utils.c
84
utils.c
@ -224,16 +224,38 @@ open_fd_or_get_path (struct ovl_layer *l, const char *path, char *out, int *fd,
|
|||||||
return *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
|
int
|
||||||
override_mode (struct ovl_layer *l, int fd, const char *abs_path, const char *path, struct stat *st)
|
override_mode (struct ovl_layer *l, int fd, const char *abs_path, const char *path, struct stat *st)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
uid_t uid;
|
uid_t uid;
|
||||||
gid_t gid;
|
gid_t gid;
|
||||||
mode_t mode;
|
mode_t mode = 0;
|
||||||
char buf[64];
|
char buf[64];
|
||||||
cleanup_close int cleanup_fd = -1;
|
cleanup_close int cleanup_fd = -1;
|
||||||
const char *xattr_name;
|
const char *xattr_name;
|
||||||
|
cleanup_free char *type = NULL;
|
||||||
|
|
||||||
switch (st->st_mode & S_IFMT)
|
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';
|
buf[ret] = '\0';
|
||||||
|
|
||||||
ret = sscanf (buf, "%d:%d:%o", &uid, &gid, &mode);
|
ret = sscanf (buf, "%d:%d:%o:%ms", &uid, &gid, &mode, &type);
|
||||||
if (ret != 3)
|
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;
|
errno = EINVAL;
|
||||||
return -1;
|
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_uid = uid;
|
||||||
st->st_gid = gid;
|
st->st_gid = gid;
|
||||||
st->st_mode = (st->st_mode & S_IFMT) | mode;
|
st->st_mode = mode;
|
||||||
|
|
||||||
return 0;
|
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
utils.h
2
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);
|
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
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user