tech-kern archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: secmodel_register(9) API
(I am CC'ing Elad, as we both worked on it)
On Mon, 5 Dec 2011 16:22:33 +0100, Christoph Badura wrote:
That is by design. The idea behind splitting the decision process
into
separate secmodels is to decouple the models and the decision making.
I can't see how -- secmodels are responsible for the decision making,
so we cannot decouple these easily.
So, when one wants to create sysctls that can only be changed when
securelevel is below a certain level, you end up adding more hooks
to
secmodel_securelevel(9)...
That is intentional. Every time a new control is added all the
secmodels
need to be examined if they need updating.
which is problematic, because the sysctl does
not necessarily belong to this secmodel (consider curtain and suser,
as
an exemple).
Uh, sysctls do not "belong to a secmodel". Whatever that is supposed
to
mean.
Okay, let's put that differently: enabling/disabling a security feature
like curtain has nothing to do with secmodel_suser(9) itself. Curtain is
a feature that says: "only owners of an object can query information
about it." So securelevel, suser, or bsd44... do not intervene in this
process, _except_ when you are root (pragmatism always add exceptions).
That's it.
But the "am I root?" evaluation is more an exception than the rule (a
weak dependency). Turning curtain into a full fledged suser extension
because there is one slight divergence is problematic.
error = secmodel_eval("org.netbsd.secmodel.suser", "is-root",
cred, &isroot, NULL);
This one asks the suser module if the user cred is assumed to be
root when evaluated by suser module. If the module is present, it
will respond. If absent, the call will return an error.
This so-called "API" is a complete perversion of the kauth system.
It
pulls the implementation details that the other secmodel is supposed
to hide and abstract away out into unrelated code again.
That's weird: what you describe here is the situation before this
patch: curtain and usermount were "planted" inside a secmodel they do
not belong to (secmodel_suser is about making decisions about root's
rights, not ordinary users).
This is adding
back all the interdependencies and knowledge about internals that
kauth
is supposed to abstract and hide.
That's precisely what we are trying to avoid.
Knowledge about internals were the de facto standard before: if you
wanted to have an extension which implements a policy ("users can only
see state of their objects") with an explicit dependency on
implementation internals ("is that user privileged?"), you had to put
the extension inside the secmodel(9) that implements the privileged
evaluation.
The problem with this is that it doesn't scale. You are just
arbitrarily
moving the code around that needs to be modified when new actions
need to
be authorized.
No; we are allowing secmodel(9) to expose evaluation logic ("a
question") to other secmodels, so they can query for a result that
depends on their internals.
The ultimate decision remains in the hand of the one making the query.
Asking a question in the form of "do you allow that action to happen?"
is a plain miss-use of this API; that should indeed be done by kauth(9).
It doesn't scale in the case when a new secmodel is introduced that
needs to have a say on this action.
The evaluation API is not designed to accept hooks, nor shall it be.
It's meant for a secmodel(9) to query "safely" (as is: no
symbol/run-time dependency on code being loaded) a secmodel for internal
state ("are you in this state?") or internal logic ("given these
credentials, do you consider them privileged or not?").
And it doesn't scale when bsd44
or suser is replace with a secmodel that defines "privilege" other
than
"is-root".
It should not. If there's another secmodel that appears later that
redefines "privilege", that secmodel will have to expose evaluation
callback and let the curtain extension handle it.
For the "is-root" case, the evaluation will return an error if the
secmodel_suser(9) is not loaded. The curtain extension will then make
the decision concerning this, and fallback to its default case.
IAW not even does this not scale from 1 to 2. It doesn't even scale
from
A to B.
Args and command are arbitrarily defined; it's up to the secmodel(9)
to explain what it expects.
This is even worse. The type-unsafety of kauth_authorize_action is
bad
enough. There is no reason to make it worse by introducing a
variadic
function in a security context.
IMNHO this idea alone is reason enough to back this out and have it
redesigned.
I am not quite sure that the type-usnafety of kauth_authorize_action(9)
is really kauth's fault, but more a shortcoming of the langage used.
Serious type-safety is not something to expect from C.
Typical example is securelevel testing: when someone wants to know
whether securelevel is raised above a certain level or not, the
caller has to request this property to the secmodel_securelevel(9)
module. Given that securelevel module may be absent from system's
context (thus making access to the global "securelevel" variable
impossible or unsafe), this API can cope with this absence and
return an error.
This isn't a typical example. There's only one entity in the kernel
that
wants to know whether securelevel is raised: secmodel_securelevel.
The typical example is that the kernel wants to ask the secmodels:
"are
these credentials authorized to perform the action detailled in the
remaining argument?".
And if the securelevel secmodel is loaded that sometimes says "yay"
or
"nay" for the cases that it is interested in.
In other words, you are asking the wrong questions and thinking about
this in an incorrect way. Therefore you end up at incorrect
solutions.
Right, dependency inversion. Let's do it that way then.
How are you suppose to allow/deny the modification of "curtain" based
on securelevel?
- you start passing arguments to describe the curtain sysctl(7) so that
secmodel_securelevel(9) knows that we are trying to modify "curtain".
- you add evaluation logic inside securelevel(9) so it can allow/deny
this action (you can always enable curtain, but never disable it when
securelevel > 0)
- you end up implementing _all_ sysctl management inside
securelevel(9). So now, instead of exposing a fraction of the
securelevel internals to other secmodels, you expose other secmodels
internals to securelevel(9).
You cannot really end up with a clear separation of concerns here;
either securelevel is in charge and knows about curtain. Or curtain is
in charge and knows about securelevel.
On Tue, Nov 29, 2011 at 01:58:20PM +0100, Jean-Yves Migeon wrote:
On Tue, 29 Nov 2011 11:13:01 +0000 (UTC), yamt%mwd.biglobe.ne.jp@localhost
wrote:
Consider user_set_cpu_affinity: if the sysctl cannot be set any more
when securelevel is above or below a threshold, checking for the
securelevel variable means that this sysctl has a strong dependency
on securelevel (or else, it won't be able to get the variable). So
if you want to still provide this sysctl but without having
securelevel loaded, you are screwed: it's part of this module.
There is no need for the code that manages user_set_cpu_affinity to
have
a dependency on the securelevel variable. Or even to know about it
in the
first place.
All that is need is a call to kauth_authorize_action asking if it is
allowed to modify the variable bound to the sysctl name.
This is precisly the reason that the indirection level that kauth
provides
has been introduced.
You are starting from false premises.
As said above for curtain: any of the two _will_ end up knowing
internals of the other. Remember: user_set_cpu_affinity cannot be
enabled when securelevel is 1+, but can still be disabled (if it was
enabled beforehand). If you implement this logic inside securelevel(9),
you are implementing user_set_cpu_affinity control inside securelevel.
securelevel ends up knowing more about user_set_cpu_affinity than it
ought to.
Given that sysctl IDs are created dynamically, what solution is
available to securelevel(9) to know that the authorization call is about
user_set_cpu_affinity, and not another node?
If curtain doesn't want to know about the internals of kauth_cred it
should do it's own user tracking and attach that data to kauth_cred's
specificdata. That's what that interface is for. And it worked just
fine for gaols.
And curtain ends up asking suser "is user privileged?" to set the
specificdata key. We are moving the problem around, not solving it.
For convenience, curtain may allow specific credentials to gather
information for all objects, and not just the ones a user owns.
Distinguishing credentials and giving some of them higher privileges
is entirely internal to a secmodel. That is why curtain should do
its own user tracking through kauth_cred's specificdata.
When
suser is loaded, thes credentials are those corresponding to root.
That, however, is at suser's discretion to decide. I.e. curtain
should
not know about the internals of suser or what kind of credentials it
considers privileged for which operations.
If curtain wants to be truly independent of other secmodel's internal
then
it needs to track itself which credentials it considers privileged.
It can't; in the case of suser(), it has to ask to secmodel_suser(9)
whether this user is deemed privileged or not. Otherwise, curtain will
deny super-user to gather information about objects it does not own.
[snip]
What you have is a requirement that changing sysctl variable that
control
that behaviour (curtain and user_set_cpu_affinity) requires
privilege.
How that privilege is granted and checked depends on the secmodels
that
are currently active.
E.g. if only suser is available conventionally only root would be
able to
change these sysctl variables.
If securelevel is available that secmodel may restrict the operation
based on the setting of the securelevel variable.
If some other secmodel is loaded then that has a say on that matter
too.
Maybe it counts the demons in the users nose.
And if only that other secmodel is loaded then being able to change
those sysctl variable may only depend on the number of demons in your
nose.
It is intentional that there is no strong coupling between secmodels.
and kauth_authorize is a much better interface for checking for
privilege
than the proposed secmodel_eval.
Please stop with that one; me and Elad agreed right from the start (I
can send the private mails if you want them) that secmodel_eval(9) _is_
_not_ meant as an alternative for authorization call, and should never
be used as such. It allows a secmodel to expose internal code evaluation
logic to the outside world at his own discretion.
--
Jean-Yves Migeon
jeanyves.migeon%free.fr@localhost
Home |
Main Index |
Thread Index |
Old Index