@@ -136,6 +136,24 @@ 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)
+{
+ int rc;
+
+ if ( !flask_enforcing || security_get_allow_unknown() )
+ {
+ printk(XENLOG_G_WARNING "FLASK: Allowing unknown %s: %d.\n", name, id);
+ rc = 0;
+ }
+ else
+ {
+ printk(XENLOG_G_ERR "FLASK: Denying unknown %s: %d.\n", name, id);
+ rc = -EPERM;
+ }
+
+ return rc;
+}
+
static int flask_domain_alloc_security(struct domain *d)
{
struct domain_security_struct *dsec;
@@ -271,7 +289,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;
@@ -423,7 +441,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);
@@ -455,7 +473,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);
@@ -521,8 +539,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);
}
}
@@ -537,8 +554,7 @@ static int flask_sysctl_scheduler_op(int op)
return domain_has_xen(current->domain, XEN__GETSCHEDULER);
default:
- printk("flask_sysctl_scheduler_op: Unknown op %d\n", op);
- return -EPERM;
+ return avc_unknown_permission("sysctl_scheduler_op", op);
}
}
@@ -735,8 +751,7 @@ static int flask_domctl(struct domain *d, int cmd)
return current_has_perm(d, SECCLASS_DOMAIN2, DOMAIN2__SOFT_RESET);
default:
- printk("flask_domctl: Unknown op %d\n", cmd);
- return -EPERM;
+ return avc_unknown_permission("domctl", cmd);
}
}
@@ -811,8 +826,7 @@ static int flask_sysctl(int cmd)
XEN2__LIVEPATCH_OP, NULL);
default:
- printk("flask_sysctl: Unknown op %d\n", cmd);
- return -EPERM;
+ return avc_unknown_permission("sysctl", cmd);
}
}
@@ -1129,7 +1143,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);
}
}
@@ -1402,8 +1416,7 @@ static int flask_platform_op(uint32_t op)
SECCLASS_XEN2, XEN2__GET_SYMBOL, NULL);
default:
- printk("flask_platform_op: Unknown op %d\n", op);
- return -EPERM;
+ return avc_unknown_permission("platform_op", op);
}
}
@@ -1434,7 +1447,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);
@@ -1538,7 +1551,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);
@@ -78,6 +78,8 @@ int security_sid_to_context(u32 sid, char **scontext, u32 *scontext_len);
int security_context_to_sid(char *scontext, u32 scontext_len, u32 *out_sid);
+int security_get_allow_unknown(void);
+
int security_irq_sid(int pirq, u32 *out_sid);
int security_iomem_sid(unsigned long, u32 *out_sid);
@@ -1843,6 +1843,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 )
@@ -246,6 +246,8 @@ struct policydb {
unsigned int policyvers;
+ unsigned int allow_unknown : 1;
+
u16 target_type;
};
@@ -261,6 +263,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
@@ -1465,6 +1465,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
When an unknown domctl, sysctl, or other operation is encountered in the FLASK security server, use the allow_unknown bit in the security policy 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. This patch will allow operations that are not handled by the existing hooks only if the policy was compiled with "checkpolicy -U allow". In previous releases, this bit did nothing, and the default remains to deny the unknown operations. Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> --- xen/xsm/flask/hooks.c | 45 ++++++++++++++++++++++++++-------------- 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, 43 insertions(+), 16 deletions(-)