config SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE
        int "NSA SELinux maximum supported policy format version value"
        depends on SECURITY_SELINUX_POLICYDB_VERSION_MAX
-       range 15 22
+       range 15 23
        default 19
        help
          This option sets the value for the maximum policy format version
 
        denied = requested & ~(p_ae->avd.allowed);
 
        if (denied) {
-               if (selinux_enforcing || (flags & AVC_STRICT))
+               if (flags & AVC_STRICT)
                        rc = -EACCES;
+               else if (!selinux_enforcing || security_permissive_sid(ssid))
+                       avc_update_node(AVC_CALLBACK_GRANT, requested, ssid,
+                                       tsid, tclass);
                else
-                       if (node)
-                               avc_update_node(AVC_CALLBACK_GRANT,requested,
-                                               ssid,tsid,tclass);
+                       rc = -EACCES;
        }
 
        rcu_read_unlock();
 
 #define POLICYDB_VERSION_AVTAB         20
 #define POLICYDB_VERSION_RANGETRANS    21
 #define POLICYDB_VERSION_POLCAP                22
+#define POLICYDB_VERSION_PERMISSIVE    23
 
 /* 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_POLCAP
+#define POLICYDB_VERSION_MAX   POLICYDB_VERSION_PERMISSIVE
 #endif
 
 #define CONTEXT_MNT    0x01
        u32 seqno;
 };
 
+int security_permissive_sid(u32 sid);
+
 int security_compute_av(u32 ssid, u32 tsid,
        u16 tclass, u32 requested,
        struct av_decision *avd);
 
                .version        = POLICYDB_VERSION_POLCAP,
                .sym_num        = SYM_NUM,
                .ocon_num       = OCON_NUM,
+       },
+       {
+               .version        = POLICYDB_VERSION_PERMISSIVE,
+               .sym_num        = SYM_NUM,
+               .ocon_num       = OCON_NUM,
        }
 };
 
                goto out_free_symtab;
 
        ebitmap_init(&p->policycaps);
+       ebitmap_init(&p->permissive_map);
 
 out:
        return rc;
        kfree(p->type_attr_map);
        kfree(p->undefined_perms);
        ebitmap_destroy(&p->policycaps);
+       ebitmap_destroy(&p->permissive_map);
 
        return;
 }
            ebitmap_read(&p->policycaps, fp) != 0)
                goto bad;
 
+       if (p->policyvers >= POLICYDB_VERSION_PERMISSIVE &&
+           ebitmap_read(&p->permissive_map, fp) != 0)
+               goto bad;
+
        info = policydb_lookup_compat(p->policyvers);
        if (!info) {
                printk(KERN_ERR "SELinux:  unable to find policy compat info "
 
 
        struct ebitmap policycaps;
 
+       struct ebitmap permissive_map;
+
        unsigned int policyvers;
 
        unsigned int reject_unknown : 1;
 
        return -EINVAL;
 }
 
+/*
+ * Given a sid find if the type has the permissive flag set
+ */
+int security_permissive_sid(u32 sid)
+{
+       struct context *context;
+       u32 type;
+       int rc;
+
+       POLICY_RDLOCK;
+
+       context = sidtab_search(&sidtab, sid);
+       BUG_ON(!context);
+
+       type = context->type;
+       /*
+        * we are intentionally using type here, not type-1, the 0th bit may
+        * someday indicate that we are globally setting permissive in policy.
+        */
+       rc = ebitmap_get_bit(&policydb.permissive_map, type);
+
+       POLICY_RDUNLOCK;
+       return rc;
+}
+
 static int security_validtrans_handle_fail(struct context *ocontext,
                                            struct context *ncontext,
                                            struct context *tcontext,