On Mon, Apr 06, 2020 at 05:01:56PM -0700, Casey Schaufler wrote:
> Create a new audit record type to contain the subject information
> when there are multiple security modules that require such data.
> This record is emitted before the other records for the event, but
> is linked with the same timestamp and serial number.
> 
> Signed-off-by: Casey Schaufler <[email protected]>

Reviewed-by: Kees Cook <[email protected]>

-Kees

> Cc: [email protected]
> ---
>  drivers/android/binder.c                |  2 +-
>  include/linux/security.h                |  9 +++-
>  include/net/scm.h                       |  3 +-
>  include/uapi/linux/audit.h              |  1 +
>  kernel/audit.c                          | 56 +++++++++++++++++++------
>  kernel/auditsc.c                        |  7 ++--
>  net/ipv4/ip_sockglue.c                  |  2 +-
>  net/netfilter/nf_conntrack_netlink.c    |  4 +-
>  net/netfilter/nf_conntrack_standalone.c |  2 +-
>  net/netfilter/nfnetlink_queue.c         |  2 +-
>  net/netlabel/netlabel_unlabeled.c       | 11 +++--
>  net/netlabel/netlabel_user.c            |  2 +-
>  security/security.c                     | 51 ++++++++++++++++++++--
>  13 files changed, 118 insertions(+), 34 deletions(-)
> 
> diff --git a/drivers/android/binder.c b/drivers/android/binder.c
> index c76fc2abd091..e79c4948ab12 100644
> --- a/drivers/android/binder.c
> +++ b/drivers/android/binder.c
> @@ -3109,7 +3109,7 @@ static void binder_transaction(struct binder_proc *proc,
>               size_t added_size;
>  
>               security_task_getsecid(proc->tsk, &blob);
> -             ret = security_secid_to_secctx(&blob, &lsmctx);
> +             ret = security_secid_to_secctx(&blob, &lsmctx, LSMBLOB_DISPLAY);
>               if (ret) {
>                       return_error = BR_FAILED_REPLY;
>                       return_error_param = ret;
> diff --git a/include/linux/security.h b/include/linux/security.h
> index fac5547dd89e..896b939f5d62 100644
> --- a/include/linux/security.h
> +++ b/include/linux/security.h
> @@ -178,6 +178,8 @@ struct lsmblob {
>  #define LSMBLOB_INVALID              -1      /* Not a valid LSM slot number 
> */
>  #define LSMBLOB_NEEDED               -2      /* Slot requested on 
> initialization */
>  #define LSMBLOB_NOT_NEEDED   -3      /* Slot not requested */
> +#define LSMBLOB_DISPLAY              -4      /* Use the "display" slot */
> +#define LSMBLOB_FIRST                -5      /* Use the default "display" 
> slot */
>  
>  /**
>   * lsmblob_init - initialize an lsmblob structure.
> @@ -240,6 +242,8 @@ static inline u32 lsmblob_value(const struct lsmblob 
> *blob)
>       return 0;
>  }
>  
> +const char *security_lsm_slot_name(int slot);
> +
>  /* These functions are in security/commoncap.c */
>  extern int cap_capable(const struct cred *cred, struct user_namespace *ns,
>                      int cap, unsigned int opts);
> @@ -549,7 +553,8 @@ int security_setprocattr(const char *lsm, const char 
> *name, void *value,
>                        size_t size);
>  int security_netlink_send(struct sock *sk, struct sk_buff *skb);
>  int security_ismaclabel(const char *name);
> -int security_secid_to_secctx(struct lsmblob *blob, struct lsmcontext *cp);
> +int security_secid_to_secctx(struct lsmblob *blob, struct lsmcontext *cp,
> +                          int display);
>  int security_secctx_to_secid(const char *secdata, u32 seclen,
>                            struct lsmblob *blob);
>  void security_release_secctx(struct lsmcontext *cp);
> @@ -1354,7 +1359,7 @@ static inline int security_ismaclabel(const char *name)
>  }
>  
>  static inline int security_secid_to_secctx(struct lsmblob *blob,
> -                                        struct lsmcontext *cp)
> +                                        struct lsmcontext *cp, int display)
>  {
>       return -EOPNOTSUPP;
>  }
> diff --git a/include/net/scm.h b/include/net/scm.h
> index 4a6ad8caf423..8b5a4737e1b8 100644
> --- a/include/net/scm.h
> +++ b/include/net/scm.h
> @@ -96,7 +96,8 @@ static inline void scm_passec(struct socket *sock, struct 
> msghdr *msg, struct sc
>       int err;
>  
>       if (test_bit(SOCK_PASSSEC, &sock->flags)) {
> -             err = security_secid_to_secctx(&scm->lsmblob, &context);
> +             err = security_secid_to_secctx(&scm->lsmblob, &context,
> +                                            LSMBLOB_DISPLAY);
>  
>               if (!err) {
>                       put_cmsg(msg, SOL_SOCKET, SCM_SECURITY,
> diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
> index a534d71e689a..2e6dbf907ee3 100644
> --- a/include/uapi/linux/audit.h
> +++ b/include/uapi/linux/audit.h
> @@ -138,6 +138,7 @@
>  #define AUDIT_MAC_UNLBL_STCDEL       1417    /* NetLabel: del a static label 
> */
>  #define AUDIT_MAC_CALIPSO_ADD        1418    /* NetLabel: add CALIPSO DOI 
> entry */
>  #define AUDIT_MAC_CALIPSO_DEL        1419    /* NetLabel: del CALIPSO DOI 
> entry */
> +#define AUDIT_MAC_TASK_CONTEXTS      1420    /* Multiple LSM contexts */
>  
>  #define AUDIT_FIRST_KERN_ANOM_MSG   1700
>  #define AUDIT_LAST_KERN_ANOM_MSG    1799
> diff --git a/kernel/audit.c b/kernel/audit.c
> index 013a90dd2bd5..00a4fbecfdf7 100644
> --- a/kernel/audit.c
> +++ b/kernel/audit.c
> @@ -1419,7 +1419,7 @@ static int audit_receive_msg(struct sk_buff *skb, 
> struct nlmsghdr *nlh)
>       case AUDIT_SIGNAL_INFO:
>               if (lsmblob_is_set(&audit_sig_lsm)) {
>                       err = security_secid_to_secctx(&audit_sig_lsm,
> -                                                    &context);
> +                                                    &context, LSMBLOB_FIRST);
>                       if (err)
>                               return err;
>               }
> @@ -2058,28 +2058,58 @@ void audit_log_key(struct audit_buffer *ab, char *key)
>  
>  int audit_log_task_context(struct audit_buffer *ab)
>  {
> +     int i;
>       int error;
> +     bool sep = false;
>       struct lsmblob blob;
> -     struct lsmcontext context;
> +     struct lsmcontext lsmdata;
> +     struct audit_buffer *lsmab = NULL;
> +     struct audit_context *context = NULL;
>  
>       security_task_getsecid(current, &blob);
>       if (!lsmblob_is_set(&blob))
>               return 0;
>  
> -     error = security_secid_to_secctx(&blob, &context);
> -     if (error) {
> -             if (error != -EINVAL)
> -                     goto error_path;
> -             return 0;
> +     /*
> +      * If there is more than one security module that has a
> +      * subject "context" it's necessary to put the subject data
> +      * into a separate record to maintain compatibility.
> +      */
> +     if (security_lsm_slot_name(1) != NULL) {
> +             audit_log_format(ab, " subj=?");
> +             context = ab->ctx;
> +             if (context)
> +                     lsmab = audit_log_start(context, GFP_KERNEL,
> +                                             AUDIT_MAC_TASK_CONTEXTS);
>       }
>  
> -     audit_log_format(ab, " subj=%s", context.context);
> -     security_release_secctx(&context);
> -     return 0;
> +     for (i = 0; i < LSMBLOB_ENTRIES; i++) {
> +             if (blob.secid[i] == 0)
> +                     continue;
> +             error = security_secid_to_secctx(&blob, &lsmdata, i);
> +             if (error && error != -EINVAL) {
> +                     audit_panic("error in audit_log_task_context");
> +                     return error;
> +             }
> +
> +             if (context) {
> +                     audit_log_format(lsmab, "%ssubj_%s=%s",
> +                                      sep ? " " : "",
> +                                      security_lsm_slot_name(i),
> +                                      lsmdata.context);
> +                     sep = true;
> +             } else
> +                     audit_log_format(ab, " subj=%s", lsmdata.context);
> +
> +             security_release_secctx(&lsmdata);
> +             if (!context)
> +                     break;
> +     }
> +
> +     if (context)
> +             audit_log_end(lsmab);
>  
> -error_path:
> -     audit_panic("error in audit_log_task_context");
> -     return error;
> +     return 0;
>  }
>  EXPORT_SYMBOL(audit_log_task_context);
>  
> diff --git a/kernel/auditsc.c b/kernel/auditsc.c
> index b7275860ba5f..4df540c32581 100644
> --- a/kernel/auditsc.c
> +++ b/kernel/auditsc.c
> @@ -980,7 +980,7 @@ static int audit_log_pid_context(struct audit_context 
> *context, pid_t pid,
>                        from_kuid(&init_user_ns, auid),
>                        from_kuid(&init_user_ns, uid), sessionid);
>       if (lsmblob_is_set(blob)) {
> -             if (security_secid_to_secctx(blob, &lsmctx)) {
> +             if (security_secid_to_secctx(blob, &lsmctx, LSMBLOB_FIRST)) {
>                       audit_log_format(ab, " obj=(none)");
>                       rc = 1;
>               } else {
> @@ -1225,7 +1225,8 @@ static void show_special(struct audit_context *context, 
> int *call_panic)
>                       struct lsmblob blob;
>  
>                       lsmblob_init(&blob, osid);
> -                     if (security_secid_to_secctx(&blob, &lsmcxt)) {
> +                     if (security_secid_to_secctx(&blob, &lsmcxt,
> +                                                  LSMBLOB_FIRST)) {
>                               audit_log_format(ab, " osid=%u", osid);
>                               *call_panic = 1;
>                       } else {
> @@ -1377,7 +1378,7 @@ static void audit_log_name(struct audit_context 
> *context, struct audit_names *n,
>               struct lsmcontext lsmctx;
>  
>               lsmblob_init(&blob, n->osid);
> -             if (security_secid_to_secctx(&blob, &lsmctx)) {
> +             if (security_secid_to_secctx(&blob, &lsmctx, LSMBLOB_FIRST)) {
>                       audit_log_format(ab, " osid=%u", n->osid);
>                       if (call_panic)
>                               *call_panic = 2;
> diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
> index 27af7a6b8780..10b418029cdd 100644
> --- a/net/ipv4/ip_sockglue.c
> +++ b/net/ipv4/ip_sockglue.c
> @@ -138,7 +138,7 @@ static void ip_cmsg_recv_security(struct msghdr *msg, 
> struct sk_buff *skb)
>       if (err)
>               return;
>  
> -     err = security_secid_to_secctx(&lb, &context);
> +     err = security_secid_to_secctx(&lb, &context, LSMBLOB_DISPLAY);
>       if (err)
>               return;
>  
> diff --git a/net/netfilter/nf_conntrack_netlink.c 
> b/net/netfilter/nf_conntrack_netlink.c
> index 2fa1e5bd781d..cd559fada596 100644
> --- a/net/netfilter/nf_conntrack_netlink.c
> +++ b/net/netfilter/nf_conntrack_netlink.c
> @@ -337,7 +337,7 @@ static int ctnetlink_dump_secctx(struct sk_buff *skb, 
> const struct nf_conn *ct)
>        * security_secid_to_secctx() will know which security module
>        * to use to create the secctx.  */
>       lsmblob_init(&blob, ct->secmark);
> -     ret = security_secid_to_secctx(&blob, &context);
> +     ret = security_secid_to_secctx(&blob, &context, LSMBLOB_DISPLAY);
>       if (ret)
>               return 0;
>  
> @@ -651,7 +651,7 @@ static inline int ctnetlink_secctx_size(const struct 
> nf_conn *ct)
>       struct lsmblob blob;
>       struct lsmcontext context;
>  
> -     ret = security_secid_to_secctx(&blob, &context);
> +     ret = security_secid_to_secctx(&blob, &context, LSMBLOB_DISPLAY);
>       if (ret)
>               return 0;
>  
> diff --git a/net/netfilter/nf_conntrack_standalone.c 
> b/net/netfilter/nf_conntrack_standalone.c
> index 383a4f44be63..9551e8be6ca4 100644
> --- a/net/netfilter/nf_conntrack_standalone.c
> +++ b/net/netfilter/nf_conntrack_standalone.c
> @@ -177,7 +177,7 @@ static void ct_show_secctx(struct seq_file *s, const 
> struct nf_conn *ct)
>       struct lsmcontext context;
>  
>       lsmblob_init(&blob, ct->secmark);
> -     ret = security_secid_to_secctx(&blob, &context);
> +     ret = security_secid_to_secctx(&blob, &context, LSMBLOB_DISPLAY);
>       if (ret)
>               return;
>  
> diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
> index d07900c317fd..dc8902f8cea2 100644
> --- a/net/netfilter/nfnetlink_queue.c
> +++ b/net/netfilter/nfnetlink_queue.c
> @@ -316,7 +316,7 @@ static u32 nfqnl_get_sk_secctx(struct sk_buff *skb, 
> struct lsmcontext *context)
>                * blob. security_secid_to_secctx() will know which security
>                * module to use to create the secctx.  */
>               lsmblob_init(&blob, skb->secmark);
> -             security_secid_to_secctx(&blob, context);
> +             security_secid_to_secctx(&blob, context, LSMBLOB_DISPLAY);
>       }
>  
>       read_unlock_bh(&skb->sk->sk_callback_lock);
> diff --git a/net/netlabel/netlabel_unlabeled.c 
> b/net/netlabel/netlabel_unlabeled.c
> index c14a485ff045..d816909866cc 100644
> --- a/net/netlabel/netlabel_unlabeled.c
> +++ b/net/netlabel/netlabel_unlabeled.c
> @@ -437,7 +437,8 @@ int netlbl_unlhsh_add(struct net *net,
>  unlhsh_add_return:
>       rcu_read_unlock();
>       if (audit_buf != NULL) {
> -             if (security_secid_to_secctx(lsmblob, &context) == 0) {
> +             if (security_secid_to_secctx(lsmblob, &context,
> +                                          LSMBLOB_FIRST) == 0) {
>                       audit_log_format(audit_buf, " sec_obj=%s",
>                                        context.context);
>                       security_release_secctx(&context);
> @@ -492,7 +493,8 @@ static int netlbl_unlhsh_remove_addr4(struct net *net,
>               if (dev != NULL)
>                       dev_put(dev);
>               if (entry != NULL &&
> -                 security_secid_to_secctx(&entry->lsmblob, &context) == 0) {
> +                 security_secid_to_secctx(&entry->lsmblob, &context,
> +                                          LSMBLOB_FIRST) == 0) {
>                       audit_log_format(audit_buf, " sec_obj=%s",
>                                        context.context);
>                       security_release_secctx(&context);
> @@ -552,7 +554,8 @@ static int netlbl_unlhsh_remove_addr6(struct net *net,
>               if (dev != NULL)
>                       dev_put(dev);
>               if (entry != NULL &&
> -                 security_secid_to_secctx(&entry->lsmblob, &context) == 0) {
> +                 security_secid_to_secctx(&entry->lsmblob, &context,
> +                                          LSMBLOB_FIRST) == 0) {
>                       audit_log_format(audit_buf, " sec_obj=%s",
>                                        context.context);
>                       security_release_secctx(&context);
> @@ -1122,7 +1125,7 @@ static int netlbl_unlabel_staticlist_gen(u32 cmd,
>               lsmb = (struct lsmblob *)&addr6->lsmblob;
>       }
>  
> -     ret_val = security_secid_to_secctx(lsmb, &context);
> +     ret_val = security_secid_to_secctx(lsmb, &context, LSMBLOB_FIRST);
>       if (ret_val != 0)
>               goto list_cb_failure;
>       ret_val = nla_put(cb_arg->skb,
> diff --git a/net/netlabel/netlabel_user.c b/net/netlabel/netlabel_user.c
> index 951ba0639d20..1941877fd16f 100644
> --- a/net/netlabel/netlabel_user.c
> +++ b/net/netlabel/netlabel_user.c
> @@ -100,7 +100,7 @@ struct audit_buffer *netlbl_audit_start_common(int type,
>  
>       lsmblob_init(&blob, audit_info->secid);
>       if (audit_info->secid != 0 &&
> -         security_secid_to_secctx(&blob, &context) == 0) {
> +         security_secid_to_secctx(&blob, &context, LSMBLOB_FIRST) == 0) {
>               audit_log_format(audit_buf, " subj=%s", context.context);
>               security_release_secctx(&context);
>       }
> diff --git a/security/security.c b/security/security.c
> index b7c2ed1eee42..d3bf71d66724 100644
> --- a/security/security.c
> +++ b/security/security.c
> @@ -480,7 +480,31 @@ static int lsm_append(const char *new, char **result)
>   * Pointers to the LSM id structures for local use.
>   */
>  static int lsm_slot __lsm_ro_after_init;
> -static struct lsm_id *lsm_slotlist[LSMBLOB_ENTRIES];
> +static struct lsm_id *lsm_slotlist[LSMBLOB_ENTRIES] __lsm_ro_after_init;
> +
> +/**
> + * security_lsm_slot_name - Get the name of the security module in a slot
> + * @slot: index into the "display" slot list.
> + *
> + * Provide the name of the security module associated with
> + * a display slot.
> + *
> + * If @slot is LSMBLOB_INVALID return the value
> + * for slot 0 if it has been set, otherwise NULL.
> + *
> + * Returns a pointer to the name string or NULL.
> + */
> +const char *security_lsm_slot_name(int slot)
> +{
> +     if (slot == LSMBLOB_INVALID)
> +             slot = 0;
> +     else if (slot >= LSMBLOB_ENTRIES || slot < 0)
> +             return NULL;
> +
> +     if (lsm_slotlist[slot] == NULL)
> +             return NULL;
> +     return lsm_slotlist[slot]->lsm;
> +}
>  
>  /**
>   * security_add_hooks - Add a modules hooks to the hook lists.
> @@ -2169,13 +2193,32 @@ int security_ismaclabel(const char *name)
>  }
>  EXPORT_SYMBOL(security_ismaclabel);
>  
> -int security_secid_to_secctx(struct lsmblob *blob, struct lsmcontext *cp)
> +int security_secid_to_secctx(struct lsmblob *blob, struct lsmcontext *cp,
> +                          int display)
>  {
>       struct security_hook_list *hp;
> -     int display = lsm_task_display(current);
>  
>       memset(cp, 0, sizeof(*cp));
>  
> +     /*
> +      * display either is the slot number use for formatting
> +      * or an instruction on which relative slot to use.
> +      */
> +     if (display == LSMBLOB_DISPLAY)
> +             display = lsm_task_display(current);
> +     else if (display == LSMBLOB_FIRST)
> +             display = LSMBLOB_INVALID;
> +     else if (display < 0) {
> +             WARN_ONCE(true,
> +                     "LSM: %s unknown display\n", __func__);
> +             display = LSMBLOB_INVALID;
> +     } else if (display >= lsm_slot) {
> +             WARN_ONCE(true,
> +                     "LSM: %s invalid display\n", __func__);
> +             display = LSMBLOB_INVALID;
> +     }
> +
> +
>       hlist_for_each_entry(hp, &security_hook_heads.secid_to_secctx, list) {
>               if (WARN_ON(hp->lsmid->slot < 0 || hp->lsmid->slot >= lsm_slot))
>                       continue;
> @@ -2186,7 +2229,7 @@ int security_secid_to_secctx(struct lsmblob *blob, 
> struct lsmcontext *cp)
>                                       &cp->context, &cp->len);
>               }
>       }
> -     return 0;
> +     return -EOPNOTSUPP;
>  }
>  EXPORT_SYMBOL(security_secid_to_secctx);
>  
> -- 
> 2.24.1
> 

-- 
Kees Cook


--
Linux-audit mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/linux-audit

Reply via email to