<feed xmlns='http://www.w3.org/2005/Atom'>
<title>src/sys/security, branch releng/14.3</title>
<subtitle>FreeBSD source tree</subtitle>
<link rel='alternate' type='text/html' href='http://cgit.freebsd.org/src/'/>
<entry>
<title>MAC/do: Fix a too stringent debug assertion for a target of 'uid=*'</title>
<updated>2025-05-27T21:01:54+00:00</updated>
<author>
<name>Olivier Certner</name>
<email>olce@FreeBSD.org</email>
</author>
<published>2025-05-27T08:20:06+00:00</published>
<link rel='alternate' type='text/html' href='http://cgit.freebsd.org/src/commit/?id=adc6f56e81aaca05b8ab72f07a8de6b69d9fe498'/>
<id>adc6f56e81aaca05b8ab72f07a8de6b69d9fe498</id>
<content type='text'>
MDF_HAS_PRIMARY_CLAUSE only concerns groups, not users, and is thus not
set in the latter case.

This change only has an effect on INVARIANTS builds.

PR:             287057
MFC after:      10 minutes
Sponsored by:   The FreeBSD Foundation

(cherry picked from commit b5c9889e369a801ce7c1115f2535ddacbd69800d)
(cherry picked from commit 30f092c40ad4eb592861839f4ffa9e9891abf1d3)

Approved by:    re (cperciva)
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
MDF_HAS_PRIMARY_CLAUSE only concerns groups, not users, and is thus not
set in the latter case.

This change only has an effect on INVARIANTS builds.

PR:             287057
MFC after:      10 minutes
Sponsored by:   The FreeBSD Foundation

(cherry picked from commit b5c9889e369a801ce7c1115f2535ddacbd69800d)
(cherry picked from commit 30f092c40ad4eb592861839f4ffa9e9891abf1d3)

Approved by:    re (cperciva)
</pre>
</div>
</content>
</entry>
<entry>
<title>MAC/do: Rules: &lt;from&gt; and &lt;to&gt; parts now to be separated by '&gt;'</title>
<updated>2025-04-08T13:38:30+00:00</updated>
<author>
<name>Olivier Certner</name>
<email>olce@FreeBSD.org</email>
</author>
<published>2025-04-01T17:06:17+00:00</published>
<link rel='alternate' type='text/html' href='http://cgit.freebsd.org/src/commit/?id=8047b85cbe17b3819ac8acf94a19b5a844025c65'/>
<id>8047b85cbe17b3819ac8acf94a19b5a844025c65</id>
<content type='text'>
Previously, we would accept only ':' as the separator, which makes
parsing of the rule specification harder for humans, especially those
people that are used to UNIX systems where ':' is used as the separator
in PATH.  With ':', the &lt;from&gt; and &lt;to&gt; parts can look like two
different elements that are unrelated, especially to these eyes.

Change parse_single_rule() so that '&gt;' is also accepted as a separator
between &lt;from&gt; and &lt;to&gt;, and promote it as the one to use.  During
a transition period, we will still allow the use of ':' for backwards
compatibility.

The manual page update comes from separate revision D49628.  ':' has
been completely removed from it on purpose.

Reviewed by:    bapt, manpages (ziaee)
MFC after:      5 days
Sponsored by:   The FreeBSD Foundation
Differential Revision:  https://reviews.freebsd.org/D49627

(cherry picked from commit f01d26dec67fb6597438ed765269b85d1099a6fa)
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Previously, we would accept only ':' as the separator, which makes
parsing of the rule specification harder for humans, especially those
people that are used to UNIX systems where ':' is used as the separator
in PATH.  With ':', the &lt;from&gt; and &lt;to&gt; parts can look like two
different elements that are unrelated, especially to these eyes.

Change parse_single_rule() so that '&gt;' is also accepted as a separator
between &lt;from&gt; and &lt;to&gt;, and promote it as the one to use.  During
a transition period, we will still allow the use of ':' for backwards
compatibility.

The manual page update comes from separate revision D49628.  ':' has
been completely removed from it on purpose.

Reviewed by:    bapt, manpages (ziaee)
MFC after:      5 days
Sponsored by:   The FreeBSD Foundation
Differential Revision:  https://reviews.freebsd.org/D49627

(cherry picked from commit f01d26dec67fb6597438ed765269b85d1099a6fa)
</pre>
</div>
</content>
</entry>
<entry>
<title>MAC/do: parse_single_rule(): Fix herald comment's first line</title>
<updated>2025-04-08T13:38:29+00:00</updated>
<author>
<name>Olivier Certner</name>
<email>olce@FreeBSD.org</email>
</author>
<published>2025-04-01T16:43:40+00:00</published>
<link rel='alternate' type='text/html' href='http://cgit.freebsd.org/src/commit/?id=bd282a73571cce6c3a7c5579debc5146a0348851'/>
<id>bd282a73571cce6c3a7c5579debc5146a0348851</id>
<content type='text'>
No functional change.

MFC after:      5 days
Sponsored by:   The FreeBSD Foundation

(cherry picked from commit 03c12d0c21a3f3aba5db8b86fc3b4637cfe109a7)
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
No functional change.

MFC after:      5 days
Sponsored by:   The FreeBSD Foundation

(cherry picked from commit 03c12d0c21a3f3aba5db8b86fc3b4637cfe109a7)
</pre>
</div>
</content>
</entry>
<entry>
<title>MAC/do: Fix a compilation warning about an unused function</title>
<updated>2025-04-03T19:31:06+00:00</updated>
<author>
<name>Olivier Certner</name>
<email>olce@FreeBSD.org</email>
</author>
<published>2024-12-17T14:17:16+00:00</published>
<link rel='alternate' type='text/html' href='http://cgit.freebsd.org/src/commit/?id=f9b5d5bf1186d4b01e92229d271f2cb0d8764b25'/>
<id>f9b5d5bf1186d4b01e92229d271f2cb0d8764b25</id>
<content type='text'>
grant_supplementary_group_from_flags() had been used in previous
versions of the recent changes, but recently has not been needed
anymore.  It has been kept around just in case deliberately, by analogy
with grant_primary_group_from_flags() (this one still being used).

(cherry picked from commit f1ddb6fb8c4d051a205dae3a848776c9d56f86ff)
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
grant_supplementary_group_from_flags() had been used in previous
versions of the recent changes, but recently has not been needed
anymore.  It has been kept around just in case deliberately, by analogy
with grant_primary_group_from_flags() (this one still being used).

(cherry picked from commit f1ddb6fb8c4d051a205dae3a848776c9d56f86ff)
</pre>
</div>
</content>
</entry>
<entry>
<title>MAC/do: Update copyright</title>
<updated>2025-04-03T19:31:06+00:00</updated>
<author>
<name>Olivier Certner</name>
<email>olce@FreeBSD.org</email>
</author>
<published>2024-12-16T16:52:14+00:00</published>
<link rel='alternate' type='text/html' href='http://cgit.freebsd.org/src/commit/?id=ba9aea5dc0e02375d0c46762b39d60f9a7d4b68a'/>
<id>ba9aea5dc0e02375d0c46762b39d60f9a7d4b68a</id>
<content type='text'>
Approved by:    emaste (mentor)
Sponsored by:   The FreeBSD Foundation

(cherry picked from commit e94684b3e0d966f755f785e4908317bd6bdd2ea0)
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Approved by:    emaste (mentor)
Sponsored by:   The FreeBSD Foundation

(cherry picked from commit e94684b3e0d966f755f785e4908317bd6bdd2ea0)
</pre>
</div>
</content>
</entry>
<entry>
<title>MAC/do: Apply a rule on real UID/GID instead of effective ones</title>
<updated>2025-04-03T19:31:06+00:00</updated>
<author>
<name>Olivier Certner</name>
<email>olce@FreeBSD.org</email>
</author>
<published>2024-11-29T14:39:17+00:00</published>
<link rel='alternate' type='text/html' href='http://cgit.freebsd.org/src/commit/?id=8f72bcd9fd5d951fe673ca4c3dfef017f39c672e'/>
<id>8f72bcd9fd5d951fe673ca4c3dfef017f39c672e</id>
<content type='text'>
We intend MAC/do to authorize transitions based on the "real" identity
information of the calling process, rather than transiently-acquired
effective IDs.

Reviewed by:    bapt
Approved by:    markj (mentor)
Sponsored by:   The FreeBSD Foundation
Differential Revision:  https://reviews.freebsd.org/D47845

(cherry picked from commit de701f9bdbe0ede691a0439d1c469082b94fe234)
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
We intend MAC/do to authorize transitions based on the "real" identity
information of the calling process, rather than transiently-acquired
effective IDs.

Reviewed by:    bapt
Approved by:    markj (mentor)
Sponsored by:   The FreeBSD Foundation
Differential Revision:  https://reviews.freebsd.org/D47845

(cherry picked from commit de701f9bdbe0ede691a0439d1c469082b94fe234)
</pre>
</div>
</content>
</entry>
<entry>
<title>MAC/do: Convert internal TAILQs to STAILQs</title>
<updated>2025-04-03T19:31:06+00:00</updated>
<author>
<name>Olivier Certner</name>
<email>olce@FreeBSD.org</email>
</author>
<published>2024-11-12T17:31:33+00:00</published>
<link rel='alternate' type='text/html' href='http://cgit.freebsd.org/src/commit/?id=53e73ec9f6c41ca8f35258b64d8a57cbc4bb2b16'/>
<id>53e73ec9f6c41ca8f35258b64d8a57cbc4bb2b16</id>
<content type='text'>
We only browse these forward and never need to remove arbitrary elements
from them.

No functional change (intended).

Reviewed by:    bapt, emaste
Approved by:    markj (mentor)
Sponsored by:   The FreeBSD Foundation
Differential Revision:  https://reviews.freebsd.org/D47624

(cherry picked from commit c7fc71c6af0761f81ecafdb281dd43a081b3b22f)
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
We only browse these forward and never need to remove arbitrary elements
from them.

No functional change (intended).

Reviewed by:    bapt, emaste
Approved by:    markj (mentor)
Sponsored by:   The FreeBSD Foundation
Differential Revision:  https://reviews.freebsd.org/D47624

(cherry picked from commit c7fc71c6af0761f81ecafdb281dd43a081b3b22f)
</pre>
</div>
</content>
</entry>
<entry>
<title>MAC/do: parse_rules(): Tolerate blanks around tokens</title>
<updated>2025-04-03T19:31:05+00:00</updated>
<author>
<name>Olivier Certner</name>
<email>olce@FreeBSD.org</email>
</author>
<published>2024-11-12T17:13:26+00:00</published>
<link rel='alternate' type='text/html' href='http://cgit.freebsd.org/src/commit/?id=8bf992d2ebadfe287909be02e6d0a51409597b05'/>
<id>8bf992d2ebadfe287909be02e6d0a51409597b05</id>
<content type='text'>
To this end, we introduce the strsep_noblanks() function, designed to be
a drop-in replacement for strstep(), and use it in place of the latter.

We had taken care of calling strsep() even when the remaining sub-string
was not delimited (i.e., with empty string as its second argument), so
this commit only has mechanical replacements of existing calls.

Reviewed by:    bapt
Approved by:    markj (mentor)
Sponsored by:   The FreeBSD Foundation
Differential Revision:  https://reviews.freebsd.org/D47623

(cherry picked from commit 4a03b64517b3151064c52e213ebbc068ab1430d1)
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
To this end, we introduce the strsep_noblanks() function, designed to be
a drop-in replacement for strstep(), and use it in place of the latter.

We had taken care of calling strsep() even when the remaining sub-string
was not delimited (i.e., with empty string as its second argument), so
this commit only has mechanical replacements of existing calls.

Reviewed by:    bapt
Approved by:    markj (mentor)
Sponsored by:   The FreeBSD Foundation
Differential Revision:  https://reviews.freebsd.org/D47623

(cherry picked from commit 4a03b64517b3151064c52e213ebbc068ab1430d1)
</pre>
</div>
</content>
</entry>
<entry>
<title>MAC/do: toast_rules(): Minor simplification</title>
<updated>2025-04-03T19:31:05+00:00</updated>
<author>
<name>Olivier Certner</name>
<email>olce@FreeBSD.org</email>
</author>
<published>2024-08-13T08:53:24+00:00</published>
<link rel='alternate' type='text/html' href='http://cgit.freebsd.org/src/commit/?id=5e00a28b2f02a820f9cf9e04b38839f8da835db8'/>
<id>5e00a28b2f02a820f9cf9e04b38839f8da835db8</id>
<content type='text'>
Use the most common pattern to browse and delete elements of a list, as it reads quicker.

Reviewed by:    bapt
Approved by:    markj (mentor)
Sponsored by:   The FreeBSD Foundation
Differential Revision:  https://reviews.freebsd.org/D47622

(cherry picked from commit 2110eef4bf608b6c1facc57c68d02960b6d880c9)
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Use the most common pattern to browse and delete elements of a list, as it reads quicker.

Reviewed by:    bapt
Approved by:    markj (mentor)
Sponsored by:   The FreeBSD Foundation
Differential Revision:  https://reviews.freebsd.org/D47622

(cherry picked from commit 2110eef4bf608b6c1facc57c68d02960b6d880c9)
</pre>
</div>
</content>
</entry>
<entry>
<title>MAC/do: Interpret the new rules specification; Monitor setcred()</title>
<updated>2025-04-03T19:31:04+00:00</updated>
<author>
<name>Olivier Certner</name>
<email>olce@FreeBSD.org</email>
</author>
<published>2024-07-22T14:11:34+00:00</published>
<link rel='alternate' type='text/html' href='http://cgit.freebsd.org/src/commit/?id=986ac13041c8205aaea98e8dcdedee798d4bef6c'/>
<id>986ac13041c8205aaea98e8dcdedee798d4bef6c</id>
<content type='text'>
TL;DR:
Now monitor setcred() calls, and reject or grant them according to the
new rules specification.

Drop monitoring setuid() and setgroups().  As previously explained in
the commit introducing the setcred() system call, MAC/do must know the
entire new credentials while the old ones are still available to be able
to approve or reject the requested changes.  To this end, the chosen
approach was to introduce a new system call, setcred(), instead of
modifying existing ones to be able to participate in a "prepare than
commit"-like protocol.

******

The MAC framework typically calls several hooks of its registered
policies as part of the privilege checking/granting process.  Each
system call calls some dedicated hook early, to which it usually passes
the same arguments it received, whose goal is to forcibly deny access to
the functionality when needed (i.e., a single deny by any policy
globally denies the access).  Then, the system call usually calls
priv_check() or priv_check_cred() an unspecified number of times, each
of which may trigger calls to two generic MAC hooks.  The first such
call is to mac_priv_check(), and always happens.  Its role is to deny
access early and forcibly, as can be done also in system calls'
dedicated early hooks (with different reach, however).  The second,
mac_priv_grant(), is called only if the priv_check*() and
prison_priv_check() generic code doesn't handle the request by itself,
i.e., doesn't explicitly grant access (to the super user, or to all
users for a few specific privileges).  It allows any single policy to
grant the requested access (regardless of whether the other policies do
so or not).

MAC/do currently only has an effect on processes spawned from the
'/usr/bin/mdo' executable.  It implements all setcred() hooks, called
via mac_cred_setcred_enter(), mac_cred_check_setcred() and
mac_cred_setcred_exit().  In the first one, implemented in
mac_do_setcred_enter(), it checks if MAC/do has to apply to the current
process, allocates (or re-uses) per-thread data to be later used by the
other hooks (those of setcred() and the mac_priv_grant() one, called by
priv_check*()) and fills them with the current context (the rules to
apply).  This is both because memory allocations cannot be performed
while holding the process lock and to ensure that all hooks called by
a single setcred() see the same rules to apply (not doing this would be
a security hazard as rules are concurrently changed by the
administrator, as explained in more details below).  In the second one
(implemented by mac_do_check_setcred()), it stores in MAC/do's
per-thread data the new credentials.  Indeed, the next MAC/do's hook
implementation to be called, mac_do_priv_grant() (implementing the
mac_priv_grant() hook) must have knowledge of the new credentials that
setcred() wants to install in order to validate them (or not), which the
MAC framework can't provide as the priv_check*() API only passes the
current credentials and a specific privilege number to the
mac_priv_check() and mac_priv_grant() hooks.  By contrast, the very
point of MAC/do is to grant the privilege of changing credentials not
only based on the current ones but also on the seeked-for ones.

The MAC framework's constraints that mac_priv_grant() hooks are called
without context and that MAC modules must compose (each module may
implement any of the available hooks, and in particular those of
setcred()) impose some aspects of MAC/do's design.  Because MAC/do's
rules are tied to jails, accessing the current rules requires holding
the corresponding jail's lock.  As other policies might try to grab the
same jail's lock in the same hooks, it is not possible to keep the
rules' jail's lock between mac_do_setcred_enter() and
mac_do_priv_grant() to ensure that the rules are still alive.  We have
thus augmented 'struct rules' with a reference count, and its lifecyle
is now decoupled from being referenced or not by a jail.  As a thread
enters mac_cred_setcred_enter(), it grabs a hold on the current rules
and keeps a pointer to them in the per-thread data.  In its
mac_do_setcred_exit(), MAC/do just "frees" the per-thread data, in
particular by dropping the referenced rules (we wrote "frees" within
guillemets, as in fact the per-thread structure is reused, and only
freed when a thread exits or the module is unloaded).

Additionally, ensuring that all hooks have a consistent view of the
rules to apply might become crucial if we augment MAC/do with forceful
access denial policies in the future (i.e., policies that forcibly
disable access regardless of other MAC policies wanting to grant that
access).  Indeed, without the above-mentioned design, if newly installed
rules start to forcibly deny some specific transitions, and some thread
is past the mac_cred_check_setcred() hook but before the
mac_priv_grant() one, the latter may grant some privileges that should
have been rejected first by the former (depending on the content of
user-supplied rules).

A previous version of this change used to implement access denial
mandated by the '!' and '-' GID flags in mac_do_check_setcred() with the
goal to have this rejection prevail over potential other MAC modules
authorizing the transition.  However, this approach had two drawbacks.
First, it was incompatible both conceptually and in the current
implementation with multiple rules being treated as an inclusive
disjunction, where any single rule granting access is enough for MAC/do
to grant access.  Explicit denial requested by one matching rule could
prevent another rule from granting access.  The implementation could
have been fixed, but the conflation of rules being considered as
disjoint for explicit granting but conjunct for forced denial would have
remained.  Second, MAC/do applies only to processes spawned from
a particular executable, and imposing system-wide restrictions on only
these processes is conceptually strange and probably not very useful.
In the end, we moved the implementation of explicit access denial into
mac_do_priv_grant(), along with the interpretation of other target
clauses.

The separate definition of 'struct mac_do_data_header' may seem odd, as
it is only used in 'struct mac_do_setcred_data'.  It is a remnant of an
earlier version that was not using setcred(), but rather implemented
hooks for setuid() and setgroups().  We however kept it, as it clearly
separates the machinery to pass data from dedicated system call hooks to
priv_grant() from the actual data that MAC/do needs to monitor a call to
setcred() specifically.  It may be useful in the future if we evolve
MAC/do to also grant privileges through other system calls (each seen as
a complete credentials transition on its own).

The target supplementary groups are checked with merge-like algorithms
leveraging the fact that all supplementary groups in credentials
('struct ucred') and in each rule ('struct rule') are sorted, avoiding
to start a binary search for each considered GID which is asymptotically
more costly.  All access granting/denial is thus at most linear and in
at most the sum of the number of requested groups, currently held ones
and those contained in the rule, per applicable rule.  This should be
enough in all practical cases.  There is however still room for more
optimizations, without or with changes in rules' data structures, if the
need ever arises.

Approved by:    markj (mentor)
Sponsored by:   The FreeBSD Foundation
Differential Revision:  https://reviews.freebsd.org/D47620

(cherry picked from commit 8f7e8726e3f5f20b9eed0ad12fc2d2a4ec304d14)
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
TL;DR:
Now monitor setcred() calls, and reject or grant them according to the
new rules specification.

Drop monitoring setuid() and setgroups().  As previously explained in
the commit introducing the setcred() system call, MAC/do must know the
entire new credentials while the old ones are still available to be able
to approve or reject the requested changes.  To this end, the chosen
approach was to introduce a new system call, setcred(), instead of
modifying existing ones to be able to participate in a "prepare than
commit"-like protocol.

******

The MAC framework typically calls several hooks of its registered
policies as part of the privilege checking/granting process.  Each
system call calls some dedicated hook early, to which it usually passes
the same arguments it received, whose goal is to forcibly deny access to
the functionality when needed (i.e., a single deny by any policy
globally denies the access).  Then, the system call usually calls
priv_check() or priv_check_cred() an unspecified number of times, each
of which may trigger calls to two generic MAC hooks.  The first such
call is to mac_priv_check(), and always happens.  Its role is to deny
access early and forcibly, as can be done also in system calls'
dedicated early hooks (with different reach, however).  The second,
mac_priv_grant(), is called only if the priv_check*() and
prison_priv_check() generic code doesn't handle the request by itself,
i.e., doesn't explicitly grant access (to the super user, or to all
users for a few specific privileges).  It allows any single policy to
grant the requested access (regardless of whether the other policies do
so or not).

MAC/do currently only has an effect on processes spawned from the
'/usr/bin/mdo' executable.  It implements all setcred() hooks, called
via mac_cred_setcred_enter(), mac_cred_check_setcred() and
mac_cred_setcred_exit().  In the first one, implemented in
mac_do_setcred_enter(), it checks if MAC/do has to apply to the current
process, allocates (or re-uses) per-thread data to be later used by the
other hooks (those of setcred() and the mac_priv_grant() one, called by
priv_check*()) and fills them with the current context (the rules to
apply).  This is both because memory allocations cannot be performed
while holding the process lock and to ensure that all hooks called by
a single setcred() see the same rules to apply (not doing this would be
a security hazard as rules are concurrently changed by the
administrator, as explained in more details below).  In the second one
(implemented by mac_do_check_setcred()), it stores in MAC/do's
per-thread data the new credentials.  Indeed, the next MAC/do's hook
implementation to be called, mac_do_priv_grant() (implementing the
mac_priv_grant() hook) must have knowledge of the new credentials that
setcred() wants to install in order to validate them (or not), which the
MAC framework can't provide as the priv_check*() API only passes the
current credentials and a specific privilege number to the
mac_priv_check() and mac_priv_grant() hooks.  By contrast, the very
point of MAC/do is to grant the privilege of changing credentials not
only based on the current ones but also on the seeked-for ones.

The MAC framework's constraints that mac_priv_grant() hooks are called
without context and that MAC modules must compose (each module may
implement any of the available hooks, and in particular those of
setcred()) impose some aspects of MAC/do's design.  Because MAC/do's
rules are tied to jails, accessing the current rules requires holding
the corresponding jail's lock.  As other policies might try to grab the
same jail's lock in the same hooks, it is not possible to keep the
rules' jail's lock between mac_do_setcred_enter() and
mac_do_priv_grant() to ensure that the rules are still alive.  We have
thus augmented 'struct rules' with a reference count, and its lifecyle
is now decoupled from being referenced or not by a jail.  As a thread
enters mac_cred_setcred_enter(), it grabs a hold on the current rules
and keeps a pointer to them in the per-thread data.  In its
mac_do_setcred_exit(), MAC/do just "frees" the per-thread data, in
particular by dropping the referenced rules (we wrote "frees" within
guillemets, as in fact the per-thread structure is reused, and only
freed when a thread exits or the module is unloaded).

Additionally, ensuring that all hooks have a consistent view of the
rules to apply might become crucial if we augment MAC/do with forceful
access denial policies in the future (i.e., policies that forcibly
disable access regardless of other MAC policies wanting to grant that
access).  Indeed, without the above-mentioned design, if newly installed
rules start to forcibly deny some specific transitions, and some thread
is past the mac_cred_check_setcred() hook but before the
mac_priv_grant() one, the latter may grant some privileges that should
have been rejected first by the former (depending on the content of
user-supplied rules).

A previous version of this change used to implement access denial
mandated by the '!' and '-' GID flags in mac_do_check_setcred() with the
goal to have this rejection prevail over potential other MAC modules
authorizing the transition.  However, this approach had two drawbacks.
First, it was incompatible both conceptually and in the current
implementation with multiple rules being treated as an inclusive
disjunction, where any single rule granting access is enough for MAC/do
to grant access.  Explicit denial requested by one matching rule could
prevent another rule from granting access.  The implementation could
have been fixed, but the conflation of rules being considered as
disjoint for explicit granting but conjunct for forced denial would have
remained.  Second, MAC/do applies only to processes spawned from
a particular executable, and imposing system-wide restrictions on only
these processes is conceptually strange and probably not very useful.
In the end, we moved the implementation of explicit access denial into
mac_do_priv_grant(), along with the interpretation of other target
clauses.

The separate definition of 'struct mac_do_data_header' may seem odd, as
it is only used in 'struct mac_do_setcred_data'.  It is a remnant of an
earlier version that was not using setcred(), but rather implemented
hooks for setuid() and setgroups().  We however kept it, as it clearly
separates the machinery to pass data from dedicated system call hooks to
priv_grant() from the actual data that MAC/do needs to monitor a call to
setcred() specifically.  It may be useful in the future if we evolve
MAC/do to also grant privileges through other system calls (each seen as
a complete credentials transition on its own).

The target supplementary groups are checked with merge-like algorithms
leveraging the fact that all supplementary groups in credentials
('struct ucred') and in each rule ('struct rule') are sorted, avoiding
to start a binary search for each considered GID which is asymptotically
more costly.  All access granting/denial is thus at most linear and in
at most the sum of the number of requested groups, currently held ones
and those contained in the rule, per applicable rule.  This should be
enough in all practical cases.  There is however still room for more
optimizations, without or with changes in rules' data structures, if the
need ever arises.

Approved by:    markj (mentor)
Sponsored by:   The FreeBSD Foundation
Differential Revision:  https://reviews.freebsd.org/D47620

(cherry picked from commit 8f7e8726e3f5f20b9eed0ad12fc2d2a4ec304d14)
</pre>
</div>
</content>
</entry>
</feed>
