]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
UBUNTU: SAUCE: LSM: Use lsmblob in security_secid_to_secctx
authorCasey Schaufler <casey@schaufler-ca.com>
Wed, 19 Aug 2020 16:32:48 +0000 (09:32 -0700)
committerPaolo Pisati <paolo.pisati@canonical.com>
Tue, 2 Nov 2021 07:24:51 +0000 (08:24 +0100)
Change security_secid_to_secctx() to take a lsmblob as input
instead of a u32 secid. It will then call the LSM hooks
using the lsmblob element allocated for that module. The
callers have been updated as well. This allows for the
possibility that more than one module may be called upon
to translate a secid to a string, as can occur in the
audit code.

Reviewed-by: Kees Cook <keescook@chromium.org>
Reviewed-by: John Johansen <john.johansen@canonical.com>
Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Andrea Righi <andrea.righi@canonical.com>
Signed-off-by: Seth Forshee <seth.forshee@canonical.com>
12 files changed:
drivers/android/binder.c
include/linux/security.h
include/net/scm.h
kernel/audit.c
kernel/auditsc.c
net/ipv4/ip_sockglue.c
net/netfilter/nf_conntrack_netlink.c
net/netfilter/nf_conntrack_standalone.c
net/netfilter/nfnetlink_queue.c
net/netlabel/netlabel_unlabeled.c
net/netlabel/netlabel_user.c
security/security.c

index 035968c66306ef6448d6dc80dbdaf8b18fe26a10..d878b83ee8d8e10fb2dca3e2d468eb05fff8cbcf 100644 (file)
@@ -2720,6 +2720,7 @@ static void binder_transaction(struct binder_proc *proc,
 
        if (target_node && target_node->txn_security_ctx) {
                u32 secid;
+               struct lsmblob blob;
                size_t added_size;
 
                /*
@@ -2732,7 +2733,16 @@ static void binder_transaction(struct binder_proc *proc,
                 * case well anyway.
                 */
                security_task_getsecid_obj(proc->tsk, &secid);
-               ret = security_secid_to_secctx(secid, &secctx, &secctx_sz);
+               /*
+                * Later in this patch set security_task_getsecid() will
+                * provide a lsmblob instead of a secid. lsmblob_init
+                * is used to ensure that all the secids in the lsmblob
+                * get the value returned from security_task_getsecid(),
+                * which means that the one expected by
+                * security_secid_to_secctx() will be set.
+                */
+               lsmblob_init(&blob, secid);
+               ret = security_secid_to_secctx(&blob, &secctx, &secctx_sz);
                if (ret) {
                        return_error = BR_FAILED_REPLY;
                        return_error_param = ret;
index 2b1c1baf3e4035f11dd8747e6265f3a695ee83fb..5ab3ba61e5bdfa696641549150f4e1c2ae104584 100644 (file)
@@ -544,7 +544,7 @@ 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(u32 secid, char **secdata, u32 *seclen);
+int security_secid_to_secctx(struct lsmblob *blob, char **secdata, u32 *seclen);
 int security_secctx_to_secid(const char *secdata, u32 seclen,
                             struct lsmblob *blob);
 void security_release_secctx(char *secdata, u32 seclen);
@@ -1394,7 +1394,8 @@ static inline int security_ismaclabel(const char *name)
        return 0;
 }
 
-static inline int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
+static inline int security_secid_to_secctx(struct lsmblob *blob,
+                                          char **secdata, u32 *seclen)
 {
        return -EOPNOTSUPP;
 }
index c09f2dfeec8852be5348454b39c78d3d91bbc787..31ae605fcc0ab43c1e7f392928087905e6c0ffb6 100644 (file)
@@ -97,12 +97,8 @@ static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct sc
        int err;
 
        if (test_bit(SOCK_PASSSEC, &sock->flags)) {
-               /* There can currently be only one value in the lsmblob,
-                * so getting it from lsmblob_value is appropriate until
-                * security_secid_to_secctx() is converted to taking a
-                * lsmblob directly. */
-               err = security_secid_to_secctx(lsmblob_value(&scm->lsmblob),
-                                              &secdata, &seclen);
+               err = security_secid_to_secctx(&scm->lsmblob, &secdata,
+                                              &seclen);
 
                if (!err) {
                        put_cmsg(msg, SOL_SOCKET, SCM_SECURITY, seclen, secdata);
index 121d37e700a62b53854c06199d9a89850ec39dd4..22286163e93ea2f58c1592425d51f9d13486b0b4 100644 (file)
@@ -1442,7 +1442,16 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
        case AUDIT_SIGNAL_INFO:
                len = 0;
                if (audit_sig_sid) {
-                       err = security_secid_to_secctx(audit_sig_sid, &ctx, &len);
+                       struct lsmblob blob;
+
+                       /*
+                        * lsmblob_init sets all values in the lsmblob
+                        * to audit_sig_sid. This is temporary until
+                        * audit_sig_sid is converted to a lsmblob, which
+                        * happens later in this patch set.
+                        */
+                       lsmblob_init(&blob, audit_sig_sid);
+                       err = security_secid_to_secctx(&blob, &ctx, &len);
                        if (err)
                                return err;
                }
@@ -2131,12 +2140,19 @@ int audit_log_task_context(struct audit_buffer *ab)
        unsigned len;
        int error;
        u32 sid;
+       struct lsmblob blob;
 
        security_task_getsecid_subj(current, &sid);
        if (!sid)
                return 0;
 
-       error = security_secid_to_secctx(sid, &ctx, &len);
+       /*
+        * lsmblob_init sets all values in the lsmblob to sid.
+        * This is temporary until security_task_getsecid is converted
+        * to use a lsmblob, which happens later in this patch set.
+        */
+       lsmblob_init(&blob, sid);
+       error = security_secid_to_secctx(&blob, &ctx, &len);
        if (error) {
                if (error != -EINVAL)
                        goto error_path;
index 1f9056f17dee837e30af0639fd78e8d1c2fea7c7..c8f8f6276c206f49b167bd8317193f624bd913de 100644 (file)
@@ -677,6 +677,13 @@ static int audit_filter_rules(struct task_struct *tsk,
                                        security_task_getsecid_subj(tsk, &sid);
                                        need_sid = 0;
                                }
+                               /*
+                                * lsmblob_init sets all values in the lsmblob
+                                * to sid. This is temporary until
+                                * security_task_getsecid() is converted to
+                                * provide a lsmblob, which happens later in
+                                * this patch set.
+                                */
                                lsmblob_init(&blob, sid);
                                result = security_audit_rule_match(&blob,
                                                                   f->type,
@@ -694,6 +701,13 @@ static int audit_filter_rules(struct task_struct *tsk,
                        if (f->lsm_isset) {
                                /* Find files that match */
                                if (name) {
+                                       /*
+                                        * lsmblob_init sets all values in the
+                                        * lsmblob to sid. This is temporary
+                                        * until name->osid is converted to a
+                                        * lsmblob, which happens later in
+                                        * this patch set.
+                                        */
                                        lsmblob_init(&blob, name->osid);
                                        result = security_audit_rule_match(
                                                                &blob,
@@ -1000,6 +1014,7 @@ static int audit_log_pid_context(struct audit_context *context, pid_t pid,
        char *ctx = NULL;
        u32 len;
        int rc = 0;
+       struct lsmblob blob;
 
        ab = audit_log_start(context, GFP_KERNEL, AUDIT_OBJ_PID);
        if (!ab)
@@ -1009,7 +1024,8 @@ 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 (sid) {
-               if (security_secid_to_secctx(sid, &ctx, &len)) {
+               lsmblob_init(&blob, sid);
+               if (security_secid_to_secctx(&blob, &ctx, &len)) {
                        audit_log_format(ab, " obj=(none)");
                        rc = 1;
                } else {
@@ -1253,8 +1269,10 @@ static void show_special(struct audit_context *context, int *call_panic)
                if (osid) {
                        char *ctx = NULL;
                        u32 len;
+                       struct lsmblob blob;
 
-                       if (security_secid_to_secctx(osid, &ctx, &len)) {
+                       lsmblob_init(&blob, osid);
+                       if (security_secid_to_secctx(&blob, &ctx, &len)) {
                                audit_log_format(ab, " osid=%u", osid);
                                *call_panic = 1;
                        } else {
@@ -1409,9 +1427,10 @@ static void audit_log_name(struct audit_context *context, struct audit_names *n,
        if (n->osid != 0) {
                char *ctx = NULL;
                u32 len;
+               struct lsmblob blob;
 
-               if (security_secid_to_secctx(
-                       n->osid, &ctx, &len)) {
+               lsmblob_init(&blob, n->osid);
+               if (security_secid_to_secctx(&blob, &ctx, &len)) {
                        audit_log_format(ab, " osid=%u", n->osid);
                        if (call_panic)
                                *call_panic = 2;
index 6b8b262aa01a0883b5c8a17c747175a14b86e8d2..863062fba7ca77feb1c16687616191d9adcb929d 100644 (file)
@@ -139,10 +139,7 @@ static void ip_cmsg_recv_security(struct msghdr *msg, struct sk_buff *skb)
        if (err)
                return;
 
-       /* There can only be one secid in the lsmblob at this point,
-        * so getting it using lsmblob_value() is sufficient until
-        * security_secid_to_secctx() is changed to use a lsmblob */
-       err = security_secid_to_secctx(lsmblob_value(&lb), &secdata, &seclen);
+       err = security_secid_to_secctx(&lb, &secdata, &seclen);
        if (err)
                return;
 
index f1e5443fe7c74cde3f5f0a1a01bcbe530bedb75c..daf554915e07d5b32b8b1a6cd3e92efc5b02354e 100644 (file)
@@ -341,8 +341,13 @@ static int ctnetlink_dump_secctx(struct sk_buff *skb, const struct nf_conn *ct)
        struct nlattr *nest_secctx;
        int len, ret;
        char *secctx;
+       struct lsmblob blob;
 
-       ret = security_secid_to_secctx(ct->secmark, &secctx, &len);
+       /* lsmblob_init() puts ct->secmark into all of the secids in blob.
+        * 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, &secctx, &len);
        if (ret)
                return 0;
 
@@ -650,8 +655,13 @@ static inline int ctnetlink_secctx_size(const struct nf_conn *ct)
 {
 #ifdef CONFIG_NF_CONNTRACK_SECMARK
        int len, ret;
+       struct lsmblob blob;
 
-       ret = security_secid_to_secctx(ct->secmark, NULL, &len);
+       /* lsmblob_init() puts ct->secmark into all of the secids in blob.
+        * 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, NULL, &len);
        if (ret)
                return 0;
 
index 80f675d884b26363d1c98ac454b047226342d58b..79c280d1efce690d6672fa1efef5ca8f48b51ef5 100644 (file)
@@ -178,8 +178,10 @@ static void ct_show_secctx(struct seq_file *s, const struct nf_conn *ct)
        int ret;
        u32 len;
        char *secctx;
+       struct lsmblob blob;
 
-       ret = security_secid_to_secctx(ct->secmark, &secctx, &len);
+       lsmblob_init(&blob, ct->secmark);
+       ret = security_secid_to_secctx(&blob, &secctx, &len);
        if (ret)
                return;
 
index 4c3fbaaeb10303d48c1c388ef8c9e2b8aedbd716..bb97e8af83459bd108c3ba84a3e8fb3ab9103b08 100644 (file)
@@ -305,13 +305,20 @@ static u32 nfqnl_get_sk_secctx(struct sk_buff *skb, char **secdata)
 {
        u32 seclen = 0;
 #if IS_ENABLED(CONFIG_NETWORK_SECMARK)
+       struct lsmblob blob;
+
        if (!skb || !sk_fullsock(skb->sk))
                return 0;
 
        read_lock_bh(&skb->sk->sk_callback_lock);
 
-       if (skb->secmark)
-               security_secid_to_secctx(skb->secmark, secdata, &seclen);
+       if (skb->secmark) {
+               /* lsmblob_init() puts ct->secmark into all of the secids in
+                * 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, secdata, &seclen);
+       }
 
        read_unlock_bh(&skb->sk->sk_callback_lock);
 #endif
index 762561318d7861ae17c80100981628088c3c25fe..cbdc8e7a22a6a31e85231d2a1efc3b081f73e672 100644 (file)
@@ -376,6 +376,7 @@ int netlbl_unlhsh_add(struct net *net,
        struct audit_buffer *audit_buf = NULL;
        char *secctx = NULL;
        u32 secctx_len;
+       struct lsmblob blob;
 
        if (addr_len != sizeof(struct in_addr) &&
            addr_len != sizeof(struct in6_addr))
@@ -438,7 +439,11 @@ int netlbl_unlhsh_add(struct net *net,
 unlhsh_add_return:
        rcu_read_unlock();
        if (audit_buf != NULL) {
-               if (security_secid_to_secctx(secid,
+               /* lsmblob_init() puts secid into all of the secids in blob.
+                * security_secid_to_secctx() will know which security module
+                * to use to create the secctx.  */
+               lsmblob_init(&blob, secid);
+               if (security_secid_to_secctx(&blob,
                                             &secctx,
                                             &secctx_len) == 0) {
                        audit_log_format(audit_buf, " sec_obj=%s", secctx);
@@ -475,6 +480,7 @@ static int netlbl_unlhsh_remove_addr4(struct net *net,
        struct net_device *dev;
        char *secctx;
        u32 secctx_len;
+       struct lsmblob blob;
 
        spin_lock(&netlbl_unlhsh_lock);
        list_entry = netlbl_af4list_remove(addr->s_addr, mask->s_addr,
@@ -493,8 +499,13 @@ static int netlbl_unlhsh_remove_addr4(struct net *net,
                                          (dev != NULL ? dev->name : NULL),
                                          addr->s_addr, mask->s_addr);
                dev_put(dev);
+               /* lsmblob_init() puts entry->secid into all of the secids
+                * in blob. security_secid_to_secctx() will know which
+                * security module to use to create the secctx.  */
+               if (entry != NULL)
+                       lsmblob_init(&blob, entry->secid);
                if (entry != NULL &&
-                   security_secid_to_secctx(entry->secid,
+                   security_secid_to_secctx(&blob,
                                             &secctx, &secctx_len) == 0) {
                        audit_log_format(audit_buf, " sec_obj=%s", secctx);
                        security_release_secctx(secctx, secctx_len);
@@ -536,6 +547,7 @@ static int netlbl_unlhsh_remove_addr6(struct net *net,
        struct net_device *dev;
        char *secctx;
        u32 secctx_len;
+       struct lsmblob blob;
 
        spin_lock(&netlbl_unlhsh_lock);
        list_entry = netlbl_af6list_remove(addr, mask, &iface->addr6_list);
@@ -553,8 +565,13 @@ static int netlbl_unlhsh_remove_addr6(struct net *net,
                                          (dev != NULL ? dev->name : NULL),
                                          addr, mask);
                dev_put(dev);
+               /* lsmblob_init() puts entry->secid into all of the secids
+                * in blob. security_secid_to_secctx() will know which
+                * security module to use to create the secctx.  */
+               if (entry != NULL)
+                       lsmblob_init(&blob, entry->secid);
                if (entry != NULL &&
-                   security_secid_to_secctx(entry->secid,
+                   security_secid_to_secctx(&blob,
                                             &secctx, &secctx_len) == 0) {
                        audit_log_format(audit_buf, " sec_obj=%s", secctx);
                        security_release_secctx(secctx, secctx_len);
@@ -1080,6 +1097,7 @@ static int netlbl_unlabel_staticlist_gen(u32 cmd,
        u32 secid;
        char *secctx;
        u32 secctx_len;
+       struct lsmblob blob;
 
        data = genlmsg_put(cb_arg->skb, NETLINK_CB(cb_arg->nl_cb->skb).portid,
                           cb_arg->seq, &netlbl_unlabel_gnl_family,
@@ -1134,7 +1152,11 @@ static int netlbl_unlabel_staticlist_gen(u32 cmd,
                secid = addr6->secid;
        }
 
-       ret_val = security_secid_to_secctx(secid, &secctx, &secctx_len);
+        /* lsmblob_init() secid into all of the secids in blob.
+         * security_secid_to_secctx() will know which security module
+         * to use to create the secctx.  */
+       lsmblob_init(&blob, secid);
+       ret_val = security_secid_to_secctx(&blob, &secctx, &secctx_len);
        if (ret_val != 0)
                goto list_cb_failure;
        ret_val = nla_put(cb_arg->skb,
index 3ed4fea2a2de354a3888dee9dcca6b5a6023f7d2..893301ae013142678b7b96125622b81c0776781a 100644 (file)
@@ -86,6 +86,7 @@ struct audit_buffer *netlbl_audit_start_common(int type,
        struct audit_buffer *audit_buf;
        char *secctx;
        u32 secctx_len;
+       struct lsmblob blob;
 
        if (audit_enabled == AUDIT_OFF)
                return NULL;
@@ -98,10 +99,9 @@ struct audit_buffer *netlbl_audit_start_common(int type,
                         from_kuid(&init_user_ns, audit_info->loginuid),
                         audit_info->sessionid);
 
+       lsmblob_init(&blob, audit_info->secid);
        if (audit_info->secid != 0 &&
-           security_secid_to_secctx(audit_info->secid,
-                                    &secctx,
-                                    &secctx_len) == 0) {
+           security_secid_to_secctx(&blob, &secctx, &secctx_len) == 0) {
                audit_log_format(audit_buf, " subj=%s", secctx);
                security_release_secctx(secctx, secctx_len);
        }
index 2fb7dd813f19c0cb639d181c7cfad327d311df78..f0d013fdd5e4cd6d161eefc701f6328ea53b99d2 100644 (file)
@@ -2132,17 +2132,16 @@ int security_ismaclabel(const char *name)
 }
 EXPORT_SYMBOL(security_ismaclabel);
 
-int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
+int security_secid_to_secctx(struct lsmblob *blob, char **secdata, u32 *seclen)
 {
        struct security_hook_list *hp;
        int rc;
 
-       /*
-        * Currently, only one LSM can implement secid_to_secctx (i.e this
-        * LSM hook is not "stackable").
-        */
        hlist_for_each_entry(hp, &security_hook_heads.secid_to_secctx, list) {
-               rc = hp->hook.secid_to_secctx(secid, secdata, seclen);
+               if (WARN_ON(hp->lsmid->slot < 0 || hp->lsmid->slot >= lsm_slot))
+                       continue;
+               rc = hp->hook.secid_to_secctx(blob->secid[hp->lsmid->slot],
+                                             secdata, seclen);
                if (rc != LSM_RET_DEFAULT(secid_to_secctx))
                        return rc;
        }