MAC_DO(4) FreeBSD Kernel Interfaces Manual MAC_DO(4)
NAME
mac_do - policy allowing unprivileged users to change process credentials
SYNOPSIS
To compile the mac_do policy into your kernel, place the following lines
in your kernel configuration file:
options MAC
options MAC_DO
Alternately, to load this policy module at boot time, place the following
line in your kernel configuration file:
options MAC
and in loader.conf(5):
mac_do_load="YES"
DESCRIPTION
The mac_do policy module allows unprivileged users to change process
credentials according to rules configured by the administrator. It
supports per-jail configuration.
Currently, the mac_do policy module only produces effects to processes
spwaned from the /usr/bin/mdo executable, please see mdo(1) for more
details on this program.
CREDENTIALS RULES
Rules specify which transitions of process credentials mac_do will allow,
based on current process credentials and the desired final ones. They
are passed by an administrator in the form of a string having the
specific syntax described below in a top-bottom manner. They have been
designed to be able to finely describe the desired target credentials in
a safe and compact way.
Top-Level List of Rules
At the top, rules are a possibly empty list of individual rules separated
by a semi-colon (`;'):
<rules> <?> [<rule> [`;' <rule>]*]
They form a disjunction, i.e., mac_do authorizes a credentials transition
as soon as at least one rule in the list matches.
One rule is composed of a <from> part (also called "match") and a <to>
part (also called "target"), in this order, separated by a greater-than
sign (`>'):
<rule> <?> <from> `>' <to>
Rule's <from> Part
The first part of a rule, <from>, is matched against the credentials of
the process requesting some credentials transition. It has the form:
<from> <?> <type> `=' <id>
<type> must be:
<type> <?> [`uid' | `gid']
i.e., one of the literal strings `uid' or `gid'. <id> must be the
numerical ID of a user or group, and is matched with the current process
real ID of the corresponding type.
Rule's <to> Part
The second part of a rule, <to>, is a comma-separated (`,') non-empty
list of target clauses:
<to> <?> <target_clause> [`,' <target_clause>]*
Target clauses of a given rule also form a disjunction, i.e., the IDs
they specify are alternatives for the target credentials, except in some
cases described below.
The next subsections describe the syntax of target clauses, the defaults
that apply and the principle of non-redundancy and non-contradiction in
each rule's <to> part.
Target Clauses
A target clause in a rule's <to> part must be of one of the following
forms:
<target_clause> <?> `any'
<target_clause> <?> <flags> <type> `=' <id>
The first form is a compact way to specify that any target credentials
are allowed. The second form is similar to that of <from> clauses, with
the following extensions:
o <id> may also be a literal `*' or `any' or `.'. `*' and `any' both
designate any ID for the specified <type>, and are treated
identically. `.' designates the process' current IDs for the
specified <type>, as explained below.
o <flags> may contain at most one of the `+', `-' and `!' characters,
and may be non-empty only when <type> is `gid'. Additionally, if
<id> is `*' or `any', only the `+' flag may appear.
For target clauses of `gid' type, an absence of flag indicates that the
specified group ID is allowed as the real, effective and/or saved group
IDs (the "primary" groups). Conversely, the presence of any allowed flag
indicates that the specification concerns supplementary groups. Each
flag has a specific meaning:
o `+' indicates that the group ID is allowed as a supplementary group.
o `!' indicates that the group ID is mandatory, i.e., it must be listed
in the supplementary groups.
o `-' indicates that the group ID must not be listed in the
supplementary groups.
A specification with `-' is only useful in conjunction with a `+'-tagged
specification where only one of them has `.' as its <id>. Target clauses
having the `!' or `-' flag are "forcing" clauses, and as such do not take
part in the disjunction of the other target clauses but rather
unconditionally apply in their rule.
`.' is a placeholder for IDs that the calling process already has on
privilege check. For type `uid', it designates any of the process' real,
effective or saved user IDs. For type `gid', its effect depends on
whether flags are present. If none is present, it designates any of the
process' real, effective or saved group IDs. If one is present, it
designates any of the process' supplementary groups.
Defaults for the <to> Part
If the <to> part does not list a target clause with type `uid', any of
the current user IDs of the calling process is accepted. In other words,
in this case, mac_do behaves as if a target clause of:
uid=.
had been listed.
Similarly, if the <to> part does not list a target clause with type
`gid', all the groups of the calling process are assumed to be required.
More precisely, each of the desired real, effective and saved group IDs
must be one of the current real, effective or saved group ID, and all
supplementary groups must be the same as those that are current. It is
as if the <to> part had contained the following two clauses:
gid=.,!gid=.
Non-Redundancy and Non-Contradiction in a <to> Part
No two target clauses of a single rule may express the exact same logical
intent nor contradictory ones.
In practice, no two clauses may display the same ID except for group IDs
but only if, each time the same ID appears, it does so with a different
flag, or no flags only once. Additionally, the specified flags in
multiple occurences must not be contradictory. For example, the same
group ID appearing with both `+' and `-' will cause rejection of the
rule.
Parsing Specifics
Any amount of whitespace is allowed around tokens of the above grammar,
except that there may be no spaces between <flags> and <id> in target
clauses.
For convenience, numerical IDs may be specified as negative integers,
which are then converted to unsigned ones as specified in the C standard
for the uid_t and gid_t types, which are both 64-bit unsigned integers.
RUNTIME CONFIGURATION
The following sysctl(8) knobs are available:
security.mac.do.enabled
Enable the mac_do policy. (Default: 1).
security.mac.do.rules
The list of credential rules, whose syntax is described in the
CREDENTIALS RULES section above. This list is specific to each
jail. Please see the JAIL SUPPORT section below for more details
on the interaction of mac_do with jails.
security.mac.do.print_parse_error
Logs a message on trying to set incorrect rules via the
security.mac.do.rules sysctl(8) knob.
JAIL SUPPORT
mac_do supports per-jail configuration of rules.
By default, at creation, a new jail has no credentials rules, effectively
disabling mac_do for its processes.
The following jail parameters are defined:
mac.do Possible values are:
`enable' mac_do will enforce specific credential rules in the
jail. The mac.do.rules jail parameter must also be
set in this case.
`disable' Disables mac_do in the jail. Strictly equivalent to
jail creation's default behavior and to setting the
rules to an empty string.
`inherit' The jail's credentials rules are inherited from the
jail's parent (which may themselves have been
inherited). Modified rules propagate to all children
jails configured for inheritance.
mac.do.rules
The credentials rules for the jail. It is always equal to the
value that can be retrieved by the sysctl(8) knob
security.mac.do.rules described in section RUNTIME CONFIGURATION.
If set, and the jail parameter mac.do is not so explicitly, the
value of the latter will default to `disable' if empty, else to
`enable'.
Each jail must have mdo(1) installed at path /usr/bin/mdo, as this path
is currently not configurable.
EXAMPLES
Here are several examples of single rules matching processes having a
real user ID of 10001:
uid=10001>uid=10002
Allows the process to switch any of its real, effective or saved
user ID to 10002, but keeping the groups it is already in, and
with the same primary/supplementary groups split.
uid=10001>uid=10002,uid=10003
Same as the first example, but also allows to switch to UID 10003
instead of 10002.
uid=10001>uid=10002,gid=10002
Same as the first example, but the new primary groups must be set
to 10002 and no supplementary groups should be set.
uid=10001>uid=10002,gid=10002,+gid=.
Same as the previous example, but in addition allowing to retain
any current supplementary groups.
uid=10001>uid=10002,gid=10002,!gid=.
Same as the previous example, but with the additional constraint
that all current supplementary groups must be kept.
uid=10001>uid=10002,gid=10002,+gid=.,-gid=10001
Same as `uid=10001>uid=10002,gid=10002,+gid=.' above, but 10001
cannot be retained as a supplementary group.
uid=10001>uid=10002,gid=10002,+gid=.,!gid=10003
Same as `uid=10001>uid=10002,gid=10002,+gid=.' above, with the
additional constraint that 10003 must appear in the supplementary
groups.
uid=10001>uid=10002,gid=*,+gid=*
Same as the first example, but lifting any constraints on groups,
allowing the process to become part of any groups it sees fit.
Here are several examples of single rules matching processes having a
real group ID of 10001:
gid=10001>uid=0
Makes 10001 a more powerful `wheel' group, allowing its members
to switch to root without password.
gid=10001>gid=10002
Allows the process to enter GID 10002 as a primary group, but
only if giving up all its supplementary groups.
security.mac.do.rules=gid=10001>gid=10002,+gid=.
Same as the previous example, but allows to retain any current
supplementary groups.
gid=10001>gid=10002,!gid=.
Same as the previous example, but with the additional constraint
that all current supplementary groups must be kept.
SEE ALSO
mdo(1), setcred(2), mac(4), jail(8), sysctl(8)
AUTHORS
Olivier Certner <
[email protected]>
Baptiste Daroussin <
[email protected]>
BUGS
Currently, mac_do considers only credentials transitions requested
through the setcred(2) system call. This system call was in large part
created so that mac_do can see whole credentials transitions to decide
whether to authorize them, which the traditional UNIX's piecewise
approach of successively changing different parts of them cannot allow.
However, calls to traditional or standard credentials-changing functions
can be considered as full transitions on their own, however limited, and
as such should be equally monitored by mac_do. Future work will lift
this restriction.
SECURITY CONSIDERATIONS
The threat model for mac_do is to consider userland programs as generally
untrustable to decide upon which credentials changes are acceptable. It
is in contrast with the traditional UNIX way to change credentials, in
which specialized programs are installed with the setuid bit, giving them
full administrator privileges so that they are effectively able to
establish new ones. Vulnerabilities in such credentials-changing
programs can have catastrophic consequences on the integrity of the
system.
Consequently, mac_do does not rely on companion userland programs to
decide whether some credentials transition is acceptable. Instead, it
maintains its own configuration independently from the userland password
and group databases. Establishing this configuration currently itself
relies on userland programs issuing calls to sysctl(3) or jail(2). It
should thus be established near system boot or jail start, before any
possible attacks could happen on the system, and further measures should
be taken to ensure that potential corruptions does not affect the
configuration in subsequent restarts, such as re-establishing pristine
state or ensuring that the boot procedure up to the configuration of
mac_do can be trusted.
FreeBSD 14.1-RELEASE-p8 December 19, 2024 FreeBSD 14.1-RELEASE-p8