Merge tag 'v3.13' into next
authorPaul Moore <pmoore@redhat.com>
Thu, 23 Jan 2014 20:52:06 +0000 (15:52 -0500)
committerPaul Moore <pmoore@redhat.com>
Thu, 23 Jan 2014 20:52:06 +0000 (15:52 -0500)
Linux 3.13

Minor fixup needed in selinux_inet_conn_request()

Conflicts:
security/selinux/hooks.c

security/selinux/hooks.c
security/selinux/include/security.h
security/selinux/netlabel.c
security/selinux/ss/constraint.h
security/selinux/ss/policydb.c
security/selinux/ss/policydb.h
security/selinux/ss/services.c

index 57b0b49..4b34847 100644 (file)
@@ -82,7 +82,6 @@
 #include <linux/syslog.h>
 #include <linux/user_namespace.h>
 #include <linux/export.h>
-#include <linux/security.h>
 #include <linux/msg.h>
 #include <linux/shm.h>
 
@@ -4490,14 +4489,10 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
 {
        struct sk_security_struct *sksec = sk->sk_security;
        int err;
-       u16 family = sk->sk_family;
+       u16 family = req->rsk_ops->family;
        u32 connsid;
        u32 peersid;
 
-       /* handle mapped IPv4 packets arriving via IPv6 sockets */
-       if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
-               family = PF_INET;
-
        err = selinux_skb_peerlbl_sid(skb, family, &peersid);
        if (err)
                return err;
index fe341ae..8ed8daf 100644 (file)
 #define POLICYDB_VERSION_ROLETRANS     26
 #define POLICYDB_VERSION_NEW_OBJECT_DEFAULTS   27
 #define POLICYDB_VERSION_DEFAULT_TYPE  28
+#define POLICYDB_VERSION_CONSTRAINT_NAMES      29
 
 /* Range of policy versions we understand*/
 #define POLICYDB_VERSION_MIN   POLICYDB_VERSION_BASE
 #ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX
 #define POLICYDB_VERSION_MAX   CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE
 #else
-#define POLICYDB_VERSION_MAX   POLICYDB_VERSION_DEFAULT_TYPE
+#define POLICYDB_VERSION_MAX   POLICYDB_VERSION_CONSTRAINT_NAMES
 #endif
 
 /* Mask for just the mount related flags */
index 6235d05..0364120 100644 (file)
@@ -100,6 +100,32 @@ static struct netlbl_lsm_secattr *selinux_netlbl_sock_genattr(struct sock *sk)
        return secattr;
 }
 
+/**
+ * selinux_netlbl_sock_getattr - Get the cached NetLabel secattr
+ * @sk: the socket
+ * @sid: the SID
+ *
+ * Query the socket's cached secattr and if the SID matches the cached value
+ * return the cache, otherwise return NULL.
+ *
+ */
+static struct netlbl_lsm_secattr *selinux_netlbl_sock_getattr(
+                                                       const struct sock *sk,
+                                                       u32 sid)
+{
+       struct sk_security_struct *sksec = sk->sk_security;
+       struct netlbl_lsm_secattr *secattr = sksec->nlbl_secattr;
+
+       if (secattr == NULL)
+               return NULL;
+
+       if ((secattr->flags & NETLBL_SECATTR_SECID) &&
+           (secattr->attr.secid == sid))
+               return secattr;
+
+       return NULL;
+}
+
 /**
  * selinux_netlbl_cache_invalidate - Invalidate the NetLabel cache
  *
@@ -224,7 +250,7 @@ int selinux_netlbl_skbuff_setsid(struct sk_buff *skb,
                struct sk_security_struct *sksec = sk->sk_security;
                if (sksec->nlbl_state != NLBL_REQSKB)
                        return 0;
-               secattr = sksec->nlbl_secattr;
+               secattr = selinux_netlbl_sock_getattr(sk, sid);
        }
        if (secattr == NULL) {
                secattr = &secattr_storage;
@@ -410,6 +436,9 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock,
             sksec->nlbl_state == NLBL_CONNLABELED)) {
                netlbl_secattr_init(&secattr);
                lock_sock(sk);
+               /* call the netlabel function directly as we want to see the
+                * on-the-wire label that is assigned via the socket's options
+                * and not the cached netlabel/lsm attributes */
                rc = netlbl_sock_getattr(sk, &secattr);
                release_sock(sk);
                if (rc == 0)
index 149dda7..96fd947 100644 (file)
@@ -48,6 +48,7 @@ struct constraint_expr {
        u32 op;                 /* operator */
 
        struct ebitmap names;   /* names */
+       struct type_set *type_names;
 
        struct constraint_expr *next;   /* next expression */
 };
index f6195eb..c0f4988 100644 (file)
@@ -143,6 +143,11 @@ static struct policydb_compat_info policydb_compat[] = {
                .sym_num        = SYM_NUM,
                .ocon_num       = OCON_NUM,
        },
+       {
+               .version        = POLICYDB_VERSION_CONSTRAINT_NAMES,
+               .sym_num        = SYM_NUM,
+               .ocon_num       = OCON_NUM,
+       },
 };
 
 static struct policydb_compat_info *policydb_lookup_compat(int version)
@@ -613,6 +618,19 @@ static int common_destroy(void *key, void *datum, void *p)
        return 0;
 }
 
+static void constraint_expr_destroy(struct constraint_expr *expr)
+{
+       if (expr) {
+               ebitmap_destroy(&expr->names);
+               if (expr->type_names) {
+                       ebitmap_destroy(&expr->type_names->types);
+                       ebitmap_destroy(&expr->type_names->negset);
+                       kfree(expr->type_names);
+               }
+               kfree(expr);
+       }
+}
+
 static int cls_destroy(void *key, void *datum, void *p)
 {
        struct class_datum *cladatum;
@@ -628,10 +646,9 @@ static int cls_destroy(void *key, void *datum, void *p)
                while (constraint) {
                        e = constraint->expr;
                        while (e) {
-                               ebitmap_destroy(&e->names);
                                etmp = e;
                                e = e->next;
-                               kfree(etmp);
+                               constraint_expr_destroy(etmp);
                        }
                        ctemp = constraint;
                        constraint = constraint->next;
@@ -642,16 +659,14 @@ static int cls_destroy(void *key, void *datum, void *p)
                while (constraint) {
                        e = constraint->expr;
                        while (e) {
-                               ebitmap_destroy(&e->names);
                                etmp = e;
                                e = e->next;
-                               kfree(etmp);
+                               constraint_expr_destroy(etmp);
                        }
                        ctemp = constraint;
                        constraint = constraint->next;
                        kfree(ctemp);
                }
-
                kfree(cladatum->comkey);
        }
        kfree(datum);
@@ -1156,8 +1171,34 @@ bad:
        return rc;
 }
 
-static int read_cons_helper(struct constraint_node **nodep, int ncons,
-                           int allowxtarget, void *fp)
+static void type_set_init(struct type_set *t)
+{
+       ebitmap_init(&t->types);
+       ebitmap_init(&t->negset);
+}
+
+static int type_set_read(struct type_set *t, void *fp)
+{
+       __le32 buf[1];
+       int rc;
+
+       if (ebitmap_read(&t->types, fp))
+               return -EINVAL;
+       if (ebitmap_read(&t->negset, fp))
+               return -EINVAL;
+
+       rc = next_entry(buf, fp, sizeof(u32));
+       if (rc < 0)
+               return -EINVAL;
+       t->flags = le32_to_cpu(buf[0]);
+
+       return 0;
+}
+
+
+static int read_cons_helper(struct policydb *p,
+                               struct constraint_node **nodep,
+                               int ncons, int allowxtarget, void *fp)
 {
        struct constraint_node *c, *lc;
        struct constraint_expr *e, *le;
@@ -1225,6 +1266,18 @@ static int read_cons_helper(struct constraint_node **nodep, int ncons,
                                rc = ebitmap_read(&e->names, fp);
                                if (rc)
                                        return rc;
+                               if (p->policyvers >=
+                                       POLICYDB_VERSION_CONSTRAINT_NAMES) {
+                                               e->type_names = kzalloc(sizeof
+                                               (*e->type_names),
+                                               GFP_KERNEL);
+                                       if (!e->type_names)
+                                               return -ENOMEM;
+                                       type_set_init(e->type_names);
+                                       rc = type_set_read(e->type_names, fp);
+                                       if (rc)
+                                               return rc;
+                               }
                                break;
                        default:
                                return -EINVAL;
@@ -1301,7 +1354,7 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp)
                        goto bad;
        }
 
-       rc = read_cons_helper(&cladatum->constraints, ncons, 0, fp);
+       rc = read_cons_helper(p, &cladatum->constraints, ncons, 0, fp);
        if (rc)
                goto bad;
 
@@ -1311,7 +1364,8 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp)
                if (rc)
                        goto bad;
                ncons = le32_to_cpu(buf[0]);
-               rc = read_cons_helper(&cladatum->validatetrans, ncons, 1, fp);
+               rc = read_cons_helper(p, &cladatum->validatetrans,
+                               ncons, 1, fp);
                if (rc)
                        goto bad;
        }
@@ -1941,7 +1995,19 @@ static int filename_trans_read(struct policydb *p, void *fp)
                if (rc)
                        goto out;
 
-               hashtab_insert(p->filename_trans, ft, otype);
+               rc = hashtab_insert(p->filename_trans, ft, otype);
+               if (rc) {
+                       /*
+                        * Do not return -EEXIST to the caller, or the system
+                        * will not boot.
+                        */
+                       if (rc != -EEXIST)
+                               goto out;
+                       /* But free memory to avoid memory leak. */
+                       kfree(ft);
+                       kfree(name);
+                       kfree(otype);
+               }
        }
        hash_eval(p->filename_trans, "filenametr");
        return 0;
@@ -2753,6 +2819,24 @@ static int common_write(void *vkey, void *datum, void *ptr)
        return 0;
 }
 
+static int type_set_write(struct type_set *t, void *fp)
+{
+       int rc;
+       __le32 buf[1];
+
+       if (ebitmap_write(&t->types, fp))
+               return -EINVAL;
+       if (ebitmap_write(&t->negset, fp))
+               return -EINVAL;
+
+       buf[0] = cpu_to_le32(t->flags);
+       rc = put_entry(buf, sizeof(u32), 1, fp);
+       if (rc)
+               return -EINVAL;
+
+       return 0;
+}
+
 static int write_cons_helper(struct policydb *p, struct constraint_node *node,
                             void *fp)
 {
@@ -2784,6 +2868,12 @@ static int write_cons_helper(struct policydb *p, struct constraint_node *node,
                                rc = ebitmap_write(&e->names, fp);
                                if (rc)
                                        return rc;
+                               if (p->policyvers >=
+                                       POLICYDB_VERSION_CONSTRAINT_NAMES) {
+                                       rc = type_set_write(e->type_names, fp);
+                                       if (rc)
+                                               return rc;
+                               }
                                break;
                        default:
                                break;
index da63747..725d594 100644 (file)
@@ -153,6 +153,17 @@ struct cond_bool_datum {
 
 struct cond_node;
 
+/*
+ * type set preserves data needed to determine constraint info from
+ * policy source. This is not used by the kernel policy but allows
+ * utilities such as audit2allow to determine constraint denials.
+ */
+struct type_set {
+       struct ebitmap types;
+       struct ebitmap negset;
+       u32 flags;
+};
+
 /*
  * The configuration data includes security contexts for
  * initial SIDs, unlabeled file systems, TCP and UDP port numbers,
index d106733..fc5a63a 100644 (file)
@@ -1831,7 +1831,7 @@ static int security_preserve_bools(struct policydb *p);
  */
 int security_load_policy(void *data, size_t len)
 {
-       struct policydb oldpolicydb, newpolicydb;
+       struct policydb *oldpolicydb, *newpolicydb;
        struct sidtab oldsidtab, newsidtab;
        struct selinux_mapping *oldmap, *map = NULL;
        struct convert_context_args args;
@@ -1840,12 +1840,19 @@ int security_load_policy(void *data, size_t len)
        int rc = 0;
        struct policy_file file = { data, len }, *fp = &file;
 
+       oldpolicydb = kzalloc(2 * sizeof(*oldpolicydb), GFP_KERNEL);
+       if (!oldpolicydb) {
+               rc = -ENOMEM;
+               goto out;
+       }
+       newpolicydb = oldpolicydb + 1;
+
        if (!ss_initialized) {
                avtab_cache_init();
                rc = policydb_read(&policydb, fp);
                if (rc) {
                        avtab_cache_destroy();
-                       return rc;
+                       goto out;
                }
 
                policydb.len = len;
@@ -1855,14 +1862,14 @@ int security_load_policy(void *data, size_t len)
                if (rc) {
                        policydb_destroy(&policydb);
                        avtab_cache_destroy();
-                       return rc;
+                       goto out;
                }
 
                rc = policydb_load_isids(&policydb, &sidtab);
                if (rc) {
                        policydb_destroy(&policydb);
                        avtab_cache_destroy();
-                       return rc;
+                       goto out;
                }
 
                security_load_policycaps();
@@ -1874,36 +1881,36 @@ int security_load_policy(void *data, size_t len)
                selinux_status_update_policyload(seqno);
                selinux_netlbl_cache_invalidate();
                selinux_xfrm_notify_policyload();
-               return 0;
+               goto out;
        }
 
 #if 0
        sidtab_hash_eval(&sidtab, "sids");
 #endif
 
-       rc = policydb_read(&newpolicydb, fp);
+       rc = policydb_read(newpolicydb, fp);
        if (rc)
-               return rc;
+               goto out;
 
-       newpolicydb.len = len;
+       newpolicydb->len = len;
        /* If switching between different policy types, log MLS status */
-       if (policydb.mls_enabled && !newpolicydb.mls_enabled)
+       if (policydb.mls_enabled && !newpolicydb->mls_enabled)
                printk(KERN_INFO "SELinux: Disabling MLS support...\n");
-       else if (!policydb.mls_enabled && newpolicydb.mls_enabled)
+       else if (!policydb.mls_enabled && newpolicydb->mls_enabled)
                printk(KERN_INFO "SELinux: Enabling MLS support...\n");
 
-       rc = policydb_load_isids(&newpolicydb, &newsidtab);
+       rc = policydb_load_isids(newpolicydb, &newsidtab);
        if (rc) {
                printk(KERN_ERR "SELinux:  unable to load the initial SIDs\n");
-               policydb_destroy(&newpolicydb);
-               return rc;
+               policydb_destroy(newpolicydb);
+               goto out;
        }
 
-       rc = selinux_set_mapping(&newpolicydb, secclass_map, &map, &map_size);
+       rc = selinux_set_mapping(newpolicydb, secclass_map, &map, &map_size);
        if (rc)
                goto err;
 
-       rc = security_preserve_bools(&newpolicydb);
+       rc = security_preserve_bools(newpolicydb);
        if (rc) {
                printk(KERN_ERR "SELinux:  unable to preserve booleans\n");
                goto err;
@@ -1921,7 +1928,7 @@ int security_load_policy(void *data, size_t len)
         * in the new SID table.
         */
        args.oldp = &policydb;
-       args.newp = &newpolicydb;
+       args.newp = newpolicydb;
        rc = sidtab_map(&newsidtab, convert_context, &args);
        if (rc) {
                printk(KERN_ERR "SELinux:  unable to convert the internal"
@@ -1931,12 +1938,12 @@ int security_load_policy(void *data, size_t len)
        }
 
        /* Save the old policydb and SID table to free later. */
-       memcpy(&oldpolicydb, &policydb, sizeof policydb);
+       memcpy(oldpolicydb, &policydb, sizeof(policydb));
        sidtab_set(&oldsidtab, &sidtab);
 
        /* Install the new policydb and SID table. */
        write_lock_irq(&policy_rwlock);
-       memcpy(&policydb, &newpolicydb, sizeof policydb);
+       memcpy(&policydb, newpolicydb, sizeof(policydb));
        sidtab_set(&sidtab, &newsidtab);
        security_load_policycaps();
        oldmap = current_mapping;
@@ -1946,7 +1953,7 @@ int security_load_policy(void *data, size_t len)
        write_unlock_irq(&policy_rwlock);
 
        /* Free the old policydb and SID table. */
-       policydb_destroy(&oldpolicydb);
+       policydb_destroy(oldpolicydb);
        sidtab_destroy(&oldsidtab);
        kfree(oldmap);
 
@@ -1956,14 +1963,17 @@ int security_load_policy(void *data, size_t len)
        selinux_netlbl_cache_invalidate();
        selinux_xfrm_notify_policyload();
 
-       return 0;
+       rc = 0;
+       goto out;
 
 err:
        kfree(map);
        sidtab_destroy(&newsidtab);
-       policydb_destroy(&newpolicydb);
-       return rc;
+       policydb_destroy(newpolicydb);
 
+out:
+       kfree(oldpolicydb);
+       return rc;
 }
 
 size_t security_policydb_len(void)