if ( unlikely((d = rcu_lock_domain_by_id(domctl->domain)) == NULL) )
break;
- ret = xsm_ioport_permission(d, fp,
- domctl->u.ioport_permission.allow_access);
- if ( ret )
- {
- rcu_unlock_domain(d);
- break;
- }
-
if ( np == 0 )
ret = 0;
else if ( domctl->u.ioport_permission.allow_access )
if ( (d = rcu_lock_domain_by_id(domctl->domain)) == NULL )
break;
+ ret = xsm_sendtrigger(d);
+ if ( ret )
+ goto sendtrigger_out;
+
ret = -EINVAL;
if ( domctl->u.sendtrigger.vcpu >= MAX_VIRT_CPUS )
goto sendtrigger_out;
bus = (domctl->u.assign_device.machine_bdf >> 16) & 0xff;
devfn = (domctl->u.assign_device.machine_bdf >> 8) & 0xff;
+ ret = xsm_test_assign_device(domctl->u.assign_device.machine_bdf);
+ if ( ret )
+ break;
+
if ( device_assigned(bus, devfn) )
{
gdprintk(XENLOG_ERR, "XEN_DOMCTL_test_assign_device: "
"XEN_DOMCTL_assign_device: get_domain_by_id() failed\n");
break;
}
+
+ ret = xsm_assign_device(d, domctl->u.assign_device.machine_bdf);
+ if ( ret )
+ goto assign_device_out;
+
bus = (domctl->u.assign_device.machine_bdf >> 16) & 0xff;
devfn = (domctl->u.assign_device.machine_bdf >> 8) & 0xff;
"assign device (%x:%x:%x) failed\n",
bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
+ assign_device_out:
put_domain(d);
}
break;
"XEN_DOMCTL_deassign_device: get_domain_by_id() failed\n");
break;
}
+
+ ret = xsm_assign_device(d, domctl->u.assign_device.machine_bdf);
+ if ( ret )
+ goto deassign_device_out;
+
bus = (domctl->u.assign_device.machine_bdf >> 16) & 0xff;
devfn = (domctl->u.assign_device.machine_bdf >> 8) & 0xff;
deassign_device(d, bus, devfn);
gdprintk(XENLOG_INFO, "XEN_DOMCTL_deassign_device: bdf = %x:%x:%x\n",
bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
+
+ deassign_device_out:
put_domain(d);
}
break;
if ( (d = rcu_lock_domain_by_id(domctl->domain)) == NULL )
break;
bind = &(domctl->u.bind_pt_irq);
+
+ ret = xsm_bind_pt_irq(d, bind);
+ if ( ret )
+ goto bind_out;
+
if ( iommu_enabled )
ret = pt_irq_create_bind_vtd(d, bind);
if ( ret < 0 )
gdprintk(XENLOG_ERR, "pt_irq_create_bind failed!\n");
+
+ bind_out:
rcu_unlock_domain(d);
}
break;
if ( d == NULL )
break;
+ ret = xsm_pin_mem_cacheattr(d);
+ if ( ret )
+ goto pin_out;
+
ret = hvm_set_mem_pinned_cacheattr(
d, domctl->u.pin_mem_cacheattr.start,
domctl->u.pin_mem_cacheattr.end,
domctl->u.pin_mem_cacheattr.type);
+ pin_out:
rcu_unlock_domain(d);
}
break;
if ( d == NULL )
break;
+ ret = xsm_ext_vcpucontext(d, domctl->cmd);
+ if ( ret )
+ goto ext_vcpucontext_out;
+
ret = -ESRCH;
if ( (evc->vcpu >= MAX_VIRT_CPUS) ||
((v = d->vcpu[evc->vcpu]) == NULL) )
break;
case XENPF_firmware_info:
+ ret = xsm_firmware_info();
+ if ( ret )
+ break;
+
switch ( op->u.firmware_info.type )
{
case XEN_FW_DISK_INFO: {
break;
case XENPF_enter_acpi_sleep:
+ ret = xsm_acpi_sleep();
+ if ( ret )
+ break;
+
ret = acpi_enter_sleep(&op->u.enter_acpi_sleep);
break;
case XENPF_change_freq:
+ ret = xsm_change_freq();
+ if ( ret )
+ break;
+
ret = -ENOSYS;
if ( cpufreq_controller != FREQCTL_dom0_kernel )
break;
XEN_GUEST_HANDLE(uint8) cpumap_bitmap;
XEN_GUEST_HANDLE(uint64) idletimes;
+ ret = xsm_getidletime();
+ if ( ret )
+ break;
+
ret = -ENOSYS;
if ( cpufreq_controller != FREQCTL_dom0_kernel )
break;
if ( d == NULL )
break;
- ret = xsm_irq_permission(d, pirq, op->u.irq_permission.allow_access);
- if ( ret )
- goto irq_permission_out;
-
if ( op->u.irq_permission.allow_access )
ret = irq_permit_access(d, pirq);
else
ret = irq_deny_access(d, pirq);
- irq_permission_out:
rcu_unlock_domain(d);
}
break;
if ( d == NULL )
break;
- ret = xsm_iomem_permission(d, mfn, op->u.iomem_permission.allow_access);
- if ( ret )
- goto iomem_permission_out;
-
if ( op->u.iomem_permission.allow_access )
ret = iomem_permit_access(d, mfn, mfn + nr_mfns - 1);
else
ret = iomem_deny_access(d, mfn, mfn + nr_mfns - 1);
- iomem_permission_out:
rcu_unlock_domain(d);
}
break;
goto set_target_out;
}
+ ret = xsm_set_target(d, e);
+ if ( ret ) {
+ put_domain(e);
+ goto set_target_out;
+ }
+
/* Hold reference on @e until we destroy @d. */
d->target = e;
#include <xen/sched.h>
#include <xen/errno.h>
#include <xen/rangeset.h>
+#include <xsm/xsm.h>
/* An inclusive range [s,e] and pointer to next range in ascending order. */
struct range {
struct range *x, *y;
int rc = 0;
+ rc = xsm_add_range(r->domain, r->name, s, e);
+ if ( rc )
+ return rc;
+
ASSERT(s <= e);
spin_lock(&r->lock);
struct range *x, *y, *t;
int rc = 0;
+ rc = xsm_remove_range(r->domain, r->name, s, e);
+ if ( rc )
+ return rc;
+
ASSERT(s <= e);
spin_lock(&r->lock);
char c;
uint32_t i;
+ ret = xsm_debug_keys();
+ if ( ret )
+ break;
+
for ( i = 0; i < op->u.debug_keys.nr_keys; i++ )
{
if ( copy_from_guest_offset(&c, op->u.debug_keys.keys, i, 1) )
nr_cpus = min_t(uint32_t, op->u.getcpuinfo.max_cpus, NR_CPUS);
+ ret = xsm_getcpuinfo();
+ if ( ret )
+ break;
+
for ( i = 0; i < nr_cpus; i++ )
{
/* Assume no holes in idle-vcpu map. */
case XEN_SYSCTL_availheap:
{
+ ret = xsm_availheap();
+ if ( ret )
+ break;
+
op->u.availheap.avail_bytes = avail_domheap_pages_region(
op->u.availheap.node,
op->u.availheap.min_bitwidth,
int (*getvcpucontext) (struct domain *d);
int (*getvcpuinfo) (struct domain *d);
int (*domain_settime) (struct domain *d);
+ int (*set_target) (struct domain *d, struct domain *e);
int (*tbufcontrol) (void);
int (*readconsole) (uint32_t clear);
int (*sched_id) (void);
int (*setdomainmaxmem) (struct domain *d);
int (*setdomainhandle) (struct domain *d);
int (*setdebugging) (struct domain *d);
- int (*irq_permission) (struct domain *d, uint8_t pirq, uint8_t access);
- int (*iomem_permission) (struct domain *d, unsigned long mfn,
- uint8_t access);
int (*perfcontrol) (void);
+ int (*debug_keys) (void);
+ int (*getcpuinfo) (void);
+ int (*availheap) (void);
int (*evtchn_unbound) (struct domain *d, struct evtchn *chn, domid_t id2);
int (*evtchn_interdomain) (struct domain *d1, struct evtchn *chn1,
int (*kexec) (void);
int (*schedop_shutdown) (struct domain *d1, struct domain *d2);
+ int (*add_range) (struct domain *d, char *name, unsigned long s, unsigned long e);
+ int (*remove_range) (struct domain *d, char *name, unsigned long s, unsigned long e);
long (*__do_xsm_op) (XEN_GUEST_HANDLE(xsm_op_t) op);
#ifdef CONFIG_X86
int (*shadow_control) (struct domain *d, uint32_t op);
- int (*ioport_permission) (struct domain *d, uint32_t ioport,
- uint8_t access);
int (*getpageframeinfo) (struct page_info *page);
int (*getmemlist) (struct domain *d);
int (*hypercall_init) (struct domain *d);
int (*microcode) (void);
int (*physinfo) (void);
int (*platform_quirk) (uint32_t);
+ int (*firmware_info) (void);
+ int (*acpi_sleep) (void);
+ int (*change_freq) (void);
+ int (*getidletime) (void);
int (*machine_memory_map) (void);
int (*domain_memory_map) (struct domain *d);
int (*mmu_normal_update) (struct domain *d, intpte_t fpte);
int (*update_va_mapping) (struct domain *d, l1_pgentry_t pte);
int (*add_to_physmap) (struct domain *d1, struct domain *d2);
int (*remove_from_physmap) (struct domain *d1, struct domain *d2);
+ int (*sendtrigger) (struct domain *d);
+ int (*test_assign_device) (uint32_t machine_bdf);
+ int (*assign_device) (struct domain *d, uint32_t machine_bdf);
+ int (*deassign_device) (struct domain *d, uint32_t machine_bdf);
+ int (*bind_pt_irq) (struct domain *d, struct xen_domctl_bind_pt_irq *bind);
+ int (*pin_mem_cacheattr) (struct domain *d);
+ int (*ext_vcpucontext) (struct domain *d, uint32_t cmd);
#endif
};
return xsm_call(domain_settime(d));
}
+static inline int xsm_set_target (struct domain *d, struct domain *e)
+{
+ return xsm_call(set_target(d, e));
+}
+
static inline int xsm_tbufcontrol (void)
{
return xsm_call(tbufcontrol());
return xsm_call(setdebugging(d));
}
-static inline int xsm_irq_permission (struct domain *d, uint8_t pirq,
- uint8_t access)
+static inline int xsm_perfcontrol (void)
{
- return xsm_call(irq_permission(d, pirq, access));
-}
+ return xsm_call(perfcontrol());
+}
-static inline int xsm_iomem_permission (struct domain *d, unsigned long mfn,
- uint8_t access)
+static inline int xsm_debug_keys (void)
{
- return xsm_call(iomem_permission(d, mfn, access));
+ return xsm_call(debug_keys());
}
-static inline int xsm_perfcontrol (void)
+static inline int xsm_availheap (void)
{
- return xsm_call(perfcontrol());
+ return xsm_call(availheap());
+}
+
+static inline int xsm_getcpuinfo (void)
+{
+ return xsm_call(getcpuinfo());
}
static inline int xsm_evtchn_unbound (struct domain *d1, struct evtchn *chn,
return xsm_call(schedop_shutdown(d1, d2));
}
+static inline int xsm_add_range (struct domain *d, char *name, unsigned long s,
+ unsigned long e)
+{
+ return xsm_call(add_range(d, name, s, e));
+}
+
+static inline int xsm_remove_range (struct domain *d, char *name, unsigned long s,
+ unsigned long e)
+{
+ return xsm_call(remove_range(d, name, s, e));
+}
+
static inline long __do_xsm_op (XEN_GUEST_HANDLE(xsm_op_t) op)
{
return xsm_call(__do_xsm_op(op));
return xsm_call(shadow_control(d, op));
}
-static inline int xsm_ioport_permission (struct domain *d, uint32_t ioport,
- uint8_t access)
-{
- return xsm_call(ioport_permission(d, ioport, access));
-}
-
static inline int xsm_getpageframeinfo (struct page_info *page)
{
return xsm_call(getpageframeinfo(page));
return xsm_call(platform_quirk(quirk));
}
+static inline int xsm_firmware_info (void)
+{
+ return xsm_call(firmware_info());
+}
+
+static inline int xsm_acpi_sleep (void)
+{
+ return xsm_call(acpi_sleep());
+}
+
+static inline int xsm_change_freq (void)
+{
+ return xsm_call(change_freq());
+}
+
+static inline int xsm_getidletime (void)
+{
+ return xsm_call(getidletime());
+}
+
static inline int xsm_machine_memory_map(void)
{
return xsm_call(machine_memory_map());
{
return xsm_call(remove_from_physmap(d1, d2));
}
+
+static inline int xsm_sendtrigger(struct domain *d)
+{
+ return xsm_call(sendtrigger(d));
+}
+
+static inline int xsm_test_assign_device(uint32_t machine_bdf)
+{
+ return xsm_call(test_assign_device(machine_bdf));
+}
+
+static inline int xsm_assign_device(struct domain *d, uint32_t machine_bdf)
+{
+ return xsm_call(assign_device(d, machine_bdf));
+}
+
+static inline int xsm_deassign_device(struct domain *d, uint32_t machine_bdf)
+{
+ return xsm_call(deassign_device(d, machine_bdf));
+}
+
+static inline int xsm_bind_pt_irq(struct domain *d,
+ struct xen_domctl_bind_pt_irq *bind)
+{
+ return xsm_call(bind_pt_irq(d, bind));
+}
+
+static inline int xsm_pin_mem_cacheattr(struct domain *d)
+{
+ return xsm_call(pin_mem_cacheattr(d));
+}
+
+static inline int xsm_ext_vcpucontext(struct domain *d, uint32_t cmd)
+{
+ return xsm_call(ext_vcpucontext(d, cmd));
+}
#endif /* CONFIG_X86 */
#endif /* __XSM_H */
return 0;
}
+static int dummy_set_target (struct domain *d, struct domain *e)
+{
+ return 0;
+}
+
static int dummy_tbufcontrol (void)
{
return 0;
return 0;
}
-static int dummy_irq_permission (struct domain *d, uint8_t pirq, uint8_t access)
+static int dummy_perfcontrol (void)
{
return 0;
}
-static int dummy_iomem_permission (struct domain *d, unsigned long mfn,
- uint8_t access)
+static int dummy_debug_keys (void)
{
return 0;
}
-static int dummy_perfcontrol (void)
+static int dummy_getcpuinfo (void)
+{
+ return 0;
+}
+
+static int dummy_availheap (void)
{
return 0;
}
return -ENOSYS;
}
-#ifdef CONFIG_X86
-static int dummy_shadow_control (struct domain *d, uint32_t op)
+static int dummy_add_range (struct domain *d, char *name, unsigned long s, unsigned long e)
+{
+ return 0;
+}
+
+static int dummy_remove_range (struct domain *d, char *name, unsigned long s,
+ unsigned long e)
{
return 0;
}
-static int dummy_ioport_permission (struct domain *d, uint32_t ioport,
- uint8_t access)
+#ifdef CONFIG_X86
+static int dummy_shadow_control (struct domain *d, uint32_t op)
{
return 0;
}
return 0;
}
+static int dummy_firmware_info (void)
+{
+ return 0;
+}
+
+static int dummy_acpi_sleep (void)
+{
+ return 0;
+}
+
+static int dummy_change_freq (void)
+{
+ return 0;
+}
+
+static int dummy_getidletime (void)
+{
+ return 0;
+}
+
static int dummy_machine_memory_map (void)
{
return 0;
return 0;
}
+static int dummy_sendtrigger (struct domain *d)
+{
+ return 0;
+}
+
+static int dummy_test_assign_device (uint32_t machine_bdf)
+{
+ return 0;
+}
+
+static int dummy_assign_device (struct domain *d, uint32_t machine_bdf)
+{
+ return 0;
+}
+
+static int dummy_deassign_device (struct domain *d, uint32_t machine_bdf)
+{
+ return 0;
+}
+
+static int dummy_bind_pt_irq (struct domain *d, struct xen_domctl_bind_pt_irq *bind)
+{
+ return 0;
+}
+
+static int dummy_pin_mem_cacheattr (struct domain *d)
+{
+ return 0;
+}
+
+static int dummy_ext_vcpucontext (struct domain *d, uint32_t cmd)
+{
+ return 0;
+}
+
static int dummy_remove_from_physmap (struct domain *d1, struct domain *d2)
{
return 0;
set_to_dummy_if_null(ops, getvcpucontext);
set_to_dummy_if_null(ops, getvcpuinfo);
set_to_dummy_if_null(ops, domain_settime);
+ set_to_dummy_if_null(ops, set_target);
set_to_dummy_if_null(ops, tbufcontrol);
set_to_dummy_if_null(ops, readconsole);
set_to_dummy_if_null(ops, sched_id);
set_to_dummy_if_null(ops, setdomainmaxmem);
set_to_dummy_if_null(ops, setdomainhandle);
set_to_dummy_if_null(ops, setdebugging);
- set_to_dummy_if_null(ops, irq_permission);
- set_to_dummy_if_null(ops, iomem_permission);
set_to_dummy_if_null(ops, perfcontrol);
+ set_to_dummy_if_null(ops, debug_keys);
+ set_to_dummy_if_null(ops, getcpuinfo);
+ set_to_dummy_if_null(ops, availheap);
set_to_dummy_if_null(ops, evtchn_unbound);
set_to_dummy_if_null(ops, evtchn_interdomain);
set_to_dummy_if_null(ops, kexec);
set_to_dummy_if_null(ops, schedop_shutdown);
+ set_to_dummy_if_null(ops, add_range);
+ set_to_dummy_if_null(ops, remove_range);
+
set_to_dummy_if_null(ops, __do_xsm_op);
#ifdef CONFIG_X86
set_to_dummy_if_null(ops, shadow_control);
- set_to_dummy_if_null(ops, ioport_permission);
set_to_dummy_if_null(ops, getpageframeinfo);
set_to_dummy_if_null(ops, getmemlist);
set_to_dummy_if_null(ops, hypercall_init);
set_to_dummy_if_null(ops, microcode);
set_to_dummy_if_null(ops, physinfo);
set_to_dummy_if_null(ops, platform_quirk);
+ set_to_dummy_if_null(ops, firmware_info);
+ set_to_dummy_if_null(ops, acpi_sleep);
+ set_to_dummy_if_null(ops, change_freq);
+ set_to_dummy_if_null(ops, getidletime);
set_to_dummy_if_null(ops, machine_memory_map);
set_to_dummy_if_null(ops, domain_memory_map);
set_to_dummy_if_null(ops, mmu_normal_update);
set_to_dummy_if_null(ops, update_va_mapping);
set_to_dummy_if_null(ops, add_to_physmap);
set_to_dummy_if_null(ops, remove_from_physmap);
+ set_to_dummy_if_null(ops, sendtrigger);
+ set_to_dummy_if_null(ops, test_assign_device);
+ set_to_dummy_if_null(ops, assign_device);
+ set_to_dummy_if_null(ops, deassign_device);
+ set_to_dummy_if_null(ops, bind_pt_irq);
+ set_to_dummy_if_null(ops, pin_mem_cacheattr);
+ set_to_dummy_if_null(ops, ext_vcpucontext);
#endif
}
if ( rc )
goto out;
- rc = avc_has_perm(dsec->sid, newsid, SECCLASS_EVENT,
- EVENT__CREATE|EVENT__ALLOC, NULL);
+ rc = avc_has_perm(dsec->sid, newsid, SECCLASS_EVENT, EVENT__CREATE, NULL);
if ( rc )
goto out;
static int flask_evtchn_send(struct domain *d, struct evtchn *chn)
{
- return domain_has_evtchn(d, chn, EVENT__SEND);
+ int rc;
+
+ switch ( chn->state )
+ {
+ case ECS_INTERDOMAIN:
+ rc = domain_has_evtchn(d, chn, EVENT__SEND);
+ break;
+ case ECS_IPI:
+ case ECS_UNBOUND:
+ rc = 0;
+ break;
+ default:
+ rc = -EPERM;
+ }
+
+ return rc;
}
static int flask_evtchn_status(struct domain *d, struct evtchn *chn)
dsec1 = current->domain->ssid;
- if ( dsec1->create_sid == SECSID_NULL )
- dsec1->create_sid = ssidref;
+ if ( dsec1->create_sid == SECSID_NULL )
+ dsec1->create_sid = ssidref;
- rc = avc_has_perm(dsec1->sid, dsec1->create_sid, SECCLASS_DOMAIN,
- DOMAIN__CREATE, NULL);
- if ( rc )
+ rc = avc_has_perm(dsec1->sid, dsec1->create_sid, SECCLASS_DOMAIN,
+ DOMAIN__CREATE, NULL);
+ if ( rc )
{
- dsec1->create_sid = SECSID_NULL;
- return rc;
+ dsec1->create_sid = SECSID_NULL;
+ return rc;
}
dsec2 = d->ssid;
dsec2->sid = dsec1->create_sid;
- dsec1->create_sid = SECSID_NULL;
- dsec2->create_sid = SECSID_NULL;
+ dsec1->create_sid = SECSID_NULL;
+ dsec2->create_sid = SECSID_NULL;
return rc;
}
return domain_has_perm(current->domain, d, SECCLASS_DOMAIN, DOMAIN__SETTIME);
}
+static int flask_set_target(struct domain *d, struct domain *e)
+{
+ return domain_has_perm(d, e, SECCLASS_DOMAIN, DOMAIN__SET_TARGET);
+}
+
static int flask_tbufcontrol(void)
{
return domain_has_xen(current->domain, SECCLASS_XEN);
DOMAIN__SETDEBUGGING);
}
+static int flask_debug_keys(void)
+{
+ return domain_has_xen(current->domain, XEN__DEBUG);
+}
+
+static int flask_getcpuinfo(void)
+{
+ return domain_has_xen(current->domain, XEN__GETCPUINFO);
+}
+
+static int flask_availheap(void)
+{
+ return domain_has_xen(current->domain, XEN__HEAP);
+}
+
static inline u32 resource_to_perm(uint8_t access)
{
if ( access )
return RESOURCE__REMOVE;
}
-static int flask_irq_permission(struct domain *d, uint8_t pirq, uint8_t access)
+static int irq_has_perm(struct domain *d, uint8_t pirq, uint8_t access)
{
u32 perm;
u32 rsid;
return rc;
rc = avc_has_perm(ssec->sid, rsid, SECCLASS_RESOURCE, perm, NULL);
-
if ( rc )
return rc;
- return avc_has_perm(tsec->sid, rsid, SECCLASS_RESOURCE,
+ if ( access )
+ return avc_has_perm(tsec->sid, rsid, SECCLASS_RESOURCE,
RESOURCE__USE, NULL);
+ else
+ return rc;
}
-static int flask_iomem_permission(struct domain *d, unsigned long mfn,
- uint8_t access)
+static int iomem_has_perm(struct domain *d, unsigned long mfn, uint8_t access)
{
u32 perm;
u32 rsid;
rc = domain_has_perm(current->domain, d, SECCLASS_RESOURCE,
resource_to_perm(access));
-
if ( rc )
return rc;
return domain_has_perm(current->domain, d, SECCLASS_SHADOW, perm);
}
-static int flask_ioport_permission(struct domain *d, uint32_t ioport,
- uint8_t access)
+static int ioport_has_perm(struct domain *d, uint32_t ioport, uint8_t access)
{
u32 perm;
u32 rsid;
if ( rc )
return rc;
- return avc_has_perm(tsec->sid, rsid, SECCLASS_RESOURCE,
+ if ( access )
+ return avc_has_perm(tsec->sid, rsid, SECCLASS_RESOURCE,
RESOURCE__USE, NULL);
+ else
+ return rc;
}
static int flask_getpageframeinfo(struct page_info *page)
XEN__QUIRK, NULL);
}
+static int flask_firmware_info(void)
+{
+ return domain_has_xen(current->domain, XEN__FIRMWARE);
+}
+
+static int flask_acpi_sleep(void)
+{
+ return domain_has_xen(current->domain, XEN__SLEEP);
+}
+
+static int flask_change_freq(void)
+{
+ return domain_has_xen(current->domain, XEN__FREQUENCY);
+}
+
+static int flask_getidletime(void)
+{
+ return domain_has_xen(current->domain, XEN__GETIDLE);
+}
+
static int flask_machine_memory_map(void)
{
struct domain_security_struct *dsec;
{
return domain_has_perm(d1, d2, SECCLASS_MMU, MMU__PHYSMAP);
}
+
+static int flask_sendtrigger(struct domain *d)
+{
+ return domain_has_perm(current->domain, d, SECCLASS_DOMAIN, DOMAIN__TRIGGER);
+}
+
+static int flask_test_assign_device(uint32_t machine_bdf)
+{
+ u32 rsid;
+ int rc = -EPERM;
+ struct domain_security_struct *ssec = current->domain->ssid;
+
+ rc = security_device_sid(machine_bdf, &rsid);
+ if ( rc )
+ return rc;
+
+ return rc = avc_has_perm(ssec->sid, rsid, SECCLASS_RESOURCE, RESOURCE__STAT_DEVICE, NULL);
+}
+
+static int flask_assign_device(struct domain *d, uint32_t machine_bdf)
+{
+ u32 rsid;
+ int rc = -EPERM;
+ struct domain_security_struct *ssec, *tsec;
+
+ rc = domain_has_perm(current->domain, d, SECCLASS_RESOURCE, RESOURCE__ADD);
+ if ( rc )
+ return rc;
+
+ rc = security_device_sid(machine_bdf, &rsid);
+ if ( rc )
+ return rc;
+
+ ssec = current->domain->ssid;
+ rc = avc_has_perm(ssec->sid, rsid, SECCLASS_RESOURCE, RESOURCE__ADD_DEVICE, NULL);
+ if ( rc )
+ return rc;
+
+ tsec = d->ssid;
+ return avc_has_perm(tsec->sid, rsid, SECCLASS_RESOURCE, RESOURCE__USE, NULL);
+}
+
+static int flask_deassign_device(struct domain *d, uint32_t machine_bdf)
+{
+ u32 rsid;
+ int rc = -EPERM;
+ struct domain_security_struct *ssec = current->domain->ssid;
+
+ rc = domain_has_perm(current->domain, d, SECCLASS_RESOURCE, RESOURCE__REMOVE);
+ if ( rc )
+ return rc;
+
+ rc = security_device_sid(machine_bdf, &rsid);
+ if ( rc )
+ return rc;
+
+ return rc = avc_has_perm(ssec->sid, rsid, SECCLASS_RESOURCE, RESOURCE__REMOVE_DEVICE, NULL);
+}
+
+static int flask_bind_pt_irq (struct domain *d, struct xen_domctl_bind_pt_irq *bind)
+{
+ u32 rsid;
+ int rc = -EPERM;
+ struct domain_security_struct *ssec, *tsec;
+
+ rc = domain_has_perm(current->domain, d, SECCLASS_RESOURCE, RESOURCE__ADD);
+ if ( rc )
+ return rc;
+
+ rc = security_pirq_sid(bind->machine_irq, &rsid);
+ if ( rc )
+ return rc;
+
+ ssec = current->domain->ssid;
+ rc = avc_has_perm(ssec->sid, rsid, SECCLASS_HVM, HVM__BIND_IRQ, NULL);
+ if ( rc )
+ return rc;
+
+ tsec = d->ssid;
+ return avc_has_perm(tsec->sid, rsid, SECCLASS_RESOURCE, RESOURCE__USE, NULL);
+}
+
+static int flask_pin_mem_cacheattr (struct domain *d)
+{
+ return domain_has_perm(current->domain, d, SECCLASS_HVM, HVM__CACHEATTR);
+}
+
+static int flask_ext_vcpucontext (struct domain *d, uint32_t cmd)
+{
+ u32 perm;
+
+ switch ( cmd )
+ {
+ case XEN_DOMCTL_set_ext_vcpucontext:
+ perm = DOMAIN__SETEXTVCPUCONTEXT;
+ break;
+ case XEN_DOMCTL_get_ext_vcpucontext:
+ perm = DOMAIN__GETEXTVCPUCONTEXT;
+ break;
+ default:
+ return -EPERM;
+ }
+
+ return domain_has_perm(current->domain, d, SECCLASS_DOMAIN, perm);
+}
+#endif
+
+static int io_has_perm(struct domain *d, char *name, unsigned long s,
+ unsigned long e, u32 access)
+{
+ int rc = -EPERM;
+
+ if ( strcmp(name, "I/O Memory") == 0 )
+ {
+ rc = iomem_has_perm(d, s, access);
+ if ( rc )
+ return rc;
+
+ if ( s != e )
+ rc = iomem_has_perm(d, s, access);
+ }
+ else if ( strcmp(name, "Interrupts") == 0 )
+ {
+ rc = irq_has_perm(d, s, access);
+ if ( rc )
+ return rc;
+
+ if ( s != e )
+ rc = irq_has_perm(d, e, access);
+ }
+#ifdef CONFIG_X86
+ else if ( strcmp(name, "I/O Ports") == 0 )
+ {
+ rc = ioport_has_perm(d, s, access);
+ if ( rc )
+ return rc;
+
+ if ( s != e )
+ rc = ioport_has_perm(d, e, access);
+ }
#endif
+ return rc;
+}
+
+static int flask_add_range(struct domain *d, char *name, unsigned long s,
+ unsigned long e)
+{
+ return io_has_perm(d, name, s, e, 1);
+}
+
+static int flask_remove_range(struct domain *d, char *name, unsigned long s,
+ unsigned long e)
+{
+ return io_has_perm(d, name, s, e, 0);
+}
+
long do_flask_op(XEN_GUEST_HANDLE(xsm_op_t) u_flask_op);
static struct xsm_operations flask_ops = {
.getvcpucontext = flask_getvcpucontext,
.getvcpuinfo = flask_getvcpuinfo,
.domain_settime = flask_domain_settime,
+ .set_target = flask_set_target,
.tbufcontrol = flask_tbufcontrol,
.readconsole = flask_readconsole,
.sched_id = flask_sched_id,
.setdomainmaxmem = flask_setdomainmaxmem,
.setdomainhandle = flask_setdomainhandle,
.setdebugging = flask_setdebugging,
- .irq_permission = flask_irq_permission,
- .iomem_permission = flask_iomem_permission,
.perfcontrol = flask_perfcontrol,
+ .debug_keys = flask_debug_keys,
+ .getcpuinfo = flask_getcpuinfo,
+ .availheap = flask_availheap,
.evtchn_unbound = flask_evtchn_unbound,
.evtchn_interdomain = flask_evtchn_interdomain,
.kexec = flask_kexec,
.schedop_shutdown = flask_schedop_shutdown,
+ .add_range = flask_add_range,
+ .remove_range = flask_remove_range,
+
.__do_xsm_op = do_flask_op,
#ifdef CONFIG_X86
.shadow_control = flask_shadow_control,
- .ioport_permission = flask_ioport_permission,
.getpageframeinfo = flask_getpageframeinfo,
.getmemlist = flask_getmemlist,
.hypercall_init = flask_hypercall_init,
.microcode = flask_microcode,
.physinfo = flask_physinfo,
.platform_quirk = flask_platform_quirk,
+ .firmware_info = flask_firmware_info,
+ .acpi_sleep = flask_acpi_sleep,
+ .change_freq = flask_change_freq,
+ .getidletime = flask_getidletime,
.machine_memory_map = flask_machine_memory_map,
.domain_memory_map = flask_domain_memory_map,
.mmu_normal_update = flask_mmu_normal_update,
.update_va_mapping = flask_update_va_mapping,
.add_to_physmap = flask_add_to_physmap,
.remove_from_physmap = flask_remove_from_physmap,
+ .sendtrigger = flask_sendtrigger,
+ .test_assign_device = flask_test_assign_device,
+ .assign_device = flask_assign_device,
+ .deassign_device = flask_deassign_device,
+ .bind_pt_irq = flask_bind_pt_irq,
+ .pin_mem_cacheattr = flask_pin_mem_cacheattr,
+ .ext_vcpucontext = flask_ext_vcpucontext,
#endif
};
S_(SECCLASS_XEN, XEN__PRIVPROFILE, "privprofile")
S_(SECCLASS_XEN, XEN__NONPRIVPROFILE, "nonprivprofile")
S_(SECCLASS_XEN, XEN__KEXEC, "kexec")
+ S_(SECCLASS_XEN, XEN__FIRMWARE, "firmware")
+ S_(SECCLASS_XEN, XEN__SLEEP, "sleep")
+ S_(SECCLASS_XEN, XEN__FREQUENCY, "frequency")
+ S_(SECCLASS_XEN, XEN__GETIDLE, "getidle")
+ S_(SECCLASS_XEN, XEN__DEBUG, "debug")
+ S_(SECCLASS_XEN, XEN__GETCPUINFO, "getcpuinfo")
+ S_(SECCLASS_XEN, XEN__HEAP, "heap")
S_(SECCLASS_DOMAIN, DOMAIN__SETVCPUCONTEXT, "setvcpucontext")
S_(SECCLASS_DOMAIN, DOMAIN__PAUSE, "pause")
S_(SECCLASS_DOMAIN, DOMAIN__UNPAUSE, "unpause")
S_(SECCLASS_DOMAIN, DOMAIN__RESUME, "resume")
S_(SECCLASS_DOMAIN, DOMAIN__CREATE, "create")
+ S_(SECCLASS_DOMAIN, DOMAIN__TRANSITION, "transition")
S_(SECCLASS_DOMAIN, DOMAIN__MAX_VCPUS, "max_vcpus")
S_(SECCLASS_DOMAIN, DOMAIN__DESTROY, "destroy")
S_(SECCLASS_DOMAIN, DOMAIN__SETVCPUAFFINITY, "setvcpuaffinity")
S_(SECCLASS_DOMAIN, DOMAIN__SETDOMAINHANDLE, "setdomainhandle")
S_(SECCLASS_DOMAIN, DOMAIN__SETDEBUGGING, "setdebugging")
S_(SECCLASS_DOMAIN, DOMAIN__HYPERCALL, "hypercall")
- S_(SECCLASS_DOMAIN, DOMAIN__TRANSITION, "transition")
S_(SECCLASS_DOMAIN, DOMAIN__SETTIME, "settime")
+ S_(SECCLASS_DOMAIN, DOMAIN__SET_TARGET, "set_target")
S_(SECCLASS_DOMAIN, DOMAIN__SHUTDOWN, "shutdown")
S_(SECCLASS_DOMAIN, DOMAIN__SETADDRSIZE, "setaddrsize")
S_(SECCLASS_DOMAIN, DOMAIN__GETADDRSIZE, "getaddrsize")
+ S_(SECCLASS_DOMAIN, DOMAIN__TRIGGER, "trigger")
+ S_(SECCLASS_DOMAIN, DOMAIN__GETEXTVCPUCONTEXT, "getextvcpucontext")
+ S_(SECCLASS_DOMAIN, DOMAIN__SETEXTVCPUCONTEXT, "setextvcpucontext")
S_(SECCLASS_HVM, HVM__SETHVMC, "sethvmc")
S_(SECCLASS_HVM, HVM__GETHVMC, "gethvmc")
S_(SECCLASS_HVM, HVM__SETPARAM, "setparam")
S_(SECCLASS_HVM, HVM__PCILEVEL, "pcilevel")
S_(SECCLASS_HVM, HVM__IRQLEVEL, "irqlevel")
S_(SECCLASS_HVM, HVM__PCIROUTE, "pciroute")
+ S_(SECCLASS_HVM, HVM__BIND_IRQ, "bind_irq")
+ S_(SECCLASS_HVM, HVM__CACHEATTR, "cacheattr")
S_(SECCLASS_EVENT, EVENT__BIND, "bind")
- S_(SECCLASS_EVENT, EVENT__CLOSE, "close")
S_(SECCLASS_EVENT, EVENT__SEND, "send")
S_(SECCLASS_EVENT, EVENT__STATUS, "status")
- S_(SECCLASS_EVENT, EVENT__UNMASK, "unmask")
S_(SECCLASS_EVENT, EVENT__NOTIFY, "notify")
S_(SECCLASS_EVENT, EVENT__CREATE, "create")
- S_(SECCLASS_EVENT, EVENT__ALLOC, "alloc")
S_(SECCLASS_EVENT, EVENT__VECTOR, "vector")
S_(SECCLASS_EVENT, EVENT__RESET, "reset")
S_(SECCLASS_GRANT, GRANT__MAP_READ, "map_read")
S_(SECCLASS_RESOURCE, RESOURCE__REMOVE_IOPORT, "remove_ioport")
S_(SECCLASS_RESOURCE, RESOURCE__ADD_IOMEM, "add_iomem")
S_(SECCLASS_RESOURCE, RESOURCE__REMOVE_IOMEM, "remove_iomem")
+ S_(SECCLASS_RESOURCE, RESOURCE__STAT_DEVICE, "stat_device")
+ S_(SECCLASS_RESOURCE, RESOURCE__ADD_DEVICE, "add_device")
+ S_(SECCLASS_RESOURCE, RESOURCE__REMOVE_DEVICE, "remove_device")
S_(SECCLASS_SECURITY, SECURITY__COMPUTE_AV, "compute_av")
S_(SECCLASS_SECURITY, SECURITY__COMPUTE_CREATE, "compute_create")
S_(SECCLASS_SECURITY, SECURITY__COMPUTE_MEMBER, "compute_member")
#define XEN__PRIVPROFILE 0x00008000UL
#define XEN__NONPRIVPROFILE 0x00010000UL
#define XEN__KEXEC 0x00020000UL
+#define XEN__FIRMWARE 0x00040000UL
+#define XEN__SLEEP 0x00080000UL
+#define XEN__FREQUENCY 0x00100000UL
+#define XEN__GETIDLE 0x00200000UL
+#define XEN__DEBUG 0x00400000UL
+#define XEN__GETCPUINFO 0x00800000UL
+#define XEN__HEAP 0x01000000UL
#define DOMAIN__SETVCPUCONTEXT 0x00000001UL
#define DOMAIN__PAUSE 0x00000002UL
#define DOMAIN__UNPAUSE 0x00000004UL
#define DOMAIN__RESUME 0x00000008UL
#define DOMAIN__CREATE 0x00000010UL
-#define DOMAIN__MAX_VCPUS 0x00000020UL
-#define DOMAIN__DESTROY 0x00000040UL
-#define DOMAIN__SETVCPUAFFINITY 0x00000080UL
-#define DOMAIN__GETVCPUAFFINITY 0x00000100UL
-#define DOMAIN__SCHEDULER 0x00000200UL
-#define DOMAIN__GETDOMAININFO 0x00000400UL
-#define DOMAIN__GETVCPUINFO 0x00000800UL
-#define DOMAIN__GETVCPUCONTEXT 0x00001000UL
-#define DOMAIN__SETDOMAINMAXMEM 0x00002000UL
-#define DOMAIN__SETDOMAINHANDLE 0x00004000UL
-#define DOMAIN__SETDEBUGGING 0x00008000UL
-#define DOMAIN__HYPERCALL 0x00010000UL
-#define DOMAIN__TRANSITION 0x00020000UL
+#define DOMAIN__TRANSITION 0x00000020UL
+#define DOMAIN__MAX_VCPUS 0x00000040UL
+#define DOMAIN__DESTROY 0x00000080UL
+#define DOMAIN__SETVCPUAFFINITY 0x00000100UL
+#define DOMAIN__GETVCPUAFFINITY 0x00000200UL
+#define DOMAIN__SCHEDULER 0x00000400UL
+#define DOMAIN__GETDOMAININFO 0x00000800UL
+#define DOMAIN__GETVCPUINFO 0x00001000UL
+#define DOMAIN__GETVCPUCONTEXT 0x00002000UL
+#define DOMAIN__SETDOMAINMAXMEM 0x00004000UL
+#define DOMAIN__SETDOMAINHANDLE 0x00008000UL
+#define DOMAIN__SETDEBUGGING 0x00010000UL
+#define DOMAIN__HYPERCALL 0x00020000UL
#define DOMAIN__SETTIME 0x00040000UL
-#define DOMAIN__SHUTDOWN 0x00080000UL
-#define DOMAIN__SETADDRSIZE 0x00100000UL
-#define DOMAIN__GETADDRSIZE 0x00200000UL
+#define DOMAIN__SET_TARGET 0x00080000UL
+#define DOMAIN__SHUTDOWN 0x00100000UL
+#define DOMAIN__SETADDRSIZE 0x00200000UL
+#define DOMAIN__GETADDRSIZE 0x00400000UL
+#define DOMAIN__TRIGGER 0x00800000UL
+#define DOMAIN__GETEXTVCPUCONTEXT 0x01000000UL
+#define DOMAIN__SETEXTVCPUCONTEXT 0x02000000UL
#define HVM__SETHVMC 0x00000001UL
#define HVM__GETHVMC 0x00000002UL
#define HVM__PCILEVEL 0x00000010UL
#define HVM__IRQLEVEL 0x00000020UL
#define HVM__PCIROUTE 0x00000040UL
+#define HVM__BIND_IRQ 0x00000080UL
+#define HVM__CACHEATTR 0x00000100UL
#define EVENT__BIND 0x00000001UL
-#define EVENT__CLOSE 0x00000002UL
-#define EVENT__SEND 0x00000004UL
-#define EVENT__STATUS 0x00000008UL
-#define EVENT__UNMASK 0x00000010UL
-#define EVENT__NOTIFY 0x00000020UL
-#define EVENT__CREATE 0x00000040UL
-#define EVENT__ALLOC 0x00000080UL
-#define EVENT__VECTOR 0x00000100UL
-#define EVENT__RESET 0x00000200UL
+#define EVENT__SEND 0x00000002UL
+#define EVENT__STATUS 0x00000004UL
+#define EVENT__NOTIFY 0x00000008UL
+#define EVENT__CREATE 0x00000010UL
+#define EVENT__VECTOR 0x00000020UL
+#define EVENT__RESET 0x00000040UL
#define GRANT__MAP_READ 0x00000001UL
#define GRANT__MAP_WRITE 0x00000002UL
#define RESOURCE__REMOVE_IOPORT 0x00000040UL
#define RESOURCE__ADD_IOMEM 0x00000080UL
#define RESOURCE__REMOVE_IOMEM 0x00000100UL
+#define RESOURCE__STAT_DEVICE 0x00000200UL
+#define RESOURCE__ADD_DEVICE 0x00000400UL
+#define RESOURCE__REMOVE_DEVICE 0x00000800UL
#define SECURITY__COMPUTE_AV 0x00000001UL
#define SECURITY__COMPUTE_CREATE 0x00000002UL
/* This file is automatically generated. Do not edit. */
-#ifndef _FLASK_FLASK_H_
-#define _FLASK_FLASK_H_
+#ifndef _SELINUX_FLASK_H_
+#define _SELINUX_FLASK_H_
/*
* Security object class definitions
#define SECINITSID_SECURITY 7
#define SECINITSID_IOPORT 8
#define SECINITSID_IOMEM 9
-#define SECINITSID_VCPU 10
-#define SECINITSID_VIRQ 11
-#define SECINITSID_PIRQ 12
+#define SECINITSID_PIRQ 10
+#define SECINITSID_DEVICE 11
-#define SECINITSID_NUM 12
+#define SECINITSID_NUM 11
#endif
"security",
"ioport",
"iomem",
- "vcpu",
- "virq",
"pirq",
+ "device",
};
int security_pirq_sid(int pirq, u32 *out_sid);
-int security_virq_sid(int virq, u32 *out_sid);
-
-int security_vcpu_sid(int vcpu, u32 *out_sid);
-
int security_iomem_sid(unsigned long, u32 *out_sid);
int security_ioport_sid(u32 ioport, u32 *out_sid);
+int security_device_sid(u32 device, u32 *out_sid);
+
int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid,
u16 tclass);
union {
char *name; /* name of initial SID, fs, netif, fstype, path */
int pirq;
- int virq;
- int vcpu;
u32 ioport;
unsigned long iomem;
+ u32 device;
} u;
struct context context[2]; /* security context(s) */
u32 sid[2]; /* SID(s) */
/* object context array indices */
#define OCON_ISID 0 /* initial SIDs */
#define OCON_PIRQ 1 /* physical irqs */
-#define OCON_VIRQ 2 /* virtual irqs */
-#define OCON_VCPU 3 /* virtual cpus */
-#define OCON_IOPORT 4 /* io ports */
-#define OCON_IOMEM 5 /* io memory */
-#define OCON_DUMMY 6
+#define OCON_IOPORT 2 /* io ports */
+#define OCON_IOMEM 3 /* io memory */
+#define OCON_DEVICE 4 /* pci devices */
+#define OCON_DUMMY1 5 /* reserved */
+#define OCON_DUMMY2 6 /* reserved */
#define OCON_NUM 7
/* The policy database */
return rc;
}
+/**
+ * security_ioport_sid - Obtain the SID for an ioport.
+ * @ioport: ioport
+ * @out_sid: security identifier
+ */
+int security_device_sid(u32 device, u32 *out_sid)
+{
+ struct ocontext *c;
+ int rc = 0;
+
+ POLICY_RDLOCK;
+
+ c = policydb.ocontexts[OCON_DEVICE];
+ while ( c )
+ {
+ if ( c->u.device == device )
+ break;
+ c = c->next;
+ }
+
+ if ( c )
+ {
+ if ( !c->sid[0] )
+ {
+ rc = sidtab_context_to_sid(&sidtab, &c->context[0], &c->sid[0]);
+ if ( rc )
+ goto out;
+ }
+ *out_sid = c->sid[0];
+ }
+ else
+ {
+ *out_sid = SECINITSID_DEVICE;
+ }
+
+out:
+ POLICY_RDUNLOCK;
+ return rc;
+}
+
#define SIDS_NEL 25
/**