vserver 1.9.5.x5
[linux-2.6.git] / security / selinux / ss / services.c
index 21ab4c9..11545e0 100644 (file)
@@ -40,8 +40,9 @@
 #include "mls.h"
 
 extern void selnl_notify_policyload(u32 seqno);
+unsigned int policydb_loaded_version;
 
-static rwlock_t policy_rwlock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(policy_rwlock);
 #define POLICY_RDLOCK read_lock(&policy_rwlock)
 #define POLICY_WRLOCK write_lock_irq(&policy_rwlock)
 #define POLICY_RDUNLOCK read_unlock(&policy_rwlock)
@@ -203,6 +204,17 @@ static int context_struct_compute_av(struct context *scontext,
        struct avtab_datum *avdatum;
        struct class_datum *tclass_datum;
 
+       /*
+        * Remap extended Netlink classes for old policy versions.
+        * Do this here rather than socket_type_to_security_class()
+        * in case a newer policy version is loaded, allowing sockets
+        * to remain in the correct class.
+        */
+       if (policydb_loaded_version < POLICYDB_VERSION_NLCLASS)
+               if (tclass >= SECCLASS_NETLINK_ROUTE_SOCKET &&
+                   tclass <= SECCLASS_NETLINK_DNRT_SOCKET)
+                       tclass = SECCLASS_NETLINK_SOCKET;
+
        if (!tclass || tclass > policydb.p_classes.nprim) {
                printk(KERN_ERR "security_compute_av:  unrecognized class %d\n",
                       tclass);
@@ -263,7 +275,7 @@ static int context_struct_compute_av(struct context *scontext,
         * pair.
         */
        if (tclass == SECCLASS_PROCESS &&
-           (avd->allowed & PROCESS__TRANSITION) &&
+           (avd->allowed & (PROCESS__TRANSITION | PROCESS__DYNTRANSITION)) &&
            scontext->role != tcontext->role) {
                for (ra = policydb.role_allow; ra; ra = ra->next) {
                        if (scontext->role == ra->role &&
@@ -271,7 +283,8 @@ static int context_struct_compute_av(struct context *scontext,
                                break;
                }
                if (!ra)
-                       avd->allowed = (avd->allowed) & ~(PROCESS__TRANSITION);
+                       avd->allowed = (avd->allowed) & ~(PROCESS__TRANSITION |
+                                                       PROCESS__DYNTRANSITION);
        }
 
        return 0;
@@ -296,7 +309,7 @@ int security_compute_av(u32 ssid,
                        u32 requested,
                        struct av_decision *avd)
 {
-       struct context *scontext = 0, *tcontext = 0;
+       struct context *scontext = NULL, *tcontext = NULL;
        int rc = 0;
 
        if (!ss_initialized) {
@@ -343,7 +356,7 @@ int context_struct_to_string(struct context *context, char **scontext, u32 *scon
 {
        char *scontextp;
 
-       *scontext = 0;
+       *scontext = NULL;
        *scontext_len = 0;
 
        /* Compute the size of the context. */
@@ -588,8 +601,8 @@ static int security_compute_sid(u32 ssid,
                                u32 specified,
                                u32 *out_sid)
 {
-       struct context *scontext = 0, *tcontext = 0, newcontext;
-       struct role_trans *roletr = 0;
+       struct context *scontext = NULL, *tcontext = NULL, newcontext;
+       struct role_trans *roletr = NULL;
        struct avtab_key avkey;
        struct avtab_datum *avdatum;
        struct avtab_node *node;
@@ -1022,15 +1035,19 @@ int security_load_policy(void *data, size_t len)
        LOAD_LOCK;
 
        if (!ss_initialized) {
+               avtab_cache_init();
                if (policydb_read(&policydb, fp)) {
                        LOAD_UNLOCK;
+                       avtab_cache_destroy();
                        return -EINVAL;
                }
                if (policydb_load_isids(&policydb, &sidtab)) {
                        LOAD_UNLOCK;
                        policydb_destroy(&policydb);
+                       avtab_cache_destroy();
                        return -EINVAL;
                }
+               policydb_loaded_version = policydb.policyvers;
                ss_initialized = 1;
 
                LOAD_UNLOCK;
@@ -1079,7 +1096,7 @@ int security_load_policy(void *data, size_t len)
        memcpy(&policydb, &newpolicydb, sizeof policydb);
        sidtab_set(&sidtab, &newsidtab);
        seqno = ++latest_granting;
-
+       policydb_loaded_version = policydb.policyvers;
        POLICY_WRUNLOCK;
        LOAD_UNLOCK;