[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH] xsm/flask: improve unknown permission handling



When an unknown domctl, sysctl, or other operation is encountered in the
FLASK security server, use the allow_unknown bit in the security policy
(set by running checkpolicy -U allow) to decide if the permission should
be allowed or denied.  This allows new operations to be tested without
needing to immediately add security checks; however, it is not flexible
enough to avoid adding the actual permission checks.  An error message
is printed to the hypervisor console when this fallback is encountered.

Signed-off-by: Daniel De Graaf <dgdegra@xxxxxxxxxxxxx>
---
 xen/xsm/flask/hooks.c            | 40 ++++++++++++++++++++++++----------------
 xen/xsm/flask/include/security.h |  2 ++
 xen/xsm/flask/ss/policydb.c      |  1 +
 xen/xsm/flask/ss/policydb.h      |  6 ++++++
 xen/xsm/flask/ss/services.c      |  5 +++++
 5 files changed, 38 insertions(+), 16 deletions(-)

diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c
index 0ba2ce9..4c8a1d2 100644
--- a/xen/xsm/flask/hooks.c
+++ b/xen/xsm/flask/hooks.c
@@ -135,6 +135,19 @@ static int get_irq_sid(int irq, u32 *sid, struct 
avc_audit_data *ad)
     return 0;
 }
 
+static int avc_unknown_permission(const char* name, int id)
+{
+    /* A guest making an invalid hypercall can trigger this message, so it 
can't
+     * be an ASSERT or BUG_ON, but normally it is caused by a missing case in
+     * one of the switch statements below.
+     */
+    printk(XENLOG_G_ERR "FLASK: Unknown %s: %d.\n", name, id);
+    if ( !flask_enforcing || security_get_allow_unknown() )
+        return 0;
+    else
+        return -EPERM;
+}
+
 static int flask_domain_alloc_security(struct domain *d)
 {
     struct domain_security_struct *dsec;
@@ -270,7 +283,7 @@ static int flask_evtchn_send(struct domain *d, struct 
evtchn *chn)
         rc = 0;
         break;
     default:
-        rc = -EPERM;
+        rc = avc_unknown_permission("event channel state", chn->state);
     }
 
     return rc;
@@ -422,7 +435,7 @@ static int flask_console_io(struct domain *d, int cmd)
         perm = XEN__WRITECONSOLE;
         break;
     default:
-        return -EPERM;
+        return avc_unknown_permission("console_io", cmd);
     }
 
     return domain_has_xen(d, perm);
@@ -454,7 +467,7 @@ static int flask_profile(struct domain *d, int op)
         perm = XEN__PRIVPROFILE;
         break;
     default:
-        return -EPERM;
+        return avc_unknown_permission("xenoprof op", op);
     }
 
     return domain_has_xen(d, perm);
@@ -520,8 +533,7 @@ static int flask_domctl_scheduler_op(struct domain *d, int 
op)
         return current_has_perm(d, SECCLASS_DOMAIN, DOMAIN__GETSCHEDULER);
 
     default:
-        printk("flask_domctl_scheduler_op: Unknown op %d\n", op);
-        return -EPERM;
+        return avc_unknown_permission("domctl_scheduler_op", op);
     }
 }
 
@@ -536,8 +548,7 @@ static int flask_sysctl_scheduler_op(int op)
         return domain_has_xen(current->domain, XEN__GETSCHEDULER);
 
     default:
-        printk("flask_domctl_scheduler_op: Unknown op %d\n", op);
-        return -EPERM;
+        return avc_unknown_permission("sysctl_scheduler_op", op);
     }
 }
 
@@ -731,8 +742,7 @@ static int flask_domctl(struct domain *d, int cmd)
         return current_has_perm(d, SECCLASS_DOMAIN2, 
DOMAIN2__CONFIGURE_DOMAIN);
 
     default:
-        printk("flask_domctl: Unknown op %d\n", cmd);
-        return -EPERM;
+        return avc_unknown_permission("domctl", cmd);
     }
 }
 
@@ -790,8 +800,7 @@ static int flask_sysctl(int cmd)
                                     XEN2__PSR_CMT_OP, NULL);
 
     default:
-        printk("flask_sysctl: Unknown op %d\n", cmd);
-        return -EPERM;
+        return avc_unknown_permission("sysctl", cmd);
     }
 }
 
@@ -1078,7 +1087,7 @@ static inline int flask_page_offline(uint32_t cmd)
     case sysctl_query_page_offline:
         return flask_resource_use_core();
     default:
-        return -EPERM;
+        return avc_unknown_permission("page_offline", cmd);
     }
 }
 
@@ -1240,7 +1249,7 @@ static int flask_shadow_control(struct domain *d, 
uint32_t op)
         perm = SHADOW__LOGDIRTY;
         break;
     default:
-        return -EPERM;
+        return avc_unknown_permission("shadow_control", op);
     }
 
     return current_has_perm(d, SECCLASS_SHADOW, perm);
@@ -1344,7 +1353,7 @@ static int flask_apic(struct domain *d, int cmd)
         perm = XEN__WRITEAPIC;
         break;
     default:
-        return -EPERM;
+        return avc_unknown_permission("apic", cmd);
     }
 
     return domain_has_xen(d, perm);
@@ -1409,8 +1418,7 @@ static int flask_platform_op(uint32_t op)
                                     XEN2__RESOURCE_OP, NULL);
 
     default:
-        printk("flask_platform_op: Unknown op %d\n", op);
-        return -EPERM;
+        return avc_unknown_permission("platform_op", op);
     }
 }
 
diff --git a/xen/xsm/flask/include/security.h b/xen/xsm/flask/include/security.h
index 348f018..a93f14a 100644
--- a/xen/xsm/flask/include/security.h
+++ b/xen/xsm/flask/include/security.h
@@ -71,6 +71,8 @@ int security_context_to_sid(char *scontext, u32 scontext_len, 
u32 *out_sid);
 
 int security_get_user_sids(u32 callsid, char *username, u32 **sids, u32 *nel);
 
+int security_get_allow_unknown(void);
+
 int security_irq_sid(int pirq, u32 *out_sid);
 
 int security_iomem_sid(unsigned long, u32 *out_sid);
diff --git a/xen/xsm/flask/ss/policydb.c b/xen/xsm/flask/ss/policydb.c
index 50b2c78..b648f05 100644
--- a/xen/xsm/flask/ss/policydb.c
+++ b/xen/xsm/flask/ss/policydb.c
@@ -1802,6 +1802,7 @@ int policydb_read(struct policydb *p, void *fp)
             goto bad;
         }
     }
+    p->allow_unknown = !!(le32_to_cpu(buf[1]) & ALLOW_UNKNOWN);
 
     if ( p->policyvers >= POLICYDB_VERSION_POLCAP &&
          ebitmap_read(&p->policycaps, fp) != 0 )
diff --git a/xen/xsm/flask/ss/policydb.h b/xen/xsm/flask/ss/policydb.h
index b176300..aeaf69b 100644
--- a/xen/xsm/flask/ss/policydb.h
+++ b/xen/xsm/flask/ss/policydb.h
@@ -245,6 +245,8 @@ struct policydb {
 
     unsigned int policyvers;
 
+    unsigned int allow_unknown : 1;
+
     u16 target_type;
 };
 
@@ -260,6 +262,10 @@ extern int policydb_read(struct policydb *p, void *fp);
 
 #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
 
diff --git a/xen/xsm/flask/ss/services.c b/xen/xsm/flask/ss/services.c
index f0e459a..9b18509 100644
--- a/xen/xsm/flask/ss/services.c
+++ b/xen/xsm/flask/ss/services.c
@@ -1464,6 +1464,11 @@ err:
 
 }
 
+int security_get_allow_unknown(void)
+{
+    return policydb.allow_unknown;
+}
+
 /**
  * security_irq_sid - Obtain the SID for a physical irq.
  * @pirq: physical irq
-- 
1.9.3


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.