mirror of
https://github.com/containers/fuse-overlayfs.git
synced 2025-09-08 06:42:27 -04:00
main: use extended override xattr
Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
This commit is contained in:
parent
8d33894c48
commit
6bbd62bb13
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);
|
||||||
|
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