SELinux: Add a capabilities bitmap to SELinux policy version 22
[firefly-linux-kernel-4.4.55.git] / security / selinux / ss / services.c
index f83b19daed16181a86ede00b8d1455432f05acec..8ee04a424df7c31d5b62558e8a7796ecdb909e93 100644 (file)
  * Updated: Hewlett-Packard <paul.moore@hp.com>
  *
  *      Added support for NetLabel
+ *      Added support for the policy capability bitmap
  *
  * Updated: Chad Sellers <csellers@tresys.com>
  *
  *  Added validation of kernel classes and permissions
  *
- * Copyright (C) 2006 Hewlett-Packard Development Company, L.P.
+ * Copyright (C) 2006, 2007 Hewlett-Packard Development Company, L.P.
  * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc.
  * Copyright (C) 2003 - 2004, 2006 Tresys Technology, LLC
  * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com>
@@ -59,6 +60,8 @@
 extern void selnl_notify_policyload(u32 seqno);
 unsigned int policydb_loaded_version;
 
+int selinux_policycap_netpeer;
+
 /*
  * This is declared in avc.c
  */
@@ -1299,6 +1302,12 @@ bad:
        goto out;
 }
 
+static void security_load_policycaps(void)
+{
+       selinux_policycap_netpeer = ebitmap_get_bit(&policydb.policycaps,
+                                                 POLICYDB_CAPABILITY_NETPEER);
+}
+
 extern void selinux_complete_init(void);
 static int security_preserve_bools(struct policydb *p);
 
@@ -1346,6 +1355,7 @@ int security_load_policy(void *data, size_t len)
                        avtab_cache_destroy();
                        return -EINVAL;
                }
+               security_load_policycaps();
                policydb_loaded_version = policydb.policyvers;
                ss_initialized = 1;
                seqno = ++latest_granting;
@@ -1404,6 +1414,7 @@ int security_load_policy(void *data, size_t len)
        POLICY_WRLOCK;
        memcpy(&policydb, &newpolicydb, sizeof policydb);
        sidtab_set(&sidtab, &newsidtab);
+       security_load_policycaps();
        seqno = ++latest_granting;
        policydb_loaded_version = policydb.policyvers;
        POLICY_WRUNLOCK;
@@ -1478,11 +1489,8 @@ out:
  * security_netif_sid - Obtain the SID for a network interface.
  * @name: interface name
  * @if_sid: interface SID
- * @msg_sid: default SID for received packets
  */
-int security_netif_sid(char *name,
-                      u32 *if_sid,
-                      u32 *msg_sid)
+int security_netif_sid(char *name, u32 *if_sid)
 {
        int rc = 0;
        struct ocontext *c;
@@ -1510,11 +1518,8 @@ int security_netif_sid(char *name,
                                goto out;
                }
                *if_sid = c->sid[0];
-               *msg_sid = c->sid[1];
-       } else {
+       } else
                *if_sid = SECINITSID_NETIF;
-               *msg_sid = SECINITSID_NETMSG;
-       }
 
 out:
        POLICY_RDUNLOCK;
@@ -1744,6 +1749,9 @@ int security_genfs_sid(const char *fstype,
        struct ocontext *c;
        int rc = 0, cmp = 0;
 
+       while (path[0] == '/' && path[1] == '/')
+               path++;
+
        POLICY_RDLOCK;
 
        for (genfs = policydb.genfs; genfs; genfs = genfs->next) {
@@ -2151,6 +2159,60 @@ int security_get_allow_unknown(void)
        return policydb.allow_unknown;
 }
 
+/**
+ * security_get_policycaps - Query the loaded policy for its capabilities
+ * @len: the number of capability bits
+ * @values: the capability bit array
+ *
+ * Description:
+ * Get an array of the policy capabilities in @values where each entry in
+ * @values is either true (1) or false (0) depending the policy's support of
+ * that feature.  The policy capabilities are defined by the
+ * POLICYDB_CAPABILITY_* enums.  The size of the array is stored in @len and it
+ * is up to the caller to free the array in @values.  Returns zero on success,
+ * negative values on failure.
+ *
+ */
+int security_get_policycaps(int *len, int **values)
+{
+       int rc = -ENOMEM;
+       unsigned int iter;
+
+       POLICY_RDLOCK;
+
+       *values = kcalloc(POLICYDB_CAPABILITY_MAX, sizeof(int), GFP_ATOMIC);
+       if (*values == NULL)
+               goto out;
+       for (iter = 0; iter < POLICYDB_CAPABILITY_MAX; iter++)
+               (*values)[iter] = ebitmap_get_bit(&policydb.policycaps, iter);
+       *len = POLICYDB_CAPABILITY_MAX;
+
+out:
+       POLICY_RDUNLOCK;
+       return rc;
+}
+
+/**
+ * security_policycap_supported - Check for a specific policy capability
+ * @req_cap: capability
+ *
+ * Description:
+ * This function queries the currently loaded policy to see if it supports the
+ * capability specified by @req_cap.  Returns true (1) if the capability is
+ * supported, false (0) if it isn't supported.
+ *
+ */
+int security_policycap_supported(unsigned int req_cap)
+{
+       int rc;
+
+       POLICY_RDLOCK;
+       rc = ebitmap_get_bit(&policydb.policycaps, req_cap);
+       POLICY_RDUNLOCK;
+
+       return rc;
+}
+
 struct selinux_audit_rule {
        u32 au_seqno;
        struct context au_ctxt;
@@ -2547,6 +2609,9 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
                default:
                        goto netlbl_secattr_to_sid_return;
                }
+       } else if (secattr->flags & NETLBL_SECATTR_SECID) {
+               *sid = secattr->attr.secid;
+               rc = 0;
        } else if (secattr->flags & NETLBL_SECATTR_MLS_LVL) {
                ctx = sidtab_search(&sidtab, base_sid);
                if (ctx == NULL)
@@ -2558,7 +2623,7 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
                mls_import_netlbl_lvl(&ctx_new, secattr);
                if (secattr->flags & NETLBL_SECATTR_MLS_CAT) {
                        if (ebitmap_netlbl_import(&ctx_new.range.level[0].cat,
-                                                 secattr->mls_cat) != 0)
+                                                 secattr->attr.mls.cat) != 0)
                                goto netlbl_secattr_to_sid_return;
                        ctx_new.range.level[1].cat.highbit =
                                ctx_new.range.level[0].cat.highbit;