By default the name of xattr's used by the client are passed through to the server file system. This can
be a problem where either those xattr names are used by something on the server (e.g. selinux
client/server confusion) or if the virtiofsd is running in a container with restricted privileges where
it cannot access some attributes.
Mappingsyntax
A mapping of xattr names can be made using -o xattrmap=mapping where the mapping string consists of a
series of rules.
The first matching rule terminates the mapping. The set of rules must include a terminating rule to
match any remaining attributes at the end.
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:scope is:
•
'client'-match'key'againstaxattrnamefromtheclientfor
setxattr/getxattr/removexattr
•
'server'-match'prepend'againstaxattrnamefromtheserver
for listxattr
•
'all'-canbeusedtomakeasinglerulewhereboththeserver
and client matches are triggered.
type is one of:
• 'prefix' - is designed to prepend and strip a prefix; the modified attributes then being passed on to
the client/server.
• 'ok' - Causes the rule set to be terminated when a match is found while allowing matching xattr's
through unchanged. It is intended both as a way of explicitly terminating the list of rules, and to
allow some xattr's to skip following rules.
• 'bad' - If a client tries to use a name matching 'key' it's denied using EPERM; when the server passes
an attribute name matching 'prepend' it's hidden. In many ways it's use is very like 'ok' as either an
explicit terminator or for special handling of certain patterns.
• 'unsupported' - If a client tries to use a name matching 'key' it's denied using ENOTSUP; when the
server passes an attribute name matching 'prepend' it's hidden. In many ways it's use is very like
'ok' as either an explicit terminator or for special handling of certain patterns.
key is a string tested as a prefix on an attribute name originating on the client. It maybe empty in
which case a 'client' rule will always match on client names.
prepend is a string tested as a prefix on an attribute name originating on the server, and used as a new
prefix. It may be empty in which case a 'server' rule will always match on all names from the server.
e.g.:
:prefix:client:trusted.:user.virtiofs.:
will match 'trusted.' attributes in client calls and prefix them before passing them to the server.
:prefix:server::user.virtiofs.:
will strip 'user.virtiofs.' from all server replies.
:prefix:all:trusted.:user.virtiofs.:
combines the previous two cases into a single rule.
:ok:client:user.::
will allow get/set xattr for 'user.' xattr's and ignore following rules.
:ok:server::security.:
will pass 'securty.' xattr's in listxattr from the server and ignore following rules.
:ok:all:::
will terminate the rule search passing any remaining attributes in both directions.
:bad:server::security.:
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.
Note: When the 'security.capability' xattr is remapped, the daemon has to do extra work to remove it
during many operations, which the host kernel normally does itself.
Securityconsiderations
Operating systems typically partition the xattr namespace using well defined name prefixes. Each
partition may have different access controls applied. For example, on Linux there are multiple partitions
• system.* - access varies depending on attribute & filesystem
• security.* - only processes with CAP_SYS_ADMIN
• trusted.* - only processes with CAP_SYS_ADMIN
• user.* - any process granted by file permissions / ownership
While other OS such as FreeBSD have different name prefixes and access control rules.
When remapping attributes on the host, it is important to ensure that the remapping does not allow a
guest user to evade the guest access control rules.
Consider if trusted.* from the guest was remapped to user.virtiofs.trusted* in the host. An unprivileged
user in a Linux guest has the ability to write to xattrs under user.*. Thus the user can evade the access
control restriction on trusted.* by instead writing to user.virtiofs.trusted.*.
As noted above, the partitions used and access controls applied, will vary across guest OS, so it is not
wise to try to predict what the guest OS will use.
The simplest way to avoid an insecure configuration is to remap all xattrs at once, to a given fixed
prefix. This is shown in example (1) below.
If selectively mapping only a subset of xattr prefixes, then rules must be added to explicitly block
direct access to the target of the remapping. This is shown in example (2) below.
Mappingexamples
1. Prefix all attributes with 'user.virtiofs.'
-o xattrmap=":prefix:all::user.virtiofs.::bad:all:::"
This uses two rules, using : as the field separator; 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
"/prefix/all/trusted./user.virtiofs./
/bad/server//trusted./
/bad/client/user.virtiofs.//
/ok/all///"
Here there are four rules, using / as the field separator, and also demonstrating that new lines can be
included between rules. The first rule is the prefixing of 'trusted.' and stripping of 'user.virtiofs.'.
The second rule hides unprefixed 'trusted.' attributes on the host. The third rule stops a guest from
explicitly setting the 'user.virtiofs.' path directly to prevent access control bypass on the target of
the earlier prefix remapping. 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
"/bad/all/security./security./
/ok/all///'
The first rule combines what could be separate client and server rules into a single 'all' rule, matching
'security.' in either client arguments or lists returned from the host. This stops the client seeing any
'security.' attributes on the server and stops it setting any.