Re: [PATCH v2] selinux: log policy capability state when a policy is loaded

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, 2017-05-16 at 17:19 -0400, Paul Moore wrote:
> On Tue, May 16, 2017 at 5:11 PM, Stephen Smalley <sds@xxxxxxxxxxxxx>
> wrote:
> > On Tue, 2017-05-16 at 16:56 -0400, Paul Moore wrote:
> > > On Fri, May 12, 2017 at 12:44 PM, Stephen Smalley <sds@xxxxxxxxx.
> > > gov>
> > > wrote:
> > > > Log the state of SELinux policy capabilities when a policy is
> > > > loaded.
> > > > For each policy capability known to the kernel, log an
> > > > informational
> > > > message with the policy capability name and the value set in
> > > > the
> > > > policy.
> > > > For policy capabilities that are set in the loaded policy but
> > > > unknown
> > > > to the kernel, log a warning with the policy capability index,
> > > > since
> > > > this is the only information presently available in the policy.
> > > > 
> > > > Sample output with a policy created with a new capability
> > > > defined
> > > > that is not known to the kernel:
> > > > [   43.812265] SELinux:  policy capability
> > > > network_peer_controls=1
> > > > [   43.812266] SELinux:  policy capability open_perms=1
> > > > [   43.812266] SELinux:  policy capability
> > > > extended_socket_class=1
> > > > [   43.812267] SELinux:  policy capability
> > > > always_check_network=0
> > > > [   43.812267] SELinux:  policy capability cgroup_seclabel=0
> > > > [   43.812268] SELinux:  unknown policy capability 5
> > > > 
> > > > Signed-off-by: Stephen Smalley <sds@xxxxxxxxxxxxx>
> > > > ---
> > > > v2 drops the Resolves line since I think we are not supposed to
> > > > include
> > > > bug tracking info in upstream kernel commit messages (correct
> > > > me if
> > > > wrong).
> > > > 
> > > >  security/selinux/include/security.h |  2 ++
> > > >  security/selinux/selinuxfs.c        | 13 ++-----------
> > > >  security/selinux/ss/services.c      | 23
> > > > +++++++++++++++++++++++
> > > >  3 files changed, 27 insertions(+), 11 deletions(-)
> > > > 
> > > > diff --git a/security/selinux/include/security.h
> > > > b/security/selinux/include/security.h
> > > > index f979c35..c4224bb 100644
> > > > --- a/security/selinux/include/security.h
> > > > +++ b/security/selinux/include/security.h
> > > > @@ -76,6 +76,8 @@ enum {
> > > >  };
> > > >  #define POLICYDB_CAPABILITY_MAX (__POLICYDB_CAPABILITY_MAX -
> > > > 1)
> > > > 
> > > > +extern char
> > > > *selinux_policycap_names[__POLICYDB_CAPABILITY_MAX];
> > > > +
> > > >  extern int selinux_policycap_netpeer;
> > > >  extern int selinux_policycap_openperm;
> > > >  extern int selinux_policycap_extsockclass;
> > > > diff --git a/security/selinux/selinuxfs.c
> > > > b/security/selinux/selinuxfs.c
> > > > index ce71718..ea2da91 100644
> > > > --- a/security/selinux/selinuxfs.c
> > > > +++ b/security/selinux/selinuxfs.c
> > > > @@ -41,15 +41,6 @@
> > > >  #include "objsec.h"
> > > >  #include "conditional.h"
> > > > 
> > > > -/* Policy capability filenames */
> > > > -static char *policycap_names[] = {
> > > > -       "network_peer_controls",
> > > > -       "open_perms",
> > > > -       "extended_socket_class",
> > > > -       "always_check_network",
> > > > -       "cgroup_seclabel"
> > > > -};
> > > > -
> > > >  unsigned int selinux_checkreqprot =
> > > > CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE;
> > > > 
> > > >  static int __init checkreqprot_setup(char *str)
> > > > @@ -1750,9 +1741,9 @@ static int sel_make_policycap(void)
> > > >         sel_remove_entries(policycap_dir);
> > > > 
> > > >         for (iter = 0; iter <= POLICYDB_CAPABILITY_MAX; iter++)
> > > > {
> > > > -               if (iter < ARRAY_SIZE(policycap_names))
> > > > +               if (iter < ARRAY_SIZE(selinux_policycap_names))
> > > >                         dentry = d_alloc_name(policycap_dir,
> > > > -                                             policycap_names[i
> > > > ter]
> > > > );
> > > > +                                             selinux_policycap
> > > > _nam
> > > > es[iter]);
> > > >                 else
> > > >                         dentry = d_alloc_name(policycap_dir,
> > > > "unknown");
> > > > 
> > > > diff --git a/security/selinux/ss/services.c
> > > > b/security/selinux/ss/services.c
> > > > index 60d9b02..0abdec2 100644
> > > > --- a/security/selinux/ss/services.c
> > > > +++ b/security/selinux/ss/services.c
> > > > @@ -70,6 +70,15 @@
> > > >  #include "ebitmap.h"
> > > >  #include "audit.h"
> > > > 
> > > > +/* Policy capability names */
> > > > +char *selinux_policycap_names[__POLICYDB_CAPABILITY_MAX] = {
> > > > +       "network_peer_controls",
> > > > +       "open_perms",
> > > > +       "extended_socket_class",
> > > > +       "always_check_network",
> > > > +       "cgroup_seclabel"
> > > > +};
> > > > +
> > > >  int selinux_policycap_netpeer;
> > > >  int selinux_policycap_openperm;
> > > >  int selinux_policycap_extsockclass;
> > > > @@ -1986,6 +1995,9 @@ static int convert_context(u32 key,
> > > > 
> > > >  static void security_load_policycaps(void)
> > > >  {
> > > > +       unsigned int i;
> > > > +       struct ebitmap_node *node;
> > > > +
> > > >         selinux_policycap_netpeer =
> > > > ebitmap_get_bit(&policydb.policycaps,
> > > >                                                   POLICYDB_CAPA
> > > > BILI
> > > > TY_NETPEER);
> > > >         selinux_policycap_openperm =
> > > > ebitmap_get_bit(&policydb.policycaps,
> > > > @@ -1997,6 +2009,17 @@ static void
> > > > security_load_policycaps(void)
> > > >         selinux_policycap_cgroupseclabel =
> > > >                 ebitmap_get_bit(&policydb.policycaps,
> > > >                                 POLICYDB_CAPABILITY_CGROUPSECLA
> > > > BEL)
> > > > ;
> > > > +
> > > > +       for (i = 0; i < ARRAY_SIZE(selinux_policycap_names);
> > > > i++)
> > > > +               pr_info("SELinux:  policy capability %s=%d\n",
> > > > +                       selinux_policycap_names[i],
> > > > +                       ebitmap_get_bit(&policydb.policycaps,
> > > > i));
> > > > +
> > > > +       ebitmap_for_each_positive_bit(&policydb.policycaps,
> > > > node,
> > > > i) {
> > > > +               if (i >= ARRAY_SIZE(selinux_policycap_names))
> > > > +                       pr_warn("SELinux:  unknown policy
> > > > capability %u\n",
> > > > +                               i);
> > > 
> > > Should this really be KERN_WARN?  An undefined policy capability
> > > may
> > > be odd, but it doesn't seem like it warrants "warning" status;
> > > while
> > > not quite apples-to-apples, missing classes/perms are displayed
> > > with
> > > KERN_NOTICE.
> > 
> > If the kernel does not support a policy capability that was enabled
> > in
> > the policy, then it may not be capable of enforcing the policy as
> > intended, and may therefore be operating insecurely (e.g. consider
> > if
> > your kernel was too old to support network_peer_controls or
> > always_check_network or open_perms but your policy has enabled them
> > and
> > is relying on those checks to be present) ...
> 
> Well, I think the key is "may"; depending on the policy capability
> and
> the handle_unknown setting things might not fail in an insecure
> manner, but the system would definitely behave
> strangely.  Regardless,
> I see your point and I'm now wondering if we should just fail the
> policy load if we detect any policy capabilities beyond what we know
> about.

I think that would prove problematic in practice since the system would
then refuse to boot with such a policy (the only way to boot in Linux
distributions would then be to boot with enforcing=0 and come up with
no policy - requiring you to then replace the policy, reboot, and
relabel, and in Android you can't boot at all if policy load fails - it
will reboot into recovery mode).  It would mean that we could not add a
new policy capability to a policy until we were sure that no one was
still using a kernel that predated the support for it.  That would more
or less preclude new policy capabilities from ever being enabled by
default in refpolicy (or at least take years to introduce them), and
would also be a problem for Android, since many different kernel
versions (and often much older ones) are used with both.

A warning seemed like a reasonable middle ground between silently
ignoring unknown policy capabilities (as the kernel currently does
before this patch) and rejecting the policy altogether.  WARN vs INFO
was due to the fact that an unknown capability seemed more significant
and potentially an indicator of a kernel/policy mismatch than the state
of the known policy capabilities.

> 
> > With undefined classes/perms, the behavior is governed by
> > handle_unknown, so a policy built with handle_unknown=allow has
> > already
> > accepted the potential for unknown classes/permissions being
> > allowed,
> > while a policy built with handle_unknown=deny will fail closed/safe
> > and
> > thus not degrade in security.  Arguably though maybe those ought to
> > be
> > warnings too.
> 
> Possibly.  I'm less worried about that.



[Index of Archives]     [Selinux Refpolicy]     [Linux SGX]     [Fedora Users]     [Fedora Desktop]     [Yosemite Photos]     [Yosemite Camping]     [Yosemite Campsites]     [KDE Users]     [Gnome Users]

  Powered by Linux