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
|
||||
for the whole rule.
|
||||
White space may be added before and after each rule.
|
||||
|
||||
Using ':' as the separator a rule is of the form:
|
||||
|
||||
``:type:scope:key:prepend:``
|
||||
|
@ -219,6 +220,14 @@ e.g.:
|
|||
|
||||
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
|
||||
----------------------
|
||||
|
||||
|
@ -234,6 +243,11 @@ the first rule prefixes and strips 'user.virtiofs.',
|
|||
the second rule hides any non-prefixed attributes that
|
||||
the host set.
|
||||
|
||||
This is equivalent to the 'map' rule:
|
||||
|
||||
::
|
||||
-o xattrmap=":map::user.virtiofs.:"
|
||||
|
||||
2) Prefix 'trusted.' attributes, allow others through
|
||||
|
||||
::
|
||||
|
@ -256,6 +270,11 @@ the 'user.virtiofs.' path directly.
|
|||
Finally, the fourth rule lets all remaining attributes
|
||||
through.
|
||||
|
||||
This is equivalent to the 'map' rule:
|
||||
|
||||
::
|
||||
-o xattrmap="/map/trusted./user.virtiofs./"
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
const char *map = lo->xattrmap;
|
||||
|
@ -2118,10 +2221,17 @@ static void parse_xattrmap(struct lo_data *lo)
|
|||
tmp_entry.flags |= XATTR_MAP_FLAG_OK;
|
||||
} else if (strstart(map, "bad", &map)) {
|
||||
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 {
|
||||
fuse_log(FUSE_LOG_ERR,
|
||||
"%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);
|
||||
exit(1);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue