By default, the name of xattrs 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.
A mapping of xattr names can be made using --xattrmap=<mapping>
where the <mapping>
string consists of a series of rules.
When looking for a mapping, the first matching rule applies. There must be a mapping for every xattr name in the list of rules, for example by making the final rule a catch-all rule to match any remaining attributes.
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 one of:
client
: Match key against an xattr name from the client for setxattr/getxattr/removexattrserver
: Match prepend against an xattr name from the server for listxattrall
: Can be used to make a single rule where both the server 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 xattrs through unchanged. It is intended both as a way of explicitly terminating the list of rules, and to allow some xattrs to skip following rules. -
bad
: If a client tries to use a name matching key it's denied usingEPERM
; when the server passes an attribute name matching prepend it's hidden. In many ways its use is very like theok
type 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 usingENOTSUP
; when the server passes an attribute name matching prepend it's hidden. In many ways its use is very like theok
type 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 may be empty in which case a client
scoped 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
scoped rule will always match on all names from
the server.
e.g.:
Mapping rule | Description |
---|---|
: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. xattrs. |
:ok:server::security.: |
will pass security. xattrs in listxattr from the server. |
:ok:all::: |
will terminate the rule search passing any remaining attributes in both directions. |
:bad:server::security.: |
would hide security. xattrs 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.
Please note that 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.
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 and filesystemsecurity.*
: only processes withCAP_SYS_ADMIN
trusted.*
: only processes withCAP_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.
- Prefix all attributes with
user.virtiofs.
--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:
--xattrmap=":map::user.virtiofs.:"
- Prefix
trusted.
attributes, allow others through
--xattrmap="/prefix/all/trusted./user.virtiofs./
/bad/server//trusted./
/bad/client/user.virtiofs.//
/ok/all///"
(each rule is on a single line just for the sake of clarity)
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:
--xattrmap="/map/trusted./user.virtiofs./"
- Hide
security.
attributes, and allow everything else
--xattrmap="/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 prevents
the client from seeing and/or setting any security.
attributes on the server.