[PATCH v3 4/4] selinux: log invalid contexts in AVCs

Paul Moore paul at paul-moore.com
Fri Jan 25 22:35:03 UTC 2019


On Fri, Jan 25, 2019 at 5:07 AM Ondrej Mosnacek <omosnace at redhat.com> wrote:
>
> In case a file has an invalid context set, in an AVC record generated
> upon access to such file, the target context is always reported as
> unlabeled. This patch adds new optional fields to the AVC record
> (srawcon and trawcon) that report the actual context string if it
> differs from the one reported in scontext/tcontext. This is useful for
> diagnosing SELinux denials involving invalid contexts.
>
> To trigger an AVC that illustrates this situation:
>
>     # setenforce 0
>     # touch /tmp/testfile
>     # setfattr -n security.selinux -v system_u:object_r:banana_t:s0 /tmp/testfile
>     # runcon system_u:system_r:sshd_t:s0 cat /tmp/testfile
>
> AVC before:
>
> type=AVC msg=audit(1547801083.248:11): avc:  denied  { open } for  pid=1149 comm="cat" path="/tmp/testfile" dev="tmpfs" ino=6608 scontext=system_u:system_r:sshd_t:s0 tcontext=system_u:object_r:unlabeled_t:s15:c0.c1023 tclass=file permissive=1
>
> AVC after:
>
> type=AVC msg=audit(1547801083.248:11): avc:  denied  { open } for  pid=1149 comm="cat" path="/tmp/testfile" dev="tmpfs" ino=6608 scontext=system_u:system_r:sshd_t:s0 tcontext=system_u:object_r:unlabeled_t:s15:c0.c1023 tclass=file permissive=1 trawcon=system_u:object_r:banana_t:s0
>
> Note that it is also possible to encounter this situation with the
> 'scontext' field - e.g. when a new policy is loaded while a process is
> running, whose context is not valid in the new policy.
>
> Cc: Daniel Walsh <dwalsh at redhat.com>
> Link: https://bugzilla.redhat.com/show_bug.cgi?id=1135683
> Signed-off-by: Ondrej Mosnacek <omosnace at redhat.com>
> ---
>  security/selinux/avc.c              | 15 ++++++++++++
>  security/selinux/include/security.h |  3 +++
>  security/selinux/ss/services.c      | 37 +++++++++++++++++++++++++----
>  3 files changed, 50 insertions(+), 5 deletions(-)

Merged, thanks.

> diff --git a/security/selinux/avc.c b/security/selinux/avc.c
> index 478fa4213c25..047de65589bd 100644
> --- a/security/selinux/avc.c
> +++ b/security/selinux/avc.c
> @@ -734,6 +734,21 @@ static void avc_audit_post_callback(struct audit_buffer *ab, void *a)
>
>         if (sad->denied)
>                 audit_log_format(ab, " permissive=%u", sad->result ? 0 : 1);
> +
> +       /* in case of invalid context report also the actual context string */
> +       rc = security_sid_to_context_inval(sad->state, sad->ssid, &scontext,
> +                                          &scontext_len);
> +       if (!rc && scontext) {
> +               audit_log_format(ab, " srawcon=%s", scontext);
> +               kfree(scontext);
> +       }
> +
> +       rc = security_sid_to_context_inval(sad->state, sad->tsid, &scontext,
> +                                          &scontext_len);
> +       if (!rc && scontext) {
> +               audit_log_format(ab, " trawcon=%s", scontext);
> +               kfree(scontext);
> +       }
>  }
>
>  /* This is the slow part of avc audit with big stack footprint */
> diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
> index ba8eedf42b90..f68fb25b5702 100644
> --- a/security/selinux/include/security.h
> +++ b/security/selinux/include/security.h
> @@ -255,6 +255,9 @@ int security_sid_to_context(struct selinux_state *state, u32 sid,
>  int security_sid_to_context_force(struct selinux_state *state,
>                                   u32 sid, char **scontext, u32 *scontext_len);
>
> +int security_sid_to_context_inval(struct selinux_state *state,
> +                                 u32 sid, char **scontext, u32 *scontext_len);
> +
>  int security_context_to_sid(struct selinux_state *state,
>                             const char *scontext, u32 scontext_len,
>                             u32 *out_sid, gfp_t gfp);
> diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
> index dd44126c8d14..9be05c3e99dc 100644
> --- a/security/selinux/ss/services.c
> +++ b/security/selinux/ss/services.c
> @@ -1281,7 +1281,8 @@ const char *security_get_initial_sid_context(u32 sid)
>
>  static int security_sid_to_context_core(struct selinux_state *state,
>                                         u32 sid, char **scontext,
> -                                       u32 *scontext_len, int force)
> +                                       u32 *scontext_len, int force,
> +                                       int only_invalid)
>  {
>         struct policydb *policydb;
>         struct sidtab *sidtab;
> @@ -1326,8 +1327,14 @@ static int security_sid_to_context_core(struct selinux_state *state,
>                 rc = -EINVAL;
>                 goto out_unlock;
>         }
> -       rc = context_struct_to_string(policydb, context, scontext,
> -                                     scontext_len);
> +       if (only_invalid && !context->len) {
> +               scontext = NULL;
> +               scontext_len = 0;
> +               rc = 0;
> +       } else {
> +               rc = context_struct_to_string(policydb, context, scontext,
> +                                             scontext_len);
> +       }
>  out_unlock:
>         read_unlock(&state->ss->policy_rwlock);
>  out:
> @@ -1349,14 +1356,34 @@ int security_sid_to_context(struct selinux_state *state,
>                             u32 sid, char **scontext, u32 *scontext_len)
>  {
>         return security_sid_to_context_core(state, sid, scontext,
> -                                           scontext_len, 0);
> +                                           scontext_len, 0, 0);
>  }
>
>  int security_sid_to_context_force(struct selinux_state *state, u32 sid,
>                                   char **scontext, u32 *scontext_len)
>  {
>         return security_sid_to_context_core(state, sid, scontext,
> -                                           scontext_len, 1);
> +                                           scontext_len, 1, 0);
> +}
> +
> +/**
> + * security_sid_to_context_inval - Obtain a context for a given SID if it
> + *                                 is invalid.
> + * @sid: security identifier, SID
> + * @scontext: security context
> + * @scontext_len: length in bytes
> + *
> + * Write the string representation of the context associated with @sid
> + * into a dynamically allocated string of the correct size, but only if the
> + * context is invalid in the current policy.  Set @scontext to point to
> + * this string (or NULL if the context is valid) and set @scontext_len to
> + * the length of the string (or 0 if the context is valid).
> + */
> +int security_sid_to_context_inval(struct selinux_state *state, u32 sid,
> +                                 char **scontext, u32 *scontext_len)
> +{
> +       return security_sid_to_context_core(state, sid, scontext,
> +                                           scontext_len, 1, 1);
>  }
>
>  /*
> --
> 2.20.1
>


-- 
paul moore
www.paul-moore.com




More information about the Linux-audit mailing list