This revision is part of a series. Click on the Stack tab below to see the context.
This series has also been squeezed into D47633 to provide an overall view.
Commit message:
Supporting group targets is a requirement for MAC/do to be able to
enforce a limited set of valid new groups passed to setgroups().
Additionally, it must be possible for this set of groups to also depend
on the target UID, since users and groups are quite tied in UNIX (users
are automatically placed in only the groups specified through
'/etc/passwd' (primary group) and '/etc/group' (supplementary ones)).
These requirements call for a re-design of the specification of the
rules specification string and of 'struct rule'.
A rules specification string is now a list of rules separated by ';'
(instead of ','). One rule is still composed of a "from" part and
a "to" (or "target") part, both being separated by ':' (as before).
The first part, "from", is matched against the credentials of the
process calling setuid()/setgroups(). Its specification remains
unchanged: It is a '<type>=<id>' clause, where <type> is either "uid" or
"gid" and <id> an UID or GID.
The second part, "to", is now a comma-separated (',') list of
'<type>=<flags><id>' clauses similar to that of the "from" part, with
the extensions that <id> may also be "*" or "any" or ".", and that
<flags> may contain at most one of the '+', '-' and '!' characters when
<type> is GID. "*" and "any" both designate any ID for the <type>, and
are aliases to each other. In front of them, only the "+" flag is
allowed (in addition to the previous rules). "." designates the
process' current IDs for the <type>, as explained below.
For GIDs, an absence of flag indicates that the specified GID is allowed
as the real, effective and/or saved GIDs (the "primary" groups).
Conversely, the presence of any allowed flag indicates that the
specification concerns supplementary groups. The '+' flag in front of
some GID indicates that it is allowed as a supplementary group. The '!'
flag indicates that the GID is mandatory, i.e., must be listed in the
supplementary groups. The '-' flag indicates that the GID 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 <id> ".", or if other MAC policies are loaded that would give
access to other, unwanted groups.
"." indicates some ID that the calling process already has on privilege
check. For type "uid", it designates any of the real, effective or
saved UIDs. For type "gid", its effect depends on the presence of one
of the '+', '-' or '!' flags. If no flag is present, it designates any
of the real, effective or saved GIDs. If one is present, it designates
any of the supplementary groups.
If the "to" part doesn't specify any explicit UID, any of the UIDs of
the calling process is implied (it is as if "uid=." has been specified).
Similarly, if it doesn't specify any explicit GID, "gid=.,gid=!." is
assumed, meaning that all the groups of the calling process are implied
and must be present. More precisely, the first group passed to
setgroups(), which is the effective GID, must either be the current
real, effective or saved GID, whereas all others (the supplementary
ones) must be the same as those that are current.
No two clauses in a single "to" list may display the same <id>, except
for GIDs but only if, each time the same <id> appears, it does so with
a different flag (no flag counting as a separate flag) and all the
specified flags are not contradictory (e.g., it is possible to have the
same GID appear with no flag and the "+" flag, but the same GID with
both "+" and "-" will be rejected).
'struct rule' now holds arrays of UIDs (field 'uids') and GIDs (field
'gids') that are admissible as targets, with accompanying flags (such as
MDF_SUPP_MUST, representing the '!' flag). Some flags are also held by
ID type, including flags associated to individual IDs, as MDF_CURRENT in
these flags stands for the process being privilege-checked's current
IDs, to which ID flags apply. As a departure from this scheme, "*" or
"any" as <id> for GIDs is either represented by MDF_ANY or MDF_ANY_SUPP.
This is to make it coexist with a "."/MDF_CURRENT specification for the
other category of groups (among primary and supplementary groups), which
needs to be qualified by the usual GID flags.
This commit contains only the changes to parse the new rules and to
build their representation. The privilege granting part is not fixed
here, beyond what making compilation work requires (and, in preparation
for some subsequent commit, minimal adaptations to the matching logic in
check_setuid()).