 |
|
| |
MAC_DO(4) |
FreeBSD Kernel Interfaces Manual |
MAC_DO(4) |
mac_do — policy
allowing unprivileged users to change process credentials
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):
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.
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.
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⟩
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.
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.
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:
- ⟨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.
- ⟨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:
- ‘
+ ’ indicates that the group ID is
allowed as a supplementary group.
- ‘
! ’ indicates that the group ID is
mandatory, i.e., it must be listed in the supplementary groups.
- ‘
- ’ 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.
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=.
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.
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.
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.
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.
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.
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.
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.
Visit the GSP FreeBSD Man Page Interface. Output converted with ManDoc.
|