Skip to content

Commit

Permalink
main: use extended override xattr
Browse files Browse the repository at this point in the history
Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
  • Loading branch information
giuseppe committed Dec 2, 2024
1 parent c677155 commit f899cee
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 49 deletions.
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
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 f899cee

Please sign in to comment.