mirror of
https://gitlab.com/qemu-project/qemu
synced 2024-11-05 20:35:44 +00:00
tools/virtiofsd: xattr name mappings: Simple 'map'
The mapping rule system implemented in the last few patches is extremely flexible, but not easy to use. Add a simple 'map' type as a sprinkling of sugar to make it easy. e.g. -o xattrmap=":map::user.virtiofs.:" would be sufficient to prefix all xattr's or -o xattrmap=":map:trusted.:user.virtiofs.:" would just prefix 'trusted.' xattr's and leave everything else alone. Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com> Message-Id: <20201023165812.36028-6-dgilbert@redhat.com> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
This commit is contained in:
parent
491bfaea3b
commit
1d84a0213a
2 changed files with 130 additions and 1 deletions
|
@ -147,6 +147,7 @@ Each rule consists of a number of fields separated with a separator that is the
|
||||||
first non-white space character in the rule. This separator must then be used
|
first non-white space character in the rule. This separator must then be used
|
||||||
for the whole rule.
|
for the whole rule.
|
||||||
White space may be added before and after each rule.
|
White space may be added before and after each rule.
|
||||||
|
|
||||||
Using ':' as the separator a rule is of the form:
|
Using ':' as the separator a rule is of the form:
|
||||||
|
|
||||||
``:type:scope:key:prepend:``
|
``:type:scope:key:prepend:``
|
||||||
|
@ -219,6 +220,14 @@ e.g.:
|
||||||
|
|
||||||
would hide 'security.' xattr's in listxattr from the server.
|
would hide 'security.' xattr's in listxattr from the server.
|
||||||
|
|
||||||
|
A simpler 'map' type provides a shorter syntax for the common case:
|
||||||
|
|
||||||
|
``:map:key:prepend:``
|
||||||
|
|
||||||
|
The 'map' type adds a number of separate rules to add **prepend** as a prefix
|
||||||
|
to the matched **key** (or all attributes if **key** is empty).
|
||||||
|
There may be at most one 'map' rule and it must be the last rule in the set.
|
||||||
|
|
||||||
xattr-mapping Examples
|
xattr-mapping Examples
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
|
@ -234,6 +243,11 @@ the first rule prefixes and strips 'user.virtiofs.',
|
||||||
the second rule hides any non-prefixed attributes that
|
the second rule hides any non-prefixed attributes that
|
||||||
the host set.
|
the host set.
|
||||||
|
|
||||||
|
This is equivalent to the 'map' rule:
|
||||||
|
|
||||||
|
::
|
||||||
|
-o xattrmap=":map::user.virtiofs.:"
|
||||||
|
|
||||||
2) Prefix 'trusted.' attributes, allow others through
|
2) Prefix 'trusted.' attributes, allow others through
|
||||||
|
|
||||||
::
|
::
|
||||||
|
@ -256,6 +270,11 @@ the 'user.virtiofs.' path directly.
|
||||||
Finally, the fourth rule lets all remaining attributes
|
Finally, the fourth rule lets all remaining attributes
|
||||||
through.
|
through.
|
||||||
|
|
||||||
|
This is equivalent to the 'map' rule:
|
||||||
|
|
||||||
|
::
|
||||||
|
-o xattrmap="/map/trusted./user.virtiofs./"
|
||||||
|
|
||||||
3) Hide 'security.' attributes, and allow everything else
|
3) Hide 'security.' attributes, and allow everything else
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
|
@ -2090,6 +2090,109 @@ static void free_xattrmap(struct lo_data *lo)
|
||||||
lo->xattr_map_nentries = -1;
|
lo->xattr_map_nentries = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handle the 'map' type, which is sugar for a set of commands
|
||||||
|
* for the common case of prefixing a subset or everything,
|
||||||
|
* and allowing anything not prefixed through.
|
||||||
|
* It must be the last entry in the stream, although there
|
||||||
|
* can be other entries before it.
|
||||||
|
* The form is:
|
||||||
|
* :map:key:prefix:
|
||||||
|
*
|
||||||
|
* key maybe empty in which case all entries are prefixed.
|
||||||
|
*/
|
||||||
|
static void parse_xattrmap_map(struct lo_data *lo,
|
||||||
|
const char *rule, char sep)
|
||||||
|
{
|
||||||
|
const char *tmp;
|
||||||
|
char *key;
|
||||||
|
char *prefix;
|
||||||
|
XattrMapEntry tmp_entry;
|
||||||
|
|
||||||
|
if (*rule != sep) {
|
||||||
|
fuse_log(FUSE_LOG_ERR,
|
||||||
|
"%s: Expecting '%c' after 'map' keyword, found '%c'\n",
|
||||||
|
__func__, sep, *rule);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
rule++;
|
||||||
|
|
||||||
|
/* At start of 'key' field */
|
||||||
|
tmp = strchr(rule, sep);
|
||||||
|
if (!tmp) {
|
||||||
|
fuse_log(FUSE_LOG_ERR,
|
||||||
|
"%s: Missing '%c' at end of key field in map rule\n",
|
||||||
|
__func__, sep);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
key = g_strndup(rule, tmp - rule);
|
||||||
|
rule = tmp + 1;
|
||||||
|
|
||||||
|
/* At start of prefix field */
|
||||||
|
tmp = strchr(rule, sep);
|
||||||
|
if (!tmp) {
|
||||||
|
fuse_log(FUSE_LOG_ERR,
|
||||||
|
"%s: Missing '%c' at end of prefix field in map rule\n",
|
||||||
|
__func__, sep);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
prefix = g_strndup(rule, tmp - rule);
|
||||||
|
rule = tmp + 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This should be the end of the string, we don't allow
|
||||||
|
* any more commands after 'map'.
|
||||||
|
*/
|
||||||
|
if (*rule) {
|
||||||
|
fuse_log(FUSE_LOG_ERR,
|
||||||
|
"%s: Expecting end of command after map, found '%c'\n",
|
||||||
|
__func__, *rule);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 1st: Prefix matches/everything */
|
||||||
|
tmp_entry.flags = XATTR_MAP_FLAG_PREFIX | XATTR_MAP_FLAG_ALL;
|
||||||
|
tmp_entry.key = g_strdup(key);
|
||||||
|
tmp_entry.prepend = g_strdup(prefix);
|
||||||
|
add_xattrmap_entry(lo, &tmp_entry);
|
||||||
|
|
||||||
|
if (!*key) {
|
||||||
|
/* Prefix all case */
|
||||||
|
|
||||||
|
/* 2nd: Hide any non-prefixed entries on the host */
|
||||||
|
tmp_entry.flags = XATTR_MAP_FLAG_BAD | XATTR_MAP_FLAG_ALL;
|
||||||
|
tmp_entry.key = g_strdup("");
|
||||||
|
tmp_entry.prepend = g_strdup("");
|
||||||
|
add_xattrmap_entry(lo, &tmp_entry);
|
||||||
|
} else {
|
||||||
|
/* Prefix matching case */
|
||||||
|
|
||||||
|
/* 2nd: Hide non-prefixed but matching entries on the host */
|
||||||
|
tmp_entry.flags = XATTR_MAP_FLAG_BAD | XATTR_MAP_FLAG_SERVER;
|
||||||
|
tmp_entry.key = g_strdup(""); /* Not used */
|
||||||
|
tmp_entry.prepend = g_strdup(key);
|
||||||
|
add_xattrmap_entry(lo, &tmp_entry);
|
||||||
|
|
||||||
|
/* 3rd: Stop the client accessing prefixed attributes directly */
|
||||||
|
tmp_entry.flags = XATTR_MAP_FLAG_BAD | XATTR_MAP_FLAG_CLIENT;
|
||||||
|
tmp_entry.key = g_strdup(prefix);
|
||||||
|
tmp_entry.prepend = g_strdup(""); /* Not used */
|
||||||
|
add_xattrmap_entry(lo, &tmp_entry);
|
||||||
|
|
||||||
|
/* 4th: Everything else is OK */
|
||||||
|
tmp_entry.flags = XATTR_MAP_FLAG_OK | XATTR_MAP_FLAG_ALL;
|
||||||
|
tmp_entry.key = g_strdup("");
|
||||||
|
tmp_entry.prepend = g_strdup("");
|
||||||
|
add_xattrmap_entry(lo, &tmp_entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free(key);
|
||||||
|
g_free(prefix);
|
||||||
|
}
|
||||||
|
|
||||||
static void parse_xattrmap(struct lo_data *lo)
|
static void parse_xattrmap(struct lo_data *lo)
|
||||||
{
|
{
|
||||||
const char *map = lo->xattrmap;
|
const char *map = lo->xattrmap;
|
||||||
|
@ -2118,10 +2221,17 @@ static void parse_xattrmap(struct lo_data *lo)
|
||||||
tmp_entry.flags |= XATTR_MAP_FLAG_OK;
|
tmp_entry.flags |= XATTR_MAP_FLAG_OK;
|
||||||
} else if (strstart(map, "bad", &map)) {
|
} else if (strstart(map, "bad", &map)) {
|
||||||
tmp_entry.flags |= XATTR_MAP_FLAG_BAD;
|
tmp_entry.flags |= XATTR_MAP_FLAG_BAD;
|
||||||
|
} else if (strstart(map, "map", &map)) {
|
||||||
|
/*
|
||||||
|
* map is sugar that adds a number of rules, and must be
|
||||||
|
* the last entry.
|
||||||
|
*/
|
||||||
|
parse_xattrmap_map(lo, map, sep);
|
||||||
|
return;
|
||||||
} else {
|
} else {
|
||||||
fuse_log(FUSE_LOG_ERR,
|
fuse_log(FUSE_LOG_ERR,
|
||||||
"%s: Unexpected type;"
|
"%s: Unexpected type;"
|
||||||
"Expecting 'prefix', 'ok', or 'bad' in rule %zu\n",
|
"Expecting 'prefix', 'ok', 'bad' or 'map' in rule %zu\n",
|
||||||
__func__, lo->xattr_map_nentries);
|
__func__, lo->xattr_map_nentries);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue