Daniel De Graaf
2012-Jan-31 21:26 UTC
[PATCH 00/10] FLASK updates: MSI interrupts, cleanups
This patch set adds XSM security labels to useful debugging output locations, and fixes some assumptions that all interrupts behaved like GSI interrupts (which had useful non-dynamic IDs). It also cleans up the policy build process and adds an example of how to use the user field in the security context. Debug output: [PATCH 01/10] xsm: Add security labels to event-channel dump [PATCH 02/10] xsm: Add security label to IRQ debug output MSI interrupt fixes: [PATCH 03/10] xsm/flask: Use PCI device label for PCI-MSI IRQs [PATCH 04/10] xsm: Add xsm_map_domain_pirq hook [PATCH 05/10] xsm: Use mapped IRQ not PIRQ in unmap_domain_pirq Cleanup: [PATCH 06/10] xsm/flask: Improve error reporting for ocontexts [PATCH 07/10] xsm/flask: Remove useless back pointers [PATCH 08/10] flask/policy: Policy build updates [PATCH 09/10] flask/policy: Add user and constraint examples [PATCH 10/10] flask/policy: use declare_domain for dom0_t
Daniel De Graaf
2012-Jan-31 21:26 UTC
[PATCH 01/10] xsm: Add security labels to event-channel dump
In FLASK, event channel labels are distinct from the labels of the domain using them. When debugging policy issues, it is useful to be able to view the current label of event channels; add this label to the event channel dump. This patch also adds the IRQ associated with a PIRQ for event channels bound to a PIRQ, and moves the xen_consumer flag to the front to create more consistent alignment in the output. Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> --- xen/common/event_channel.c | 19 +++++++++++++++---- xen/include/xsm/xsm.h | 6 ++++++ xen/xsm/dummy.c | 6 ++++++ xen/xsm/flask/hooks.c | 30 ++++++++++++++++++++++++++++++ 4 files changed, 57 insertions(+), 4 deletions(-) diff --git a/xen/common/event_channel.c b/xen/common/event_channel.c index f784254..989ebae 100644 --- a/xen/common/event_channel.c +++ b/xen/common/event_channel.c @@ -1256,6 +1256,7 @@ void evtchn_move_pirqs(struct vcpu *v) static void domain_dump_evtchn_info(struct domain *d) { unsigned int port; + int irq; bitmap_scnlistprintf(keyhandler_scratch, sizeof(keyhandler_scratch), d->poll_mask, d->max_vcpus); @@ -1268,6 +1269,7 @@ static void domain_dump_evtchn_info(struct domain *d) for ( port = 1; port < MAX_EVTCHNS(d); ++port ) { const struct evtchn *chn; + char *ssid; if ( !port_is_valid(d, port) ) continue; @@ -1275,11 +1277,12 @@ static void domain_dump_evtchn_info(struct domain *d) if ( chn->state == ECS_FREE ) continue; - printk(" %4u [%d/%d]: s=%d n=%d", + printk(" %4u [%d/%d]: s=%d n=%d x=%d", port, !!test_bit(port, &shared_info(d, evtchn_pending)), !!test_bit(port, &shared_info(d, evtchn_mask)), - chn->state, chn->notify_vcpu_id); + chn->state, chn->notify_vcpu_id, chn->xen_consumer); + switch ( chn->state ) { case ECS_UNBOUND: @@ -1291,13 +1294,21 @@ static void domain_dump_evtchn_info(struct domain *d) chn->u.interdomain.remote_port); break; case ECS_PIRQ: - printk(" p=%d", chn->u.pirq.irq); + irq = domain_pirq_to_irq(d, chn->u.pirq.irq); + printk(" p=%d i=%d", chn->u.pirq.irq, irq); break; case ECS_VIRQ: printk(" v=%d", chn->u.virq); break; } - printk(" x=%d\n", chn->xen_consumer); + + ssid = xsm_show_security_evtchn(d, chn); + if (ssid) { + printk(" Z=%s\n", ssid); + xfree(ssid); + } else { + printk("\n"); + } } spin_unlock(&d->event_lock); diff --git a/xen/include/xsm/xsm.h b/xen/include/xsm/xsm.h index e3cae60..92204b3 100644 --- a/xen/include/xsm/xsm.h +++ b/xen/include/xsm/xsm.h @@ -99,6 +99,7 @@ struct xsm_operations { void (*free_security_domain) (struct domain *d); int (*alloc_security_evtchn) (struct evtchn *chn); void (*free_security_evtchn) (struct evtchn *chn); + char *(*show_security_evtchn) (struct domain *d, const struct evtchn *chn); int (*get_pod_target) (struct domain *d); int (*set_pod_target) (struct domain *d); @@ -424,6 +425,11 @@ static inline void xsm_free_security_evtchn (struct evtchn *chn) (void)xsm_call(free_security_evtchn(chn)); } +static inline char *xsm_show_security_evtchn (struct domain *d, const struct evtchn *chn) +{ + return xsm_call(show_security_evtchn(d, chn)); +} + static inline int xsm_get_pod_target (struct domain *d) { return xsm_call(get_pod_target(d)); diff --git a/xen/xsm/dummy.c b/xen/xsm/dummy.c index d99f886..fca9d7b 100644 --- a/xen/xsm/dummy.c +++ b/xen/xsm/dummy.c @@ -290,6 +290,11 @@ static void dummy_free_security_evtchn (struct evtchn *chn) return; } +static char *dummy_show_security_evtchn (struct domain *d, const struct evtchn *chn) +{ + return NULL; +} + static int dummy_test_assign_device (uint32_t machine_bdf) { return 0; @@ -637,6 +642,7 @@ void xsm_fixup_ops (struct xsm_operations *ops) set_to_dummy_if_null(ops, free_security_domain); set_to_dummy_if_null(ops, alloc_security_evtchn); set_to_dummy_if_null(ops, free_security_evtchn); + set_to_dummy_if_null(ops, show_security_evtchn); set_to_dummy_if_null(ops, memory_adjust_reservation); set_to_dummy_if_null(ops, memory_stat_reservation); diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c index 543dc77..d207b1d 100644 --- a/xen/xsm/flask/hooks.c +++ b/xen/xsm/flask/hooks.c @@ -274,6 +274,35 @@ static void flask_free_security_evtchn(struct evtchn *chn) xfree(esec); } +static char *flask_show_security_evtchn(struct domain *d, const struct evtchn *chn) +{ + struct evtchn_security_struct *esec; + int irq; + u32 sid = 0; + char *ctx; + u32 ctx_len; + + switch ( chn->state ) + { + case ECS_UNBOUND: + case ECS_INTERDOMAIN: + esec = chn->ssid; + if ( esec ) + sid = esec->sid; + break; + case ECS_PIRQ: + irq = domain_pirq_to_irq(d, chn->u.pirq.irq); + if (irq) + security_irq_sid(irq, &sid); + break; + } + if ( !sid ) + return NULL; + if (security_sid_to_context(sid, &ctx, &ctx_len)) + return NULL; + return ctx; +} + static int flask_grant_mapref(struct domain *d1, struct domain *d2, uint32_t flags) { @@ -1499,6 +1528,7 @@ static struct xsm_operations flask_ops = { .free_security_domain = flask_domain_free_security, .alloc_security_evtchn = flask_alloc_security_evtchn, .free_security_evtchn = flask_free_security_evtchn, + .show_security_evtchn = flask_show_security_evtchn, .get_pod_target = flask_get_pod_target, .set_pod_target = flask_set_pod_target, -- 1.7.7.6
Daniel De Graaf
2012-Jan-31 21:26 UTC
[PATCH 02/10] xsm: Add security label to IRQ debug output
Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> --- xen/arch/x86/irq.c | 8 ++++++++ xen/include/xsm/xsm.h | 7 +++++++ xen/xsm/dummy.c | 7 ++++++- xen/xsm/flask/hooks.c | 16 ++++++++++++++++ 4 files changed, 37 insertions(+), 1 deletions(-) diff --git a/xen/arch/x86/irq.c b/xen/arch/x86/irq.c index 058f89d..6d17ec0 100644 --- a/xen/arch/x86/irq.c +++ b/xen/arch/x86/irq.c @@ -2001,6 +2001,7 @@ static void dump_irqs(unsigned char key) struct domain *d; const struct pirq *info; unsigned long flags; + char *ssid; printk("Guest interrupt information:\n"); @@ -2012,6 +2013,8 @@ static void dump_irqs(unsigned char key) if ( !irq_desc_initialized(desc) || desc->handler == &no_irq_type ) continue; + ssid = xsm_show_irq_sid(irq); + spin_lock_irqsave(&desc->lock, flags); cpumask_scnprintf(keyhandler_scratch, sizeof(keyhandler_scratch), @@ -2021,6 +2024,9 @@ static void dump_irqs(unsigned char key) irq, keyhandler_scratch, desc->arch.vector, desc->handler->typename, desc->status); + if ( ssid ) + printk("Z=%-25s ", ssid); + if ( !(desc->status & IRQ_GUEST) ) printk("mapped, unbound\n"); else @@ -2053,6 +2059,8 @@ static void dump_irqs(unsigned char key) } spin_unlock_irqrestore(&desc->lock, flags); + + xfree(ssid); } dump_ioapic_irq_info(); diff --git a/xen/include/xsm/xsm.h b/xen/include/xsm/xsm.h index 92204b3..6e3a8f0 100644 --- a/xen/include/xsm/xsm.h +++ b/xen/include/xsm/xsm.h @@ -113,6 +113,8 @@ struct xsm_operations { int (*kexec) (void); int (*schedop_shutdown) (struct domain *d1, struct domain *d2); + + char *(*show_irq_sid) (int irq); int (*irq_permission) (struct domain *d, int pirq, uint8_t allow); int (*iomem_permission) (struct domain *d, uint64_t s, uint64_t e, uint8_t allow); int (*pci_config_permission) (struct domain *d, uint32_t machine_bdf, uint16_t start, uint16_t end, uint8_t access); @@ -477,6 +479,11 @@ static inline int xsm_schedop_shutdown (struct domain *d1, struct domain *d2) return xsm_call(schedop_shutdown(d1, d2)); } +static inline char *xsm_show_irq_sid (int irq) +{ + return xsm_call(show_irq_sid(irq)); +} + static inline int xsm_irq_permission (struct domain *d, int pirq, uint8_t allow) { return xsm_call(irq_permission(d, pirq, allow)); diff --git a/xen/xsm/dummy.c b/xen/xsm/dummy.c index fca9d7b..83e5dba 100644 --- a/xen/xsm/dummy.c +++ b/xen/xsm/dummy.c @@ -365,12 +365,16 @@ static int dummy_sched_op (void) return 0; } - static long dummy___do_xsm_op(XEN_GUEST_HANDLE(xsm_op_t) op) { return -ENOSYS; } +static char *dummy_show_irq_sid (int irq) +{ + return NULL; +} + static int dummy_irq_permission (struct domain *d, int pirq, uint8_t allow) { return 0; @@ -655,6 +659,7 @@ void xsm_fixup_ops (struct xsm_operations *ops) set_to_dummy_if_null(ops, kexec); set_to_dummy_if_null(ops, schedop_shutdown); + set_to_dummy_if_null(ops, show_irq_sid); set_to_dummy_if_null(ops, irq_permission); set_to_dummy_if_null(ops, iomem_permission); set_to_dummy_if_null(ops, pci_config_permission); diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c index d207b1d..d79405b 100644 --- a/xen/xsm/flask/hooks.c +++ b/xen/xsm/flask/hooks.c @@ -712,6 +712,20 @@ static inline u32 resource_to_perm(uint8_t access) return RESOURCE__REMOVE; } +static char *flask_show_irq_sid (int irq) +{ + u32 sid, ctx_len; + char *ctx; + int rc = security_irq_sid(irq, &sid); + if ( rc ) + return NULL; + + if (security_sid_to_context(sid, &ctx, &ctx_len)) + return NULL; + + return ctx; +} + static int flask_irq_permission (struct domain *d, int pirq, uint8_t access) { u32 perm; @@ -1543,6 +1557,8 @@ static struct xsm_operations flask_ops = { .kexec = flask_kexec, .schedop_shutdown = flask_schedop_shutdown, + .show_irq_sid = flask_show_irq_sid, + .irq_permission = flask_irq_permission, .iomem_permission = flask_iomem_permission, .pci_config_permission = flask_pci_config_permission, -- 1.7.7.6
Daniel De Graaf
2012-Jan-31 21:26 UTC
[PATCH 03/10] xsm/flask: Use PCI device label for PCI-MSI IRQs
Because the PCI-MSI IRQ numbers are allocated dynamically, labeling them by number is not useful. Instead, for all IRQs beyond nr_irqs_gsi, use the associated msi_desc to find the PCI device and use the label of the PCI device for the IRQ. Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> --- xen/xsm/flask/hooks.c | 53 +++++++++++++++++++++++++++++++++++------------- 1 files changed, 38 insertions(+), 15 deletions(-) diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c index d79405b..0dbf19d 100644 --- a/xen/xsm/flask/hooks.c +++ b/xen/xsm/flask/hooks.c @@ -19,6 +19,7 @@ #include <xen/errno.h> #include <xen/guest_access.h> #include <xen/xenoprof.h> +#include <asm/msi.h> #include <public/xen.h> #include <public/physdev.h> #include <public/platform.h> @@ -62,6 +63,36 @@ static int domain_has_xen(struct domain *d, u32 perms) return avc_has_perm(dsec->sid, SECINITSID_XEN, SECCLASS_XEN, perms, NULL); } +static int get_irq_sid(int irq, u32 *sid, struct avc_audit_data *ad) +{ + struct irq_desc *desc = irq_to_desc(irq); + if ( irq >= nr_irqs || irq < 0 ) + return -EINVAL; + if ( irq < nr_irqs_gsi ) { + if (ad) { + AVC_AUDIT_DATA_INIT(ad, IRQ); + ad->irq = irq; + } + return security_irq_sid(irq, sid); + } + if ( desc->msi_desc ) { + struct pci_dev *dev = desc->msi_desc->dev; + u32 sbdf = (dev->seg << 16) | (dev->bus << 8) | dev->devfn; + if (ad) { + AVC_AUDIT_DATA_INIT(ad, DEV); + ad->device = sbdf; + } + return security_device_sid(sbdf, sid); + } + if (ad) { + AVC_AUDIT_DATA_INIT(ad, IRQ); + ad->irq = irq; + } + /* HPET or IOMMU IRQ, should not be seen by domains */ + *sid = SECINITSID_UNLABELED; + return 0; +} + static int flask_domain_alloc_security(struct domain *d) { struct domain_security_struct *dsec; @@ -292,8 +323,8 @@ static char *flask_show_security_evtchn(struct domain *d, const struct evtchn *c break; case ECS_PIRQ: irq = domain_pirq_to_irq(d, chn->u.pirq.irq); - if (irq) - security_irq_sid(irq, &sid); + if (irq && get_irq_sid(irq, &sid, NULL)) + return NULL; break; } if ( !sid ) @@ -716,7 +747,7 @@ static char *flask_show_irq_sid (int irq) { u32 sid, ctx_len; char *ctx; - int rc = security_irq_sid(irq, &sid); + int rc = get_irq_sid(irq, &sid, NULL); if ( rc ) return NULL; @@ -726,7 +757,7 @@ static char *flask_show_irq_sid (int irq) return ctx; } -static int flask_irq_permission (struct domain *d, int pirq, uint8_t access) +static int flask_irq_permission (struct domain *d, int irq, uint8_t access) { u32 perm; u32 rsid; @@ -749,13 +780,10 @@ static int flask_irq_permission (struct domain *d, int pirq, uint8_t access) ssec = current->domain->ssid; tsec = d->ssid; - rc = security_irq_sid(pirq, &rsid); + rc = get_irq_sid(irq, &rsid, &ad); if ( rc ) return rc; - AVC_AUDIT_DATA_INIT(&ad, IRQ); - ad.irq = pirq; - rc = avc_has_perm(ssec->sid, rsid, SECCLASS_RESOURCE, perm, &ad); if ( rc ) return rc; @@ -915,12 +943,10 @@ static int flask_resource_setup_gsi(int gsi) struct avc_audit_data ad; struct domain_security_struct *ssec; - rc = security_irq_sid(gsi, &rsid); + rc = get_irq_sid(gsi, &rsid, &ad); if ( rc ) return rc; - AVC_AUDIT_DATA_INIT(&ad, IRQ); - ad.irq = gsi; ssec = current->domain->ssid; return avc_has_perm(ssec->sid, rsid, SECCLASS_RESOURCE, RESOURCE__SETUP, &ad); } @@ -1424,13 +1450,10 @@ static int flask_bind_pt_irq (struct domain *d, struct xen_domctl_bind_pt_irq *b irq = domain_pirq_to_irq(d, bind->machine_irq); - rc = security_irq_sid(irq, &rsid); + rc = get_irq_sid(irq, &rsid, &ad); if ( rc ) return rc; - AVC_AUDIT_DATA_INIT(&ad, IRQ); - ad.irq = irq; - ssec = current->domain->ssid; rc = avc_has_perm(ssec->sid, rsid, SECCLASS_HVM, HVM__BIND_IRQ, &ad); if ( rc ) -- 1.7.7.6
When checking permissions in map_domain_pirq, the msi_desc field of the irq_desc is not yet populated with the PCI device being used. Pass in the msi_info structure which contains the intended PCI device whose label will be used in the security check. Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> --- xen/arch/x86/irq.c | 2 +- xen/include/xsm/xsm.h | 6 ++++++ xen/xsm/dummy.c | 6 ++++++ xen/xsm/flask/hooks.c | 37 +++++++++++++++++++++++++++++++++++++ 4 files changed, 50 insertions(+), 1 deletions(-) diff --git a/xen/arch/x86/irq.c b/xen/arch/x86/irq.c index 6d17ec0..bbcfa09 100644 --- a/xen/arch/x86/irq.c +++ b/xen/arch/x86/irq.c @@ -1828,7 +1828,7 @@ int map_domain_pirq( return 0; } - ret = xsm_irq_permission(d, irq, 1); + ret = xsm_map_domain_pirq(d, irq, data); if ( ret ) { dprintk(XENLOG_G_ERR, "dom%d: could not permit access to irq %d mapping to pirq %d\n", diff --git a/xen/include/xsm/xsm.h b/xen/include/xsm/xsm.h index 6e3a8f0..e896f73 100644 --- a/xen/include/xsm/xsm.h +++ b/xen/include/xsm/xsm.h @@ -115,6 +115,7 @@ struct xsm_operations { int (*schedop_shutdown) (struct domain *d1, struct domain *d2); char *(*show_irq_sid) (int irq); + int (*map_domain_pirq) (struct domain *d, int irq, void *data); int (*irq_permission) (struct domain *d, int pirq, uint8_t allow); int (*iomem_permission) (struct domain *d, uint64_t s, uint64_t e, uint8_t allow); int (*pci_config_permission) (struct domain *d, uint32_t machine_bdf, uint16_t start, uint16_t end, uint8_t access); @@ -484,6 +485,11 @@ static inline char *xsm_show_irq_sid (int irq) return xsm_call(show_irq_sid(irq)); } +static inline int xsm_map_domain_pirq (struct domain *d, int irq, void *data) +{ + return xsm_call(map_domain_pirq(d, irq, data)); +} + static inline int xsm_irq_permission (struct domain *d, int pirq, uint8_t allow) { return xsm_call(irq_permission(d, pirq, allow)); diff --git a/xen/xsm/dummy.c b/xen/xsm/dummy.c index 83e5dba..7027ee7 100644 --- a/xen/xsm/dummy.c +++ b/xen/xsm/dummy.c @@ -375,6 +375,11 @@ static char *dummy_show_irq_sid (int irq) return NULL; } +static int dummy_map_domain_pirq (struct domain *d, int irq, void *data) +{ + return 0; +} + static int dummy_irq_permission (struct domain *d, int pirq, uint8_t allow) { return 0; @@ -660,6 +665,7 @@ void xsm_fixup_ops (struct xsm_operations *ops) set_to_dummy_if_null(ops, schedop_shutdown); set_to_dummy_if_null(ops, show_irq_sid); + set_to_dummy_if_null(ops, map_domain_pirq); set_to_dummy_if_null(ops, irq_permission); set_to_dummy_if_null(ops, iomem_permission); set_to_dummy_if_null(ops, pci_config_permission); diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c index 0dbf19d..a095915 100644 --- a/xen/xsm/flask/hooks.c +++ b/xen/xsm/flask/hooks.c @@ -757,6 +757,42 @@ static char *flask_show_irq_sid (int irq) return ctx; } +static int flask_map_domain_pirq (struct domain *d, int irq, void *data) +{ + u32 sid; + int rc = -EPERM; + struct msi_info *msi = data; + + struct domain_security_struct *ssec, *tsec; + struct avc_audit_data ad; + + rc = domain_has_perm(current->domain, d, SECCLASS_RESOURCE, RESOURCE__ADD); + + if ( rc ) + return rc; + + if ( irq >= nr_irqs_gsi && msi ) { + u32 machine_bdf = (msi->seg << 16) | (msi->bus << 8) | msi->devfn; + AVC_AUDIT_DATA_INIT(&ad, DEV); + ad.device = machine_bdf; + rc = security_device_sid(machine_bdf, &sid); + } else { + rc = get_irq_sid(irq, &sid, &ad); + } + if ( rc ) + return rc; + + ssec = current->domain->ssid; + tsec = d->ssid; + + rc = avc_has_perm(ssec->sid, sid, SECCLASS_RESOURCE, RESOURCE__ADD_IRQ, &ad); + if ( rc ) + return rc; + + rc = avc_has_perm(tsec->sid, sid, SECCLASS_RESOURCE, RESOURCE__USE, &ad); + return rc; +} + static int flask_irq_permission (struct domain *d, int irq, uint8_t access) { u32 perm; @@ -1582,6 +1618,7 @@ static struct xsm_operations flask_ops = { .show_irq_sid = flask_show_irq_sid, + .map_domain_pirq = flask_map_domain_pirq, .irq_permission = flask_irq_permission, .iomem_permission = flask_iomem_permission, .pci_config_permission = flask_pci_config_permission, -- 1.7.7.6
Daniel De Graaf
2012-Jan-31 21:26 UTC
[PATCH 05/10] xsm: Use mapped IRQ not PIRQ in unmap_domain_pirq
XSM permissions are defined in terms of IRQs, not PIRQs; use the correct number when checking permission in unmap_domain_pirq. Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> --- xen/arch/x86/physdev.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/xen/arch/x86/physdev.c b/xen/arch/x86/physdev.c index a3ceb7d..05fff9e 100644 --- a/xen/arch/x86/physdev.c +++ b/xen/arch/x86/physdev.c @@ -239,7 +239,7 @@ int physdev_unmap_pirq(domid_t domid, int pirq) if ( !IS_PRIV_FOR(current->domain, d) ) goto free_domain; - ret = xsm_irq_permission(d, pirq, 0); + ret = xsm_irq_permission(d, domain_pirq_to_irq(d, pirq), 0); if ( ret ) goto free_domain; -- 1.7.7.6
Daniel De Graaf
2012-Jan-31 21:26 UTC
[PATCH 06/10] xsm/flask: Improve error reporting for ocontexts
Instead of returning -EINVAL for all errors, return -EEXIST if adding an entry that overlaps with an existing entry, and -ENOENT if attempting to remove an entry that does not exist. Adding an ocontext that already exists with the same SID is no longer an error. Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> --- xen/xsm/flask/ss/services.c | 29 +++++++++++++++++++++-------- 1 files changed, 21 insertions(+), 8 deletions(-) diff --git a/xen/xsm/flask/ss/services.c b/xen/xsm/flask/ss/services.c index 7b08e73..3b0acf5 100644 --- a/xen/xsm/flask/ss/services.c +++ b/xen/xsm/flask/ss/services.c @@ -2084,8 +2084,10 @@ int security_ocontext_add( char *ocontext, unsigned long low, unsigned long high { if ( c->u.pirq == add->u.pirq ) { + if ( c->sid[0] == sid ) + break; printk("%s: Duplicate pirq %d\n", __FUNCTION__, add->u.pirq); - ret = -EINVAL; + ret = -EEXIST; break; } c = c->next; @@ -2112,10 +2114,14 @@ int security_ocontext_add( char *ocontext, unsigned long low, unsigned long high if (c && c->u.ioport.low_ioport <= high) { + if (c->u.ioport.low_ioport == low && + c->u.ioport.high_ioport == high && c->sid[0] == sid) + break; + printk("%s: IO Port overlap with entry 0x%x - 0x%x\n", __FUNCTION__, c->u.ioport.low_ioport, c->u.ioport.high_ioport); - ret = -EINVAL; + ret = -EEXIST; break; } @@ -2142,10 +2148,14 @@ int security_ocontext_add( char *ocontext, unsigned long low, unsigned long high if (c && c->u.iomem.low_iomem <= high) { + if (c->u.iomem.low_iomem == low && + c->u.iomem.high_iomem == high && c->sid[0] == sid) + break; + printk("%s: IO Memory overlap with entry 0x%x - 0x%x\n", __FUNCTION__, c->u.iomem.low_iomem, c->u.iomem.high_iomem); - ret = -EINVAL; + ret = -EEXIST; break; } @@ -2171,9 +2181,12 @@ int security_ocontext_add( char *ocontext, unsigned long low, unsigned long high { if ( c->u.device == add->u.device ) { + if ( c->sid[0] == sid ) + break; + printk("%s: Duplicate PCI Device 0x%x\n", __FUNCTION__, add->u.device); - ret = -EINVAL; + ret = -EEXIST; break; } c = c->next; @@ -2230,7 +2243,7 @@ int security_ocontext_del( char *ocontext, unsigned int low, unsigned int high ) } printk("%s: ocontext not found: pirq %d\n", __FUNCTION__, low); - ret = -EINVAL; + ret = -ENOENT; break; case OCON_IOPORT: @@ -2257,7 +2270,7 @@ int security_ocontext_del( char *ocontext, unsigned int low, unsigned int high ) printk("%s: ocontext not found: ioport 0x%x - 0x%x\n", __FUNCTION__, low, high); - ret = -EINVAL; + ret = -ENOENT; break; case OCON_IOMEM: @@ -2284,7 +2297,7 @@ int security_ocontext_del( char *ocontext, unsigned int low, unsigned int high ) printk("%s: ocontext not found: iomem 0x%x - 0x%x\n", __FUNCTION__, low, high); - ret = -EINVAL; + ret = -ENOENT; break; case OCON_DEVICE: @@ -2309,7 +2322,7 @@ int security_ocontext_del( char *ocontext, unsigned int low, unsigned int high ) } printk("%s: ocontext not found: pcidevice 0x%x\n", __FUNCTION__, low); - ret = -EINVAL; + ret = -ENOENT; break; default: -- 1.7.7.6
Daniel De Graaf
2012-Jan-31 21:26 UTC
[PATCH 07/10] xsm/flask: Remove useless back pointers
Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> --- xen/xsm/flask/hooks.c | 3 --- xen/xsm/flask/include/objsec.h | 2 -- 2 files changed, 0 insertions(+), 5 deletions(-) diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c index a095915..ad1013f 100644 --- a/xen/xsm/flask/hooks.c +++ b/xen/xsm/flask/hooks.c @@ -104,8 +104,6 @@ static int flask_domain_alloc_security(struct domain *d) memset(dsec, 0, sizeof(struct domain_security_struct)); - dsec->d = d; - if ( is_idle_domain(d) ) { dsec->sid = SECINITSID_XEN; @@ -281,7 +279,6 @@ static int flask_alloc_security_evtchn(struct evtchn *chn) memset(esec, 0, sizeof(struct evtchn_security_struct)); - esec->chn = chn; esec->sid = SECINITSID_UNLABELED; chn->ssid = esec; diff --git a/xen/xsm/flask/include/objsec.h b/xen/xsm/flask/include/objsec.h index 12f709a..df5baee 100644 --- a/xen/xsm/flask/include/objsec.h +++ b/xen/xsm/flask/include/objsec.h @@ -18,13 +18,11 @@ #include "avc.h" struct domain_security_struct { - struct domain *d; /* back pointer to domain object */ u32 sid; /* current SID */ u32 create_sid; }; struct evtchn_security_struct { - struct evtchn *chn; /* back pointer to evtchn object */ u32 sid; /* current SID */ }; -- 1.7.7.6
Eliminate temporary files used in creating FLASK policy to improve error reporting during policy build. Syntax errors now point to the file and line number visible to the user, not the intermediate temporary file. Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> --- tools/flask/policy/Makefile | 61 +++---------------------- tools/flask/policy/policy/initial_sids | 12 +++++ tools/flask/policy/policy/modules/xen/xen.te | 10 ---- 3 files changed, 20 insertions(+), 63 deletions(-) create mode 100644 tools/flask/policy/policy/initial_sids diff --git a/tools/flask/policy/Makefile b/tools/flask/policy/Makefile index a27c813..5c25cbe 100644 --- a/tools/flask/policy/Makefile +++ b/tools/flask/policy/Makefile @@ -102,9 +102,8 @@ else POLVER +=$(NAME).$(PV) endif - -# determine the policy version and current kernel version if possible -M4PARAM += -D mls_num_sens=$(MLS_SENS) -D mls_num_cats=$(MLS_CATS) -D hide_broken_symptoms +# Always define these because they are referenced even in non-MLS policy +M4PARAM += -D mls_num_sens=$(MLS_SENS) -D mls_num_cats=$(MLS_CATS) M4SUPPORT = $(wildcard $(POLDIR)/support/*.spt) @@ -126,9 +125,9 @@ ALL_INTERFACES := $(ALL_MODULES:.te=.if) ALL_TE_FILES := $(ALL_MODULES) PRE_TE_FILES := $(SECCLASS) $(ISIDS) $(AVS) $(M4SUPPORT) $(POLDIR)/mls -POST_TE_FILES := $(POLDIR)/users $(POLDIR)/constraints +POST_TE_FILES := $(POLDIR)/users $(POLDIR)/constraints $(POLDIR)/initial_sids -POLICY_SECTIONS := tmp/pre_te_files.conf tmp/all_interfaces.conf tmp/all_attrs_types.conf $(GLOBALBOOL) $(GLOBALTUN) tmp/only_te_rules.conf tmp/all_post.conf +POLICY_SECTIONS := $(PRE_TE_FILES) $(ALL_INTERFACES) $(GLOBALBOOL) $(GLOBALTUN) $(ALL_TE_FILES) $(POST_TE_FILES) ######################################## # @@ -140,7 +139,7 @@ policy: $(POLVER) install: $(LOADPATH) -load: tmp/load +load: .load_stamp ######################################## # @@ -166,11 +165,11 @@ $(LOADPATH): policy.conf # # Load the binary policy # -tmp/load: reload -reload: $(LOADPATH) $(FCPATH) +.load_stamp: reload +reload: $(LOADPATH) @echo "Loading $(NAME) $(LOADPATH)" $(QUIET) $(LOADPOLICY) $(LOADPATH) - @touch tmp/load + @touch .load_stamp ######################################## # @@ -181,50 +180,6 @@ policy.conf: $(POLICY_SECTIONS) # checkpolicy can use the #line directives provided by -s for error reporting: $(QUIET) m4 -D self_contained_policy $(M4PARAM) -s $^ > $@ -tmp/pre_te_files.conf: $(PRE_TE_FILES) - @test -d tmp || mkdir -p tmp - $(QUIET) cat $^ > $@ - -tmp/all_interfaces.conf: $(M4SUPPORT) $(ALL_INTERFACES) -ifeq ($(ALL_INTERFACES),) - $(error No enabled modules! $(notdir $(MOD_CONF)) please create a modules.conf file) -endif - @test -d tmp || mkdir -p tmp - $(QUIET) cat $^ | sed -e s/dollarsstar/\$$\*/g > $@ - -tmp/all_te_files.conf: $(ALL_TE_FILES) -ifeq ($(ALL_TE_FILES),) - $(error No enabled modules! $(notdir $(MOD_CONF)) please create a modules.conf file) -endif - @test -d tmp || mkdir -p tmp - $(QUIET) cat $^ > $@ - -tmp/post_te_files.conf: $(POST_TE_FILES) - @test -d tmp || mkdir -p tmp - $(QUIET) cat $^ > $@ - -# extract attributes and put them first. extract post te stuff -# like genfscon and put last. portcon, nodecon, and netifcon -# is delayed since they are generated by m4 -tmp/all_attrs_types.conf tmp/all_post.conf: tmp/only_te_rules.conf -tmp/only_te_rules.conf: tmp/all_te_files.conf tmp/post_te_files.conf - $(QUIET) grep ^attribute tmp/all_te_files.conf > tmp/all_attrs_types.conf || true - $(QUIET) grep ''^type '' tmp/all_te_files.conf >> tmp/all_attrs_types.conf - $(QUIET) cat tmp/post_te_files.conf > tmp/all_post.conf - $(QUIET) grep ''^sid '' tmp/all_te_files.conf >> tmp/all_post.conf || true - $(QUIET) grep ^pirqcon tmp/all_te_files.conf >> \ - tmp/all_post.conf || true - $(QUIET) grep ^ioportcon tmp/all_te_files.conf >> \ - tmp/all_post.conf || true - $(QUIET) grep ^iomemcon tmp/all_te_files.conf >> \ - tmp/all_post.conf || true - $(QUIET) grep ^pcidevicecon tmp/all_te_files.conf >> \ - tmp/all_post.conf || true - $(QUIET) sed -r -e /^attribute/d -e ''/^type /d'' -e ''/^sid /d'' \ - -e "/^pirqcon/d" -e "/^pcidevicecon/d" -e "/^ioportcon/d" \ - -e "/^iomemcon/d" < tmp/all_te_files.conf \ - > tmp/only_te_rules.conf - ######################################## # # Remove the dontaudit rules from the policy.conf diff --git a/tools/flask/policy/policy/initial_sids b/tools/flask/policy/policy/initial_sids new file mode 100644 index 0000000..b70a54e --- /dev/null +++ b/tools/flask/policy/policy/initial_sids @@ -0,0 +1,12 @@ +# Labels for initial SIDs + +sid xen gen_context(system_u:system_r:xen_t,s0) +sid dom0 gen_context(system_u:system_r:dom0_t,s0) +sid domxen gen_context(system_u:system_r:domxen_t,s0) +sid domio gen_context(system_u:system_r:domio_t,s0) +sid unlabeled gen_context(system_u:system_r:unlabeled_t,s0) +sid security gen_context(system_u:system_r:security_t,s0) +sid irq gen_context(system_u:object_r:irq_t,s0) +sid iomem gen_context(system_u:object_r:iomem_t,s0) +sid ioport gen_context(system_u:object_r:ioport_t,s0) +sid device gen_context(system_u:object_r:device_t,s0) diff --git a/tools/flask/policy/policy/modules/xen/xen.te b/tools/flask/policy/policy/modules/xen/xen.te index c5e0883..ac52c3f 100644 --- a/tools/flask/policy/policy/modules/xen/xen.te +++ b/tools/flask/policy/policy/modules/xen/xen.te @@ -162,16 +162,6 @@ neverallow * ~event_type:event { create send status }; # Labels for initial SIDs and system role # ################################################################################ -sid xen gen_context(system_u:system_r:xen_t,s0) -sid dom0 gen_context(system_u:system_r:dom0_t,s0) -sid domxen gen_context(system_u:system_r:domxen_t,s0) -sid domio gen_context(system_u:system_r:domio_t,s0) -sid unlabeled gen_context(system_u:system_r:unlabeled_t,s0) -sid security gen_context(system_u:system_r:security_t,s0) -sid irq gen_context(system_u:object_r:irq_t,s0) -sid iomem gen_context(system_u:object_r:iomem_t,s0) -sid ioport gen_context(system_u:object_r:ioport_t,s0) -sid device gen_context(system_u:object_r:device_t,s0) role system_r; role system_r types { xen_type domain_type }; -- 1.7.7.6
Daniel De Graaf
2012-Jan-31 21:26 UTC
[PATCH 09/10] flask/policy: Add user and constraint examples
These examples show how to use constraints and the user field of the security label to prevent communication between virtual machines of different customers in a multi-tenant environment. Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> --- docs/misc/xsm-flask.txt | 42 +++++++++++++++++++------ tools/flask/policy/policy/constraints | 15 ++++++++- tools/flask/policy/policy/modules/xen/xen.te | 28 +++++++++++++---- tools/flask/policy/policy/users | 14 ++------ 4 files changed, 71 insertions(+), 28 deletions(-) diff --git a/docs/misc/xsm-flask.txt b/docs/misc/xsm-flask.txt index 2eb75d6..285bb9f 100644 --- a/docs/misc/xsm-flask.txt +++ b/docs/misc/xsm-flask.txt @@ -27,14 +27,17 @@ FLASK_ENABLE to "y"; this change requires a make clean and rebuild. FLASK uses only one domain configuration parameter (seclabel) defining the full security label of the newly created domain. If using the example policy, -"seclabel=''system_u:system_r:domU_t''" would be used for normal domains. For -simple policies including the example policy, the user and role portions of the -label are unused and will always be "system_u:system_r". Most of FLASK policy -consists of defining the interactions allowed between different types (domU_t -would be the type in this example); FLASK policy does not distinguish between -domains with the same type. This is the same format as used for SELinux -labeling; see http://selinuxproject.org for more details on the use of the user, -role, and optional MLS/MCS labels. +"seclabel=''system_u:system_r:domU_t''" is an example of a normal domain. The +labels are in the same format as SELinux labels; see http://selinuxproject.org +for more details on the use of the user, role, and optional MLS/MCS labels. + +FLASK policy overview +--------------------- + +Most of FLASK policy consists of defining the interactions allowed between +different types (domU_t would be the type in this example). For simple policies, +only type enforcement is used and the user and role are set to system_u and +system_r for all domains. The FLASK security framework is mostly configured using a security policy file. This policy file is not normally generated during the Xen build process because @@ -57,8 +60,27 @@ that can be used without dom0 disaggregation. It has two main types for domUs: - domU_t is a domain that can communicate with any other domU_t - isolated_domU_t can only communicate with dom0 -More types can be added to allow groups of domains to communicate without -allowing communication between groups, or only between certain groups. +One disadvantage of using type enforcement to enforce isolation is that a new +type is needed for each group of domains. In addition, it is not possible to +allow isolated_domU_t cannot to create loopback event channels without allowing +two domains of type isolated_domU_t to communicate with one another. + +Users and roles +--------------- + +Users are defined in tools/flask/policy/policy/users. The example policy defines +two users (customer_1 and customer_2) in addition to the system user system_u. +Users are visible in the labels of domains and associated objects (event +channels); in the example policy, "customer_1:vm_r:domU_t" is a valid label for +the customer_1 user. + +Access control rules involving users and roles are defined in the policy +constraints file (tools/flask/policy/policy/constraints). The example policy +provides constraints that prevent different users from communicating using +grants or event channels, while still allowing communication with dom0. + +Resource Policy +--------------- The example policy also includes a resource type (nic_dev_t) for device passthrough, configured to allow use by domU_t. To label the PCI device 3:2.0 diff --git a/tools/flask/policy/policy/constraints b/tools/flask/policy/policy/constraints index beb949c..765ed4d 100644 --- a/tools/flask/policy/policy/constraints +++ b/tools/flask/policy/policy/constraints @@ -22,6 +22,19 @@ # role_op : == | != | eq | dom | domby | incomp # # names : name | { name_list } -# name_list : name | name_list name +# name_list : name | name_list name # +# Prevent event channels and grants between different customers + +constrain event bind ( + u1 == system_u or + u2 == system_u or + u1 == u2 +); + +constrain grant { map_read map_write copy } ( + u1 == system_u or + u2 == system_u or + u1 == u2 +); diff --git a/tools/flask/policy/policy/modules/xen/xen.te b/tools/flask/policy/policy/modules/xen/xen.te index ac52c3f..67dd0df 100644 --- a/tools/flask/policy/policy/modules/xen/xen.te +++ b/tools/flask/policy/policy/modules/xen/xen.te @@ -22,22 +22,22 @@ attribute mls_priv; ################################################################################ # The hypervisor itself -type xen_t, xen_type, domain_type, mls_priv; +type xen_t, xen_type, mls_priv; # Domain 0 type dom0_t, domain_type, mls_priv; # Untracked I/O memory (pseudo-domain) -type domio_t, domain_type; +type domio_t, xen_type; # Xen heap (pseudo-domain) -type domxen_t, domain_type; +type domxen_t, xen_type; # Unlabeled objects -type unlabeled_t, domain_type; +type unlabeled_t, xen_type; # The XSM/FLASK security server -type security_t, domain_type; +type security_t, xen_type; # Unlabeled device resources # Note: don''t allow access to these types directly; see below for how to label @@ -143,7 +143,11 @@ delegate_devices(dom0_t, domU_t) ################################################################################ # -# Constraints +# Policy constraints +# +# Neverallow rules will cause the policy build to fail if an allow rule exists +# that violates the expression. This is used to ensure proper labeling of +# objects. # ################################################################################ @@ -159,9 +163,19 @@ neverallow * ~event_type:event { create send status }; ################################################################################ # -# Labels for initial SIDs and system role +# Roles # ################################################################################ +# The object role (object_r) is used for devices, resources, and event channels; +# it does not need to be defined here and should not be used for domains. + +# The system role is used for utility domains and pseudo-domains role system_r; role system_r types { xen_type domain_type }; +# If you want to prevent domUs from being placed in system_r: +##role system_r types { xen_type dom0_t }; + +# The vm role is used for customer virtual machines +role vm_r; +role vm_r types { domain_type -dom0_t }; diff --git a/tools/flask/policy/policy/users b/tools/flask/policy/policy/users index a0205e5..35ed8a9 100644 --- a/tools/flask/policy/policy/users +++ b/tools/flask/policy/policy/users @@ -3,15 +3,9 @@ # System User configuration. # -# -# gen_user(username, role_set, mls_defaultlevel, mls_range) -# - -# -# system_u is the user identity for system processes and objects. -# There should be no corresponding Unix user identity for system, -# and a user process should never be assigned the system user -# identity. -# +# system_u is the user identity for system domains and objects gen_user(system_u,, system_r, s0, s0 - mls_systemhigh) +# Other users are defined using the vm role +gen_user(customer_1,, vm_r, s0, s0) +gen_user(customer_2,, vm_r, s0, s0) -- 1.7.7.6
Daniel De Graaf
2012-Jan-31 21:26 UTC
[PATCH 10/10] flask/policy: use declare_domain for dom0_t
Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> --- tools/flask/policy/policy/modules/xen/xen.if | 4 ++-- tools/flask/policy/policy/modules/xen/xen.te | 4 +--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/tools/flask/policy/policy/modules/xen/xen.if b/tools/flask/policy/policy/modules/xen/xen.if index 3065718..dde7f90 100644 --- a/tools/flask/policy/policy/modules/xen/xen.if +++ b/tools/flask/policy/policy/modules/xen/xen.if @@ -5,10 +5,10 @@ # Domain creation and setup # ################################################################################ -# declare_domain(type) +# declare_domain(type, attrs...) # Declare a type as a domain type, and allow basic domain setup define(`declare_domain'', ` - type $1, domain_type; + type $1, domain_type`''ifelse(`$#'', `1'', `'', `,shift($@)''); allow $1 $1:grant { query setup }; allow $1 $1:mmu { adjust physmap map_read map_write stat pinpage }; allow $1 $1:hvm { getparam setparam }; diff --git a/tools/flask/policy/policy/modules/xen/xen.te b/tools/flask/policy/policy/modules/xen/xen.te index 67dd0df..fb71b75 100644 --- a/tools/flask/policy/policy/modules/xen/xen.te +++ b/tools/flask/policy/policy/modules/xen/xen.te @@ -25,7 +25,7 @@ attribute mls_priv; type xen_t, xen_type, mls_priv; # Domain 0 -type dom0_t, domain_type, mls_priv; +declare_domain(dom0_t, mls_priv); # Untracked I/O memory (pseudo-domain) type domio_t, xen_type; @@ -63,8 +63,6 @@ allow dom0_t security_t:security { check_context compute_av compute_create setbool setsecparam add_ocontext del_ocontext }; allow dom0_t dom0_t:domain { getdomaininfo getvcpuinfo getvcpuaffinity }; -allow dom0_t dom0_t:grant { query setup }; -allow dom0_t dom0_t:mmu { adjust physmap map_read map_write stat pinpage }; allow dom0_t dom0_t:resource { add remove }; admin_device(dom0_t, device_t) -- 1.7.7.6
Daniel De Graaf
2012-Feb-01 19:09 UTC
[PATCH 0/8] XSM/FLASK updates part 2: booleans, stubdoms
This is a continuation of the previous 10-patch series updating the FLASK XSM security module and supporting libraries/tools. Bugfix: [PATCH 1/8] xen/xsm: fix incorrect handling of XSM hook return FLASK boolean addressing by name with tools: [PATCH 2/8] xsm/flask: allow policy booleans to be addressed by name [PATCH 3/8] libflask: Add boolean manipulation functions [PATCH 4/8] flask: add flask-{get,set}-bool tools [PATCH 5/8] flask/policy: Add boolean example Device model stub domain support: [PATCH 6/8] libxl: Add device_model_stubdomain_seclabel [PATCH 7/8] flask/policy: add device model types to example policy Cleanup: [PATCH 8/8] xsm/flask: Improve domain ID auditing in AVCs
Daniel De Graaf
2012-Feb-01 19:09 UTC
[PATCH 1/8] xen/xsm: fix incorrect handling of XSM hook return
If the XSM hook denied access, the execution incorrectly continued on after an extra unlock domain. Reported-by: John McDermott <john.mcdermott@nrl.navy.mil> Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> Cc: Keir Fraser <keir@xen.org> --- xen/arch/x86/domctl.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c index 9c9d5d1..831cdda 100644 --- a/xen/arch/x86/domctl.c +++ b/xen/arch/x86/domctl.c @@ -648,7 +648,7 @@ long arch_do_domctl( ret = xsm_machine_address_size(d, domctl->cmd); if ( ret ) - rcu_unlock_domain(d); + goto set_machine_address_size_out; ret = -EBUSY; if ( d->tot_pages > 0 ) -- 1.7.7.6
Daniel De Graaf
2012-Feb-01 19:09 UTC
[PATCH 2/8] xsm/flask: allow policy booleans to be addressed by name
Booleans are currently only addressable by using a sequence number that is not easily accessible to tools. Add new FLASK operations to get/set booleans by name, and to get the name of a boolean given its ID. Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> --- xen/include/public/xsm/flask_op.h | 5 +- xen/xsm/flask/flask_op.c | 159 ++++++++++++++++++++++++++++++----- xen/xsm/flask/include/conditional.h | 5 +- xen/xsm/flask/ss/services.c | 75 +++++++++++++---- 4 files changed, 207 insertions(+), 37 deletions(-) diff --git a/xen/include/public/xsm/flask_op.h b/xen/include/public/xsm/flask_op.h index e2dd403..416ac08 100644 --- a/xen/include/public/xsm/flask_op.h +++ b/xen/include/public/xsm/flask_op.h @@ -47,8 +47,11 @@ #define FLASK_MEMBER 20 #define FLASK_ADD_OCONTEXT 21 #define FLASK_DEL_OCONTEXT 22 +#define FLASK_GETBOOL_NAMED 23 +#define FLASK_GETBOOL2 24 +#define FLASK_SETBOOL_NAMED 25 -#define FLASK_LAST FLASK_DEL_OCONTEXT +#define FLASK_LAST FLASK_SETBOOL_NAMED typedef struct flask_op { uint32_t cmd; diff --git a/xen/xsm/flask/flask_op.c b/xen/xsm/flask/flask_op.c index 265a3cf..64d9ec5 100644 --- a/xen/xsm/flask/flask_op.c +++ b/xen/xsm/flask/flask_op.c @@ -47,7 +47,10 @@ integer_param("flask_enabled", flask_enabled); 1UL<<FLASK_SETAVC_THRESHOLD | \ 1UL<<FLASK_MEMBER | \ 1UL<<FLASK_ADD_OCONTEXT | \ - 1UL<<FLASK_DEL_OCONTEXT \ + 1UL<<FLASK_DEL_OCONTEXT | \ + 1UL<<FLASK_GETBOOL_NAMED | \ + 1UL<<FLASK_GETBOOL2 | \ + 1UL<<FLASK_SETBOOL_NAMED \ ) #define FLASK_COPY_OUT \ @@ -65,7 +68,9 @@ integer_param("flask_enabled", flask_enabled); 1UL<<FLASK_GETAVC_THRESHOLD | \ 1UL<<FLASK_AVC_HASHSTATS | \ 1UL<<FLASK_AVC_CACHESTATS | \ - 1UL<<FLASK_MEMBER \ + 1UL<<FLASK_MEMBER | \ + 1UL<<FLASK_GETBOOL_NAMED | \ + 1UL<<FLASK_GETBOOL2 \ ) static DEFINE_SPINLOCK(sel_sem); @@ -73,6 +78,7 @@ static DEFINE_SPINLOCK(sel_sem); /* global data for booleans */ static int bool_num = 0; static int *bool_pending_values = NULL; +static int flask_security_make_bools(void); extern int ss_initialized; @@ -573,7 +579,7 @@ static int flask_security_setavc_threshold(char *buf, uint32_t count) static int flask_security_set_bool(char *buf, uint32_t count) { int length = -EFAULT; - int i, new_value; + unsigned int i, new_value; spin_lock(&sel_sem); @@ -585,10 +591,14 @@ static int flask_security_set_bool(char *buf, uint32_t count) if ( sscanf(buf, "%d %d", &i, &new_value) != 2 ) goto out; + if (!bool_pending_values) + flask_security_make_bools(); + + if ( i >= bool_num ) + goto out; + if ( new_value ) - { new_value = 1; - } bool_pending_values[i] = new_value; length = count; @@ -598,6 +608,57 @@ static int flask_security_set_bool(char *buf, uint32_t count) return length; } +static int flask_security_set_bool_name(char *buf, uint32_t count) +{ + int rv, num; + int i, new_value, commit; + int *values = NULL; + char *name; + + name = xmalloc_bytes(count); + if ( name == NULL ) + return -ENOMEM; + + spin_lock(&sel_sem); + + rv = domain_has_security(current->domain, SECURITY__SETBOOL); + if ( rv ) + goto out; + + rv = -EINVAL; + if ( sscanf(buf, "%s %d %d", name, &new_value, &commit) != 3 ) + goto out; + + i = security_find_bool(name); + if ( i < 0 ) + goto out; + + if ( new_value ) + new_value = 1; + + if ( commit ) { + rv = security_get_bools(&num, NULL, &values); + if ( rv != 0 ) + goto out; + values[i] = new_value; + if (bool_pending_values) + bool_pending_values[i] = new_value; + rv = security_set_bools(num, values); + xfree(values); + } else { + if (!bool_pending_values) + flask_security_make_bools(); + + bool_pending_values[i] = new_value; + rv = count; + } + + out: + xfree(name); + spin_unlock(&sel_sem); + return rv; +} + static int flask_security_commit_bools(char *buf, uint32_t count) { int length = -EFAULT; @@ -613,7 +674,7 @@ static int flask_security_commit_bools(char *buf, uint32_t count) if ( sscanf(buf, "%d", &new_value) != 1 ) goto out; - if ( new_value ) + if ( new_value && bool_pending_values ) security_set_bools(bool_num, bool_pending_values); length = count; @@ -623,10 +684,11 @@ static int flask_security_commit_bools(char *buf, uint32_t count) return length; } -static int flask_security_get_bool(char *buf, uint32_t count) +static int flask_security_get_bool(char *buf, uint32_t count, int named) { int length; - int i, cur_enforcing; + int i, cur_enforcing, pend_enforcing; + char* name = NULL; spin_lock(&sel_sem); @@ -641,25 +703,70 @@ static int flask_security_get_bool(char *buf, uint32_t count) goto out; } + if ( bool_pending_values ) + pend_enforcing = bool_pending_values[i]; + else + pend_enforcing = cur_enforcing; + + if ( named ) + name = security_get_bool_name(i); + if ( named && !name ) + goto out; + memset(buf, 0, count); - length = snprintf(buf, count, "%d %d", cur_enforcing, - bool_pending_values[i]); + if ( named ) + length = snprintf(buf, count, "%d %d %s", cur_enforcing, + pend_enforcing, name); + else + length = snprintf(buf, count, "%d %d", cur_enforcing, + pend_enforcing); out: + xfree(name); spin_unlock(&sel_sem); return length; } +static int flask_security_get_bool_name(char *buf, uint32_t count) +{ + int rv = -ENOENT; + int i, cur_enforcing, pend_enforcing; + + spin_lock(&sel_sem); + + i = security_find_bool(buf); + if ( i < 0 ) + goto out; + + cur_enforcing = security_get_bool_value(i); + if ( cur_enforcing < 0 ) + { + rv = cur_enforcing; + goto out; + } + + if ( bool_pending_values ) + pend_enforcing = bool_pending_values[i]; + else + pend_enforcing = cur_enforcing; + + memset(buf, 0, count); + rv = snprintf(buf, count, "%d %d", cur_enforcing, pend_enforcing); + + out: + spin_unlock(&sel_sem); + return rv; +} + static int flask_security_make_bools(void) { - int i, ret = 0; - char **names = NULL; + int ret = 0; int num; int *values = NULL; xfree(bool_pending_values); - ret = security_get_bools(&num, &names, &values); + ret = security_get_bools(&num, NULL, &values); if ( ret != 0 ) goto out; @@ -667,12 +774,6 @@ static int flask_security_make_bools(void) bool_pending_values = values; out: - if ( names ) - { - for ( i = 0; i < num; i++ ) - xfree(names[i]); - xfree(names); - } return ret; } @@ -938,7 +1039,7 @@ long do_flask_op(XEN_GUEST_HANDLE(xsm_op_t) u_flask_op) case FLASK_GETBOOL: { - length = flask_security_get_bool(arg, op->size); + length = flask_security_get_bool(arg, op->size, 0); } break; @@ -1010,6 +1111,24 @@ long do_flask_op(XEN_GUEST_HANDLE(xsm_op_t) u_flask_op) break; } + case FLASK_GETBOOL_NAMED: + { + length = flask_security_get_bool_name(arg, op->size); + } + break; + + case FLASK_GETBOOL2: + { + length = flask_security_get_bool(arg, op->size, 1); + } + break; + + case FLASK_SETBOOL_NAMED: + { + length = flask_security_set_bool_name(arg, op->size); + } + break; + default: length = -ENOSYS; break; diff --git a/xen/xsm/flask/include/conditional.h b/xen/xsm/flask/include/conditional.h index bd3eb92..2fa0a30 100644 --- a/xen/xsm/flask/include/conditional.h +++ b/xen/xsm/flask/include/conditional.h @@ -17,6 +17,9 @@ int security_get_bools(int *len, char ***names, int **values); int security_set_bools(int len, int *values); -int security_get_bool_value(int bool); +int security_find_bool(const char *name); + +char *security_get_bool_name(unsigned int bool); +int security_get_bool_value(unsigned int bool); #endif diff --git a/xen/xsm/flask/ss/services.c b/xen/xsm/flask/ss/services.c index 3b0acf5..0189baf 100644 --- a/xen/xsm/flask/ss/services.c +++ b/xen/xsm/flask/ss/services.c @@ -1883,12 +1883,30 @@ out: return rc; } +int security_find_bool(const char *name) +{ + int i, rv = -ENOENT; + POLICY_RDLOCK; + for ( i = 0; i < policydb.p_bools.nprim; i++ ) + { + if (!strcmp(name, policydb.p_bool_val_to_name[i])) + { + rv = i; + break; + } + } + + POLICY_RDUNLOCK; + return rv; +} + int security_get_bools(int *len, char ***names, int **values) { int i, rc = -ENOMEM; POLICY_RDLOCK; - *names = NULL; + if ( names ) + *names = NULL; *values = NULL; *len = policydb.p_bools.nprim; @@ -1898,10 +1916,12 @@ int security_get_bools(int *len, char ***names, int **values) goto out; } - *names = (char**)xmalloc_array(char*, *len); - if ( !*names ) - goto err; - memset(*names, 0, sizeof(char*) * *len); + if ( names ) { + *names = (char**)xmalloc_array(char*, *len); + if ( !*names ) + goto err; + memset(*names, 0, sizeof(char*) * *len); + } *values = (int*)xmalloc_array(int, *len); if ( !*values ) @@ -1911,19 +1931,21 @@ int security_get_bools(int *len, char ***names, int **values) { size_t name_len; (*values)[i] = policydb.bool_val_to_struct[i]->state; - name_len = strlen(policydb.p_bool_val_to_name[i]) + 1; - (*names)[i] = (char*)xmalloc_array(char, name_len); - if ( !(*names)[i] ) - goto err; - strlcpy((*names)[i], policydb.p_bool_val_to_name[i], name_len); - (*names)[i][name_len - 1] = 0; + if ( names ) { + name_len = strlen(policydb.p_bool_val_to_name[i]) + 1; + (*names)[i] = (char*)xmalloc_array(char, name_len); + if ( !(*names)[i] ) + goto err; + strlcpy((*names)[i], policydb.p_bool_val_to_name[i], name_len); + (*names)[i][name_len - 1] = 0; + } } rc = 0; out: POLICY_RDUNLOCK; return rc; err: - if ( *names ) + if ( names && *names ) { for ( i = 0; i < *len; i++ ) xfree((*names)[i]); @@ -1984,17 +2006,17 @@ out: return rc; } -int security_get_bool_value(int bool) +int security_get_bool_value(unsigned int bool) { int rc = 0; - int len; + unsigned int len; POLICY_RDLOCK; len = policydb.p_bools.nprim; if ( bool >= len ) { - rc = -EFAULT; + rc = -ENOENT; goto out; } @@ -2004,6 +2026,29 @@ out: return rc; } +char *security_get_bool_name(unsigned int bool) +{ + unsigned int len; + char *rv = NULL; + + POLICY_RDLOCK; + + len = policydb.p_bools.nprim; + if ( bool >= len ) + { + goto out; + } + + len = strlen(policydb.p_bool_val_to_name[bool]) + 1; + rv = xmalloc_array(char, len); + if ( !rv ) + goto out; + memcpy(rv, policydb.p_bool_val_to_name[bool], len); +out: + POLICY_RDUNLOCK; + return rv; +} + static int security_preserve_bools(struct policydb *p) { int rc, nbools = 0, *bvalues = NULL, i; -- 1.7.7.6
Daniel De Graaf
2012-Feb-01 19:09 UTC
[PATCH 3/8] libflask: Add boolean manipulation functions
Add wrappers for getting and setting policy booleans by name or ID. Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> --- tools/flask/libflask/flask_op.c | 59 +++++++++++++++++++++++++++++++ tools/flask/libflask/include/libflask.h | 3 ++ 2 files changed, 62 insertions(+), 0 deletions(-) diff --git a/tools/flask/libflask/flask_op.c b/tools/flask/libflask/flask_op.c index d4b8ef0..412a05d 100644 --- a/tools/flask/libflask/flask_op.c +++ b/tools/flask/libflask/flask_op.c @@ -109,6 +109,65 @@ int flask_setenforce(xc_interface *xc_handle, int mode) return 0; } +int flask_getbool_byid(xc_interface *xc_handle, int id, char *name, int *curr, int *pend) +{ + flask_op_t op; + char buf[255]; + int rv; + + op.cmd = FLASK_GETBOOL2; + op.buf = buf; + op.size = 255; + + snprintf(buf, sizeof buf, "%i", id); + + rv = xc_flask_op(xc_handle, &op); + + if ( rv ) + return rv; + + sscanf(buf, "%i %i %s", curr, pend, name); + + return rv; +} + +int flask_getbool_byname(xc_interface *xc_handle, char *name, int *curr, int *pend) +{ + flask_op_t op; + char buf[255]; + int rv; + + op.cmd = FLASK_GETBOOL_NAMED; + op.buf = buf; + op.size = 255; + + strncpy(buf, name, op.size); + + rv = xc_flask_op(xc_handle, &op); + + if ( rv ) + return rv; + + sscanf(buf, "%i %i", curr, pend); + + return rv; +} + +int flask_setbool(xc_interface *xc_handle, char *name, int value, int commit) +{ + flask_op_t op; + char buf[255]; + int size = 255; + + op.cmd = FLASK_SETBOOL_NAMED; + op.buf = buf; + op.size = size; + + snprintf(buf, size, "%s %i %i", name, value, commit); + + return xc_flask_op(xc_handle, &op); +} + int flask_add_pirq(xc_interface *xc_handle, unsigned int pirq, char *scontext) { int err; diff --git a/tools/flask/libflask/include/libflask.h b/tools/flask/libflask/include/libflask.h index e4c34b8..b8a6ca9 100644 --- a/tools/flask/libflask/include/libflask.h +++ b/tools/flask/libflask/include/libflask.h @@ -21,6 +21,9 @@ int flask_context_to_sid(xc_interface *xc_handle, char *buf, uint32_t size, uint int flask_sid_to_context(xc_interface *xc_handle, int sid, char *buf, uint32_t size); int flask_getenforce(xc_interface *xc_handle); int flask_setenforce(xc_interface *xc_handle, int mode); +int flask_getbool_byid(xc_interface *xc_handle, int id, char *name, int *curr, int *pend); +int flask_getbool_byname(xc_interface *xc_handle, char *name, int *curr, int *pend); +int flask_setbool(xc_interface *xc_handle, char *name, int value, int commit); int flask_add_pirq(xc_interface *xc_handle, unsigned int pirq, char *scontext); int flask_add_ioport(xc_interface *xc_handle, unsigned long low, unsigned long high, char *scontext); -- 1.7.7.6
These utilities can be used to modify policy booleans, which allow minor policy changes without reloading the security policy. This can be used to make security policy change based on external information such as time of day, user physical presence, completion of system boot, or other relevant variables. Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> --- tools/flask/utils/Makefile | 8 +++- tools/flask/utils/get-bool.c | 90 ++++++++++++++++++++++++++++++++++++++++++ tools/flask/utils/set-bool.c | 72 +++++++++++++++++++++++++++++++++ 3 files changed, 169 insertions(+), 1 deletions(-) create mode 100644 tools/flask/utils/get-bool.c create mode 100644 tools/flask/utils/set-bool.c diff --git a/tools/flask/utils/Makefile b/tools/flask/utils/Makefile index 171a728..3ac6ac2 100644 --- a/tools/flask/utils/Makefile +++ b/tools/flask/utils/Makefile @@ -11,7 +11,7 @@ TESTDIR = testsuite/tmp TESTFLAGS= -DTESTING TESTENV = XENSTORED_ROOTDIR=$(TESTDIR) XENSTORED_RUNDIR=$(TESTDIR) -CLIENTS := flask-loadpolicy flask-setenforce flask-getenforce flask-label-pci +CLIENTS := flask-loadpolicy flask-setenforce flask-getenforce flask-label-pci flask-get-bool flask-set-bool CLIENTS_SRCS := $(patsubst flask-%,%.c,$(CLIENTS)) CLIENTS_OBJS := $(patsubst flask-%,%.o,$(CLIENTS)) @@ -30,6 +30,12 @@ flask-getenforce: getenforce.o flask-label-pci: label-pci.o $(CC) $(LDFLAGS) $< $(LDLIBS) -L$(LIBFLASK_ROOT) -lflask $(LDLIBS_libxenctrl) -o $@ +flask-get-bool: get-bool.o + $(CC) $(LDFLAGS) $< $(LDLIBS) -L$(LIBFLASK_ROOT) -lflask $(LDLIBS_libxenctrl) -o $@ + +flask-set-bool: set-bool.o + $(CC) $(LDFLAGS) $< $(LDLIBS) -L$(LIBFLASK_ROOT) -lflask $(LDLIBS_libxenctrl) -o $@ + .PHONY: clean clean: rm -f *.o *.opic *.so diff --git a/tools/flask/utils/get-bool.c b/tools/flask/utils/get-bool.c new file mode 100644 index 0000000..c0cd7c8 --- /dev/null +++ b/tools/flask/utils/get-bool.c @@ -0,0 +1,90 @@ +/* + * Author: Daniel De Graaf <dgdegra@tycho.nsa.gov> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + */ + +#include <stdlib.h> +#include <errno.h> +#include <stdio.h> +#include <xenctrl.h> +#include <fcntl.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <string.h> +#include <unistd.h> +#include <inttypes.h> +#include <libflask.h> + +static void usage(char **argv) +{ + fprintf(stderr, "Usage: %s {name|-a}\n", argv[0]); + exit(1); +} + +static int all_bools(xc_interface *xch) +{ + int err = 0, i = 0, curr, pend; + char name[256]; + while (1) { + err = flask_getbool_byid(xch, i, name, &curr, &pend); + if (err < 0) { + if (errno == ENOENT) + return 0; + fprintf(stderr, "flask_getbool: Unable to get boolean #%d: %s (%d)", + i, strerror(errno), err); + return 2; + } + if (curr == pend) + printf("%s: %d\n", name, curr); + else + printf("%s: %d (pending %d)\n", name, curr, pend); + i++; + } +} + +int main(int argc, char **argv) +{ + int err = 0; + xc_interface *xch; + int curr, pend; + + if (argc != 2) + usage(argv); + + xch = xc_interface_open(0,0,0); + if ( !xch ) + { + fprintf(stderr, "Unable to create interface to xenctrl: %s\n", + strerror(errno)); + err = 1; + goto done; + } + + if (!strcmp(argv[1], "-a")) + { + err = all_bools(xch); + goto done; + } + + err = flask_getbool_byname(xch, argv[1], &curr, &pend); + if (err) { + fprintf(stderr, "flask_getbool: Unable to get boolean %s: %s (%d)", + argv[1], strerror(errno), err); + err = 2; + goto done; + } + + if (curr == pend) + printf("%s: %d\n", argv[1], curr); + else + printf("%s: %d (pending %d)\n", argv[1], curr, pend); + + done: + if ( xch ) + xc_interface_close(xch); + + return err; +} diff --git a/tools/flask/utils/set-bool.c b/tools/flask/utils/set-bool.c new file mode 100644 index 0000000..cde25cd --- /dev/null +++ b/tools/flask/utils/set-bool.c @@ -0,0 +1,72 @@ +/* + * Author: Daniel De Graaf <dgdegra@tycho.nsa.gov> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + */ + +#include <stdlib.h> +#include <errno.h> +#include <stdio.h> +#include <xenctrl.h> +#include <fcntl.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <string.h> +#include <unistd.h> +#include <inttypes.h> +#include <libflask.h> + +static void usage(char **argv) +{ + fprintf(stderr, "Usage: %s name value\n", argv[0]); + exit(1); +} + +static int str2bool(const char *str) +{ + if (str[0] == ''0'' || str[0] == ''1'') + return (str[0] == ''1''); + if (!strcasecmp(str, "enabled") || !strcasecmp(str, "on") || !strcasecmp(str, "y")) + return 1; + if (!strcasecmp(str, "disabled") || !strcasecmp(str, "off") || !strcasecmp(str, "n")) + return 0; + fprintf(stderr, "Unknown value %s\n", str); + exit(1); +} + +int main(int argc, char **argv) +{ + int err = 0; + xc_interface *xch; + int value; + + if (argc != 3) + usage(argv); + + value = str2bool(argv[2]); + + xch = xc_interface_open(0,0,0); + if ( !xch ) + { + fprintf(stderr, "Unable to create interface to xenctrl: %s\n", + strerror(errno)); + err = 1; + goto done; + } + + err = flask_setbool(xch, argv[1], value, 1); + if (err) { + fprintf(stderr, "flask_setbool: Unable to set boolean %s=%s: %s (%d)", + argv[1], argv[2], strerror(errno), err); + err = 2; + goto done; + } + + done: + if ( xch ) + xc_interface_close(xch); + + return err; +} -- 1.7.7.6
This shows an example boolean (prot_doms_locked) which can be set at runtime to prevent dom0 from mapping memory of domains of type prot_domU_t. Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> --- docs/misc/xsm-flask.txt | 3 ++- tools/flask/policy/policy/modules/xen/xen.te | 10 +++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/docs/misc/xsm-flask.txt b/docs/misc/xsm-flask.txt index 285bb9f..5b4297d 100644 --- a/docs/misc/xsm-flask.txt +++ b/docs/misc/xsm-flask.txt @@ -55,10 +55,11 @@ kernel; it is normally placed either just above the dom0 kernel or at the end. Once dom0 is running, the policy can be reloaded using "xl loadpolicy". The example policy included with Xen demonstrates most of the features of FLASK -that can be used without dom0 disaggregation. It has two main types for domUs: +that can be used without dom0 disaggregation. The main types for domUs are: - domU_t is a domain that can communicate with any other domU_t - isolated_domU_t can only communicate with dom0 + - prot_domU_t is a domain type whose creation can be disabled with a boolean One disadvantage of using type enforcement to enforce isolation is that a new type is needed for each group of domains. In addition, it is not possible to diff --git a/tools/flask/policy/policy/modules/xen/xen.te b/tools/flask/policy/policy/modules/xen/xen.te index fb71b75..f7343a2 100644 --- a/tools/flask/policy/policy/modules/xen/xen.te +++ b/tools/flask/policy/policy/modules/xen/xen.te @@ -73,7 +73,7 @@ allow dom0_t domio_t:mmu { map_read map_write }; domain_self_comms(dom0_t) -auditallow dom0_t security_t:security { load_policy setenforce }; +auditallow dom0_t security_t:security { load_policy setenforce setbool }; ############################################################################### # @@ -92,6 +92,14 @@ create_domain(dom0_t, isolated_domU_t) manage_domain(dom0_t, isolated_domU_t) domain_comms(dom0_t, isolated_domU_t) +gen_bool(prot_doms_locked, false) +declare_domain(prot_domU_t) +if (!prot_doms_locked) { + create_domain(dom0_t, prot_domU_t) +} +domain_comms(dom0_t, prot_domU_t) +domain_comms(domU_t, prot_domU_t) + ############################################################################### # # Device delegation -- 1.7.7.6
Daniel De Graaf
2012-Feb-01 19:09 UTC
[PATCH 6/8] libxl: Add device_model_stubdomain_seclabel
This allows the security label of stub domains to be specified. Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> --- docs/man/xl.cfg.pod.5 | 4 ++++ tools/libxl/libxl_dm.c | 1 + tools/libxl/libxl_types.idl | 1 + tools/libxl/xl_cmdimpl.c | 12 ++++++++++++ 4 files changed, 18 insertions(+), 0 deletions(-) diff --git a/docs/man/xl.cfg.pod.5 b/docs/man/xl.cfg.pod.5 index 9d90290..8f171b4 100644 --- a/docs/man/xl.cfg.pod.5 +++ b/docs/man/xl.cfg.pod.5 @@ -789,6 +789,10 @@ Override the use of stubdomain based device-model. Normally this will be automatically selected based upon the other features and options you have selected. +=item B<device_model_stubdomain_seclabel="LABEL"> + +Assign an XSM security label to the device-model stubdomain. + =item B<device_model_args=[ "ARG", "ARG", ...]> Pass additional arbitrary options on the devide-model command diff --git a/tools/libxl/libxl_dm.c b/tools/libxl/libxl_dm.c index 5fec137..e99d173 100644 --- a/tools/libxl/libxl_dm.c +++ b/tools/libxl/libxl_dm.c @@ -703,6 +703,7 @@ static int libxl__create_stubdom(libxl__gc *gc, dm_config.c_info.type = LIBXL_DOMAIN_TYPE_PV; dm_config.c_info.name = libxl__sprintf(gc, "%s-dm", libxl__domid_to_name(gc, guest_domid)); + dm_config.c_info.ssidref = guest_config->b_info.device_model_ssidref; libxl_uuid_generate(&dm_config.c_info.uuid); diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl index 3c24626..b77bc65 100644 --- a/tools/libxl/libxl_types.idl +++ b/tools/libxl/libxl_types.idl @@ -217,6 +217,7 @@ libxl_domain_build_info = Struct("domain_build_info",[ ("device_model_stubdomain", bool), # you set device_model you must set device_model_version too ("device_model", string), + ("device_model_ssidref", uint32), # extra parameters pass directly to qemu, NULL terminated ("extra", libxl_string_list), diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c index 0b811b5..e95bace 100644 --- a/tools/libxl/xl_cmdimpl.c +++ b/tools/libxl/xl_cmdimpl.c @@ -1254,6 +1254,18 @@ skip_vfb: if (!xlu_cfg_get_long (config, "device_model_stubdomain_override", &l, 0)) b_info->device_model_stubdomain = l; + if (!xlu_cfg_get_string (config, "device_model_stubdomain_seclabel", &buf, 0)) { + e = libxl_flask_context_to_sid(ctx, (char *)buf, strlen(buf), + &b_info->device_model_ssidref); + if (e) { + if (errno == ENOSYS) { + fprintf(stderr, "XSM Disabled: device_model_stubdomain_seclabel not supported\n"); + } else { + fprintf(stderr, "Invalid device_model_stubdomain_seclabel: %s\n", buf); + exit(1); + } + } + } #define parse_extra_args(type) \ e = xlu_cfg_get_list_as_string_list(config, "device_model_args"#type, \ &b_info->extra##type, 0); \ -- 1.7.7.6
Daniel De Graaf
2012-Feb-01 19:09 UTC
[PATCH 7/8] flask/policy: add device model types to example policy
This adds an example user for device_model_stubdomain_seclabel. Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> --- docs/misc/xsm-flask.txt | 4 ++++ tools/flask/policy/policy/modules/xen/xen.if | 11 ++++++++++- tools/flask/policy/policy/modules/xen/xen.te | 13 +++++++++++++ 3 files changed, 27 insertions(+), 1 deletions(-) diff --git a/docs/misc/xsm-flask.txt b/docs/misc/xsm-flask.txt index 5b4297d..e2e415d 100644 --- a/docs/misc/xsm-flask.txt +++ b/docs/misc/xsm-flask.txt @@ -61,6 +61,10 @@ that can be used without dom0 disaggregation. The main types for domUs are: - isolated_domU_t can only communicate with dom0 - prot_domU_t is a domain type whose creation can be disabled with a boolean +HVM domains with stubdomain device models use two types (one per domain): + - domHVM_t is an HVM domain that uses a stubdomain device model + - dm_dom_t is the device model for a domain with type domHVM_t + One disadvantage of using type enforcement to enforce isolation is that a new type is needed for each group of domains. In addition, it is not possible to allow isolated_domU_t cannot to create loopback event channels without allowing diff --git a/tools/flask/policy/policy/modules/xen/xen.if b/tools/flask/policy/policy/modules/xen/xen.if index dde7f90..87ef165 100644 --- a/tools/flask/policy/policy/modules/xen/xen.if +++ b/tools/flask/policy/policy/modules/xen/xen.if @@ -25,7 +25,7 @@ define(`create_domain'', ` allow $1 $2:shadow enable; allow $1 $2:mmu {map_read map_write adjust memorymap physmap pinpage}; allow $1 $2:grant setup; - allow $1 $2:hvm { cacheattr getparam hvmctl irqlevel pciroute setparam }; + allow $1 $2:hvm { cacheattr getparam hvmctl irqlevel pciroute setparam pcilevel trackdirtyvram }; allow $1 $2_$1_channel:event create; '') @@ -36,6 +36,7 @@ define(`manage_domain'', ` getaddrsize pause unpause trigger shutdown destroy setvcpuaffinity setdomainmaxmem }; '') + ################################################################################ # # Inter-domain communication @@ -75,6 +76,14 @@ define(`domain_self_comms'', ` allow $1 $1:grant { map_read map_write copy unmap }; '') +# device_model(dm_dom, hvm_dom) +# Define how a device model domain interacts with its target +define(`device_model'', ` + domain_comms($1, $2) + allow $1 $2:domain { set_target shutdown }; + allow $1 $2:mmu { map_read map_write adjust physmap }; + allow $1 $2:hvm { getparam setparam trackdirtyvram hvmctl irqlevel pciroute }; +'') ################################################################################ # # Device types and delegation (PCI passthrough) diff --git a/tools/flask/policy/policy/modules/xen/xen.te b/tools/flask/policy/policy/modules/xen/xen.te index f7343a2..29885c4 100644 --- a/tools/flask/policy/policy/modules/xen/xen.te +++ b/tools/flask/policy/policy/modules/xen/xen.te @@ -100,6 +100,19 @@ if (!prot_doms_locked) { domain_comms(dom0_t, prot_domU_t) domain_comms(domU_t, prot_domU_t) +# domHVM_t is meant to be paired with a qemu-dm stub domain of type dm_dom_t +declare_domain(domHVM_t) +create_domain(dom0_t, domHVM_t) +manage_domain(dom0_t, domHVM_t) +domain_comms(dom0_t, domHVM_t) +domain_self_comms(domHVM_t) + +declare_domain(dm_dom_t) +create_domain(dom0_t, dm_dom_t) +manage_domain(dom0_t, dm_dom_t) +domain_comms(dom0_t, dm_dom_t) +device_model(dm_dom_t, domHVM_t) + ############################################################################### # # Device delegation -- 1.7.7.6
Daniel De Graaf
2012-Feb-01 19:09 UTC
[PATCH 8/8] xsm/flask: Improve domain ID auditing in AVCs
Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> --- xen/xsm/flask/avc.c | 17 ++++++++++++----- xen/xsm/flask/hooks.c | 18 ++++++++++++++++-- xen/xsm/flask/include/avc.h | 4 +++- 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/xen/xsm/flask/avc.c b/xen/xsm/flask/avc.c index 9475d92..3a60a3a 100644 --- a/xen/xsm/flask/avc.c +++ b/xen/xsm/flask/avc.c @@ -539,7 +539,7 @@ static struct avc_node *avc_insert(u32 ssid, u32 tsid, u16 tclass, void avc_audit(u32 ssid, u32 tsid, u16 tclass, u32 requested, struct av_decision *avd, int result, struct avc_audit_data *a) { - struct domain *d = current->domain; + struct domain *cdom = current->domain; u32 denied, audited; denied = requested & ~avd->allowed; @@ -564,10 +564,17 @@ void avc_audit(u32 ssid, u32 tsid, u16 tclass, u32 requested, avc_dump_av(tclass, audited); printk(" for "); - if ( a && a->d ) - d = a->d; - if ( d ) - printk("domid=%d ", d->domain_id); + if ( a && (a->sdom || a->tdom) ) + { + if ( a->sdom && a->tdom && a->sdom != a->tdom ) + printk("domid=%d target=%d ", a->sdom->domain_id, a->tdom->domain_id); + else if ( a->sdom ) + printk("domid=%d ", a->sdom->domain_id); + else + printk("target=%d ", a->tdom->domain_id); + } + else if ( cdom ) + printk("domid=%d ", cdom->domain_id); switch ( a ? a->type : 0 ) { case AVC_AUDIT_DATA_DEV: printk("device=0x%lx ", a->device); diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c index ad1013f..649c473 100644 --- a/xen/xsm/flask/hooks.c +++ b/xen/xsm/flask/hooks.c @@ -37,11 +37,15 @@ static int domain_has_perm(struct domain *dom1, struct domain *dom2, u16 class, u32 perms) { struct domain_security_struct *dsec1, *dsec2; + struct avc_audit_data ad; + AVC_AUDIT_DATA_INIT(&ad, NONE); + ad.sdom = dom1; + ad.tdom = dom2; dsec1 = dom1->ssid; dsec2 = dom2->ssid; - return avc_has_perm(dsec1->sid, dsec2->sid, class, perms, NULL); + return avc_has_perm(dsec1->sid, dsec2->sid, class, perms, &ad); } static int domain_has_evtchn(struct domain *d, struct evtchn *chn, u32 perms) @@ -1323,6 +1327,7 @@ static int flask_mmu_normal_update(struct domain *d, struct domain *t, unsigned long fmfn; struct domain_security_struct *dsec; u32 fsid; + struct avc_audit_data ad; if (d != t) rc = domain_has_perm(d, t, SECCLASS_MMU, MMU__REMOTE_REMAP); @@ -1337,13 +1342,22 @@ static int flask_mmu_normal_update(struct domain *d, struct domain *t, if ( l1e_get_flags(l1e_from_intpte(fpte)) & _PAGE_RW ) map_perms |= MMU__MAP_WRITE; + AVC_AUDIT_DATA_INIT(&ad, RANGE); fmfn = get_gfn_untyped(f, l1e_get_pfn(l1e_from_intpte(fpte))); + ad.sdom = d; + ad.tdom = f; + ad.range.start = fpte; + ad.range.end = fmfn; + rc = get_mfn_sid(fmfn, &fsid); + + put_gfn(f, fmfn); + if ( rc ) return rc; - return avc_has_perm(dsec->sid, fsid, SECCLASS_MMU, map_perms, NULL); + return avc_has_perm(dsec->sid, fsid, SECCLASS_MMU, map_perms, &ad); } static int flask_mmu_machphys_update(struct domain *d, unsigned long mfn) diff --git a/xen/xsm/flask/include/avc.h b/xen/xsm/flask/include/avc.h index 1b19189..8fffbb6 100644 --- a/xen/xsm/flask/include/avc.h +++ b/xen/xsm/flask/include/avc.h @@ -38,10 +38,12 @@ struct sk_buff; /* Auxiliary data to use in generating the audit record. */ struct avc_audit_data { char type; +#define AVC_AUDIT_DATA_NONE 0 #define AVC_AUDIT_DATA_DEV 1 #define AVC_AUDIT_DATA_IRQ 2 #define AVC_AUDIT_DATA_RANGE 3 - struct domain *d; + struct domain *sdom; + struct domain *tdom; union { unsigned long device; int irq; -- 1.7.7.6
Ian Campbell
2012-Feb-02 09:06 UTC
Re: [PATCH 3/8] libflask: Add boolean manipulation functions
On Wed, 2012-02-01 at 19:09 +0000, Daniel De Graaf wrote:> Add wrappers for getting and setting policy booleans by name or ID. > > Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> > --- > tools/flask/libflask/flask_op.c | 59 +++++++++++++++++++++++++++++++ > tools/flask/libflask/include/libflask.h | 3 ++ > 2 files changed, 62 insertions(+), 0 deletions(-) > > diff --git a/tools/flask/libflask/flask_op.c b/tools/flask/libflask/flask_op.c > index d4b8ef0..412a05d 100644 > --- a/tools/flask/libflask/flask_op.c > +++ b/tools/flask/libflask/flask_op.c > @@ -109,6 +109,65 @@ int flask_setenforce(xc_interface *xc_handle, int mode) > return 0; > } > > +int flask_getbool_byid(xc_interface *xc_handle, int id, char *name, int *curr, int *pend) > +{ > + flask_op_t op; > + char buf[255]; > + int rv; > + > + op.cmd = FLASK_GETBOOL2; > + op.buf = buf; > + op.size = 255;sizeof(buf)? Here and elsewhere (including a few existing locations in flask_op.c).> + > + snprintf(buf, sizeof buf, "%i", id); > + > + rv = xc_flask_op(xc_handle, &op); > + > + if ( rv ) > + return rv; > + > + sscanf(buf, "%i %i %s", curr, pend, name);Do you care about sscanf failures? It seems from other uses in the file that buf can contain binary data so would it make sense to make this two ints as binary followed by a string? That would remove string parsing here and in the hypervisor (which seems more critical to me?) Is there a defined maximum for the length of "name"? Ian.
Daniel De Graaf
2012-Feb-02 14:28 UTC
Re: [PATCH 3/8] libflask: Add boolean manipulation functions
On 02/02/2012 04:06 AM, Ian Campbell wrote:> On Wed, 2012-02-01 at 19:09 +0000, Daniel De Graaf wrote: >> Add wrappers for getting and setting policy booleans by name or ID. >> >> Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> >> --- >> tools/flask/libflask/flask_op.c | 59 +++++++++++++++++++++++++++++++ >> tools/flask/libflask/include/libflask.h | 3 ++ >> 2 files changed, 62 insertions(+), 0 deletions(-) >> >> diff --git a/tools/flask/libflask/flask_op.c b/tools/flask/libflask/flask_op.c >> index d4b8ef0..412a05d 100644 >> --- a/tools/flask/libflask/flask_op.c >> +++ b/tools/flask/libflask/flask_op.c >> @@ -109,6 +109,65 @@ int flask_setenforce(xc_interface *xc_handle, int mode) >> return 0; >> } >> >> +int flask_getbool_byid(xc_interface *xc_handle, int id, char *name, int *curr, int *pend) >> +{ >> + flask_op_t op; >> + char buf[255]; >> + int rv; >> + >> + op.cmd = FLASK_GETBOOL2; >> + op.buf = buf; >> + op.size = 255; > > sizeof(buf)? Here and elsewhere (including a few existing locations in > flask_op.c). > >> + >> + snprintf(buf, sizeof buf, "%i", id); >> + >> + rv = xc_flask_op(xc_handle, &op); >> + >> + if ( rv ) >> + return rv; >> + >> + sscanf(buf, "%i %i %s", curr, pend, name); > > Do you care about sscanf failures?A failure here would be a sign of the hypervisor having made a format change that is not backwards compatible. Checking it would be more complete, however.> It seems from other uses in the file that buf can contain binary data so > would it make sense to make this two ints as binary followed by a > string? That would remove string parsing here and in the hypervisor > (which seems more critical to me?)That also seems far simpler to me; however, all the current FLASK hypercalls are done via string parsing so deviating from this for new operations would make them inconsistent. If we didn''t have to care about backwards compatibility I would convert the entire flask_op hypercall to use a union-of-structures similar to domctl because the string parsing introduces unneeded complexity.> Is there a defined maximum for the length of "name"?INITCONTEXTLEN = 256.
Ian Campbell
2012-Feb-02 14:50 UTC
Re: [PATCH 3/8] libflask: Add boolean manipulation functions
On Thu, 2012-02-02 at 14:28 +0000, Daniel De Graaf wrote:> On 02/02/2012 04:06 AM, Ian Campbell wrote: > > On Wed, 2012-02-01 at 19:09 +0000, Daniel De Graaf wrote: > >> Add wrappers for getting and setting policy booleans by name or ID. > >> > >> Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> > >> --- > >> tools/flask/libflask/flask_op.c | 59 +++++++++++++++++++++++++++++++ > >> tools/flask/libflask/include/libflask.h | 3 ++ > >> 2 files changed, 62 insertions(+), 0 deletions(-) > >> > >> diff --git a/tools/flask/libflask/flask_op.c b/tools/flask/libflask/flask_op.c > >> index d4b8ef0..412a05d 100644 > >> --- a/tools/flask/libflask/flask_op.c > >> +++ b/tools/flask/libflask/flask_op.c > >> @@ -109,6 +109,65 @@ int flask_setenforce(xc_interface *xc_handle, int mode) > >> return 0; > >> } > >> > >> +int flask_getbool_byid(xc_interface *xc_handle, int id, char *name, int *curr, int *pend) > >> +{ > >> + flask_op_t op; > >> + char buf[255]; > >> + int rv; > >> + > >> + op.cmd = FLASK_GETBOOL2; > >> + op.buf = buf; > >> + op.size = 255; > > > > sizeof(buf)? Here and elsewhere (including a few existing locations in > > flask_op.c). > > > >> + > >> + snprintf(buf, sizeof buf, "%i", id); > >> + > >> + rv = xc_flask_op(xc_handle, &op); > >> + > >> + if ( rv ) > >> + return rv; > >> + > >> + sscanf(buf, "%i %i %s", curr, pend, name); > > > > Do you care about sscanf failures? > > A failure here would be a sign of the hypervisor having made a format change > that is not backwards compatible. Checking it would be more complete, however. > > > It seems from other uses in the file that buf can contain binary data so > > would it make sense to make this two ints as binary followed by a > > string? That would remove string parsing here and in the hypervisor > > (which seems more critical to me?) > > That also seems far simpler to me; however, all the current FLASK hypercalls > are done via string parsing so deviating from this for new operations would > make them inconsistent.OK. I thought I''d seen some binary muddling in their but I must have been mistaken.> If we didn''t have to care about backwards compatibility I would convert the > entire flask_op hypercall to use a union-of-structures similar to domctl > because the string parsing introduces unneeded complexity.How much do we care about backwards compat for this interface? Isn''t it a tools only dom0 interface?> > Is there a defined maximum for the length of "name"? > > INITCONTEXTLEN = 256.So the max size of the buffer is 256 + whatever two int and two spaces might maximally take, but your buffer is exactly 256.
Daniel De Graaf
2012-Feb-02 15:22 UTC
Re: [PATCH 3/8] libflask: Add boolean manipulation functions
On 02/02/2012 09:50 AM, Ian Campbell wrote:> On Thu, 2012-02-02 at 14:28 +0000, Daniel De Graaf wrote: >> On 02/02/2012 04:06 AM, Ian Campbell wrote: >>> On Wed, 2012-02-01 at 19:09 +0000, Daniel De Graaf wrote: >>>> Add wrappers for getting and setting policy booleans by name or ID. >>>> >>>> Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov> >>>> --- >>>> tools/flask/libflask/flask_op.c | 59 +++++++++++++++++++++++++++++++ >>>> tools/flask/libflask/include/libflask.h | 3 ++ >>>> 2 files changed, 62 insertions(+), 0 deletions(-) >>>> >>>> diff --git a/tools/flask/libflask/flask_op.c b/tools/flask/libflask/flask_op.c >>>> index d4b8ef0..412a05d 100644 >>>> --- a/tools/flask/libflask/flask_op.c >>>> +++ b/tools/flask/libflask/flask_op.c >>>> @@ -109,6 +109,65 @@ int flask_setenforce(xc_interface *xc_handle, int mode) >>>> return 0; >>>> } >>>> >>>> +int flask_getbool_byid(xc_interface *xc_handle, int id, char *name, int *curr, int *pend) >>>> +{ >>>> + flask_op_t op; >>>> + char buf[255]; >>>> + int rv; >>>> + >>>> + op.cmd = FLASK_GETBOOL2; >>>> + op.buf = buf; >>>> + op.size = 255; >>> >>> sizeof(buf)? Here and elsewhere (including a few existing locations in >>> flask_op.c). >>> >>>> + >>>> + snprintf(buf, sizeof buf, "%i", id); >>>> + >>>> + rv = xc_flask_op(xc_handle, &op); >>>> + >>>> + if ( rv ) >>>> + return rv; >>>> + >>>> + sscanf(buf, "%i %i %s", curr, pend, name); >>> >>> Do you care about sscanf failures? >> >> A failure here would be a sign of the hypervisor having made a format change >> that is not backwards compatible. Checking it would be more complete, however. >> >>> It seems from other uses in the file that buf can contain binary data so >>> would it make sense to make this two ints as binary followed by a >>> string? That would remove string parsing here and in the hypervisor >>> (which seems more critical to me?) >> >> That also seems far simpler to me; however, all the current FLASK hypercalls >> are done via string parsing so deviating from this for new operations would >> make them inconsistent. > > OK. I thought I''d seen some binary muddling in their but I must have > been mistaken.Loading a policy seems to be the only operation not involving scanf.>> If we didn''t have to care about backwards compatibility I would convert the >> entire flask_op hypercall to use a union-of-structures similar to domctl >> because the string parsing introduces unneeded complexity. > > How much do we care about backwards compat for this interface? Isn''t it > a tools only dom0 interface?Looking over the users - yes, it is, so we should be fine breaking compat here. This would also eliminate all in-hypervisor users of *scanf. I''ll try and see what a patch fixing this would look like. I also noticed that libxc and libflask have parallel implementations of some funcitons: xc_flask_getenforce from libxc and flask_getenforce from libflask. Not sure if this is a leftover from before ACM support was removed, but it appears that libflask can be eliminated completely (or remain only as a shim to call libxc functions).>>> Is there a defined maximum for the length of "name"? >> >> INITCONTEXTLEN = 256. > > So the max size of the buffer is 256 + whatever two int and two spaces > might maximally take, but your buffer is exactly 256. >Agreed, it would be better to adjust this to a larger buffer.
Keir Fraser
2012-Feb-02 15:28 UTC
Re: [PATCH 6/8] libxl: Add device_model_stubdomain_seclabel
On 01/02/2012 19:09, "Daniel De Graaf" <dgdegra@tycho.nsa.gov> wrote:> This allows the security label of stub domains to be specified. > > Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov>This and patch 7/8 I assume will be picked up by a libxl maintainer (cc''ing Ian Jackson). All your other outstanding patches I have now applied. -- Keir> --- > docs/man/xl.cfg.pod.5 | 4 ++++ > tools/libxl/libxl_dm.c | 1 + > tools/libxl/libxl_types.idl | 1 + > tools/libxl/xl_cmdimpl.c | 12 ++++++++++++ > 4 files changed, 18 insertions(+), 0 deletions(-) > > diff --git a/docs/man/xl.cfg.pod.5 b/docs/man/xl.cfg.pod.5 > index 9d90290..8f171b4 100644 > --- a/docs/man/xl.cfg.pod.5 > +++ b/docs/man/xl.cfg.pod.5 > @@ -789,6 +789,10 @@ Override the use of stubdomain based device-model. > Normally this will > be automatically selected based upon the other features and options > you have selected. > > +=item B<device_model_stubdomain_seclabel="LABEL"> > + > +Assign an XSM security label to the device-model stubdomain. > + > =item B<device_model_args=[ "ARG", "ARG", ...]> > > Pass additional arbitrary options on the devide-model command > diff --git a/tools/libxl/libxl_dm.c b/tools/libxl/libxl_dm.c > index 5fec137..e99d173 100644 > --- a/tools/libxl/libxl_dm.c > +++ b/tools/libxl/libxl_dm.c > @@ -703,6 +703,7 @@ static int libxl__create_stubdom(libxl__gc *gc, > dm_config.c_info.type = LIBXL_DOMAIN_TYPE_PV; > dm_config.c_info.name = libxl__sprintf(gc, "%s-dm", > libxl__domid_to_name(gc, guest_domid)); > + dm_config.c_info.ssidref = guest_config->b_info.device_model_ssidref; > > libxl_uuid_generate(&dm_config.c_info.uuid); > > diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl > index 3c24626..b77bc65 100644 > --- a/tools/libxl/libxl_types.idl > +++ b/tools/libxl/libxl_types.idl > @@ -217,6 +217,7 @@ libxl_domain_build_info = Struct("domain_build_info",[ > ("device_model_stubdomain", bool), > # you set device_model you must set device_model_version too > ("device_model", string), > + ("device_model_ssidref", uint32), > > # extra parameters pass directly to qemu, NULL terminated > ("extra", libxl_string_list), > diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c > index 0b811b5..e95bace 100644 > --- a/tools/libxl/xl_cmdimpl.c > +++ b/tools/libxl/xl_cmdimpl.c > @@ -1254,6 +1254,18 @@ skip_vfb: > if (!xlu_cfg_get_long (config, "device_model_stubdomain_override", &l, > 0)) > b_info->device_model_stubdomain = l; > > + if (!xlu_cfg_get_string (config, "device_model_stubdomain_seclabel", > &buf, 0)) { > + e = libxl_flask_context_to_sid(ctx, (char *)buf, strlen(buf), > + &b_info->device_model_ssidref); > + if (e) { > + if (errno == ENOSYS) { > + fprintf(stderr, "XSM Disabled: > device_model_stubdomain_seclabel not supported\n"); > + } else { > + fprintf(stderr, "Invalid device_model_stubdomain_seclabel: > %s\n", buf); > + exit(1); > + } > + } > + } > #define parse_extra_args(type) \ > e = xlu_cfg_get_list_as_string_list(config, "device_model_args"#type, \ > &b_info->extra##type, 0); \
Ian Jackson
2012-Feb-09 18:25 UTC
Re: [PATCH 6/8] libxl: Add device_model_stubdomain_seclabel
Daniel De Graaf writes ("[Xen-devel] [PATCH 6/8] libxl: Add device_model_stubdomain_seclabel"):> This allows the security label of stub domains to be specified.Acked-by: Ian Jackson <ian.jackson@eu.citrix.com> Committed-by: Ian Jackson <ian.jackson@eu.citrix.com>
Ian Jackson
2012-Feb-09 18:25 UTC
Re: [PATCH 7/8] flask/policy: add device model types to example policy
Daniel De Graaf writes ("[Xen-devel] [PATCH 7/8] flask/policy: add device model types to example policy"):> This adds an example user for device_model_stubdomain_seclabel. > > Signed-off-by: Daniel De Graaf <dgdegra@tycho.nsa.gov>Committed-by: Ian Jackson <ian.jackson@eu.citrix.com>