int security_get_classes(char ***classes, int *nclasses);
 int security_get_permissions(char *class, char ***perms, int *nperms);
+int security_get_reject_unknown(void);
+int security_get_allow_unknown(void);
 
 #define SECURITY_FS_USE_XATTR          1 /* use xattr */
 #define SECURITY_FS_USE_TRANS          2 /* use transition SIDs, e.g. devpts/tmpfs */
 
        SEL_MEMBER,     /* compute polyinstantiation membership decision */
        SEL_CHECKREQPROT, /* check requested protection, not kernel-applied one */
        SEL_COMPAT_NET, /* whether to use old compat network packet controls */
+       SEL_REJECT_UNKNOWN, /* export unknown reject handling to userspace */
+       SEL_DENY_UNKNOWN, /* export unknown deny handling to userspace */
        SEL_INO_NEXT,   /* The next inode number to use */
 };
 
        .write          = sel_write_enforce,
 };
 
+static ssize_t sel_read_handle_unknown(struct file *filp, char __user *buf,
+                                       size_t count, loff_t *ppos)
+{
+       char tmpbuf[TMPBUFLEN];
+       ssize_t length;
+       ino_t ino = filp->f_path.dentry->d_inode->i_ino;
+       int handle_unknown = (ino == SEL_REJECT_UNKNOWN) ?
+               security_get_reject_unknown() : !security_get_allow_unknown();
+
+       length = scnprintf(tmpbuf, TMPBUFLEN, "%d", handle_unknown);
+       return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
+}
+
+static const struct file_operations sel_handle_unknown_ops = {
+       .read           = sel_read_handle_unknown,
+};
+
 #ifdef CONFIG_SECURITY_SELINUX_DISABLE
 static ssize_t sel_write_disable(struct file * file, const char __user * buf,
                                 size_t count, loff_t *ppos)
                length = count;
 
 out1:
+
+       printk(KERN_INFO "SELinux: policy loaded with handle_unknown=%s\n",
+              (security_get_reject_unknown() ? "reject" :
+               (security_get_allow_unknown() ? "allow" : "deny")));
+
        audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_POLICY_LOAD,
                "policy loaded auid=%u",
                audit_get_loginuid(current->audit_context));
                [SEL_MEMBER] = {"member", &transaction_ops, S_IRUGO|S_IWUGO},
                [SEL_CHECKREQPROT] = {"checkreqprot", &sel_checkreqprot_ops, S_IRUGO|S_IWUSR},
                [SEL_COMPAT_NET] = {"compat_net", &sel_compat_net_ops, S_IRUGO|S_IWUSR},
+               [SEL_REJECT_UNKNOWN] = {"reject_unknown", &sel_handle_unknown_ops, S_IRUGO},
+               [SEL_DENY_UNKNOWN] = {"deny_unknown", &sel_handle_unknown_ops, S_IRUGO},
                /* last one */ {""}
        };
        ret = simple_fill_super(sb, SELINUX_MAGIC, selinux_files);
 
        }
        kfree(p->type_attr_map);
 
+       kfree(p->undefined_perms);
+
        return;
 }
 
                        goto bad;
                }
        }
+       p->reject_unknown = !!(le32_to_cpu(buf[1]) & REJECT_UNKNOWN);
+       p->allow_unknown = !!(le32_to_cpu(buf[1]) & ALLOW_UNKNOWN);
 
        info = policydb_lookup_compat(p->policyvers);
        if (!info) {
 
        struct ebitmap *type_attr_map;
 
        unsigned int policyvers;
+
+       unsigned int reject_unknown : 1;
+       unsigned int allow_unknown : 1;
+       u32 *undefined_perms;
 };
 
 extern void policydb_destroy(struct policydb *p);
 
 #define POLICYDB_CONFIG_MLS    1
 
+/* the config flags related to unknown classes/perms are bits 2 and 3 */
+#define REJECT_UNKNOWN 0x00000002
+#define ALLOW_UNKNOWN  0x00000004
+
 #define OBJECT_R "object_r"
 #define OBJECT_R_VAL 1
 
 
        struct class_datum *tclass_datum;
        struct ebitmap *sattr, *tattr;
        struct ebitmap_node *snode, *tnode;
+       const struct selinux_class_perm *kdefs = &selinux_class_perm;
        unsigned int i, j;
 
        /*
                    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);
-               return -EINVAL;
-       }
-       tclass_datum = policydb.class_val_to_struct[tclass - 1];
-
        /*
         * Initialize the access vectors to the default values.
         */
        avd->auditdeny = 0xffffffff;
        avd->seqno = latest_granting;
 
+       /*
+        * Check for all the invalid cases.
+        * - tclass 0
+        * - tclass > policy and > kernel
+        * - tclass > policy but is a userspace class
+        * - tclass > policy but we do not allow unknowns
+        */
+       if (unlikely(!tclass))
+               goto inval_class;
+       if (unlikely(tclass > policydb.p_classes.nprim))
+               if (tclass > kdefs->cts_len ||
+                   !kdefs->class_to_string[tclass - 1] ||
+                   !policydb.allow_unknown)
+                       goto inval_class;
+
+       /*
+        * Kernel class and we allow unknown so pad the allow decision
+        * the pad will be all 1 for unknown classes.
+        */
+       if (tclass <= kdefs->cts_len && policydb.allow_unknown)
+               avd->allowed = policydb.undefined_perms[tclass - 1];
+
+       /*
+        * Not in policy. Since decision is completed (all 1 or all 0) return.
+        */
+       if (unlikely(tclass > policydb.p_classes.nprim))
+               return 0;
+
+       tclass_datum = policydb.class_val_to_struct[tclass - 1];
+
        /*
         * If a specific type enforcement rule was defined for
         * this permission check, then use it.
        }
 
        return 0;
+
+inval_class:
+       printk(KERN_ERR "%s:  unrecognized class %d\n", __FUNCTION__, tclass);
+       return -EINVAL;
 }
 
 static int security_validtrans_handle_fail(struct context *ocontext,
        const char *def_class, *def_perm, *pol_class;
        struct symtab *perms;
 
+       if (p->allow_unknown) {
+               u32 num_classes = kdefs->cts_len;
+               p->undefined_perms = kcalloc(num_classes, sizeof(u32), GFP_KERNEL);
+               if (!p->undefined_perms)
+                       return -ENOMEM;
+       }
+
        for (i = 1; i < kdefs->cts_len; i++) {
                def_class = kdefs->class_to_string[i];
                if (!def_class)
                        printk(KERN_INFO
                               "security:  class %s not defined in policy\n",
                               def_class);
+                       if (p->reject_unknown)
+                               return -EINVAL;
+                       if (p->allow_unknown)
+                               p->undefined_perms[i-1] = ~0U;
                        continue;
                }
                pol_class = p->p_class_val_to_name[i-1];
                        printk(KERN_INFO
                               "security:  permission %s in class %s not defined in policy\n",
                               def_perm, pol_class);
+                       if (p->reject_unknown)
+                               return -EINVAL;
+                       if (p->allow_unknown)
+                               p->undefined_perms[class_val-1] |= perm_val;
                        continue;
                }
                perdatum = hashtab_search(perms->table, def_perm);
                if (perdatum == NULL) {
                        printk(KERN_ERR
-                              "security:  permission %s in class %s not found in policy\n",
+                              "security:  permission %s in class %s not found in policy, bad policy\n",
                               def_perm, pol_class);
                        return -EINVAL;
                }
                                printk(KERN_INFO
                                       "security:  permission %s in class %s not defined in policy\n",
                                       def_perm, pol_class);
+                               if (p->reject_unknown)
+                                       return -EINVAL;
+                               if (p->allow_unknown)
+                                       p->undefined_perms[class_val-1] |= (1 << j);
                                continue;
                        }
                        perdatum = hashtab_search(perms->table, def_perm);
                        if (perdatum == NULL) {
                                printk(KERN_ERR
-                                      "security:  permission %s in class %s not found in policy\n",
+                                      "security:  permission %s in class %s not found in policy, bad policy\n",
                                       def_perm, pol_class);
                                return -EINVAL;
                        }
        return rc;
 }
 
+int security_get_reject_unknown(void)
+{
+       return policydb.reject_unknown;
+}
+
+int security_get_allow_unknown(void)
+{
+       return policydb.allow_unknown;
+}
+
 struct selinux_audit_rule {
        u32 au_seqno;
        struct context au_ctxt;