@@ -35,7 +35,7 @@ long do_platform_op(XEN_GUEST_HANDLE_PARAM(xen_platform_op_t) u_xenpf_op)
if ( d == NULL )
return -ESRCH;
- ret = xsm_platform_op(XSM_PRIV, op->cmd);
+ ret = xsm_platform_op(XSM_HW_PRIV, op->cmd);
if ( ret )
return ret;
@@ -1355,7 +1355,7 @@ int pci_restore_msi_state(struct pci_dev *pdev)
if ( !use_msi )
return -EOPNOTSUPP;
- ret = xsm_resource_setup_pci(XSM_PRIV,
+ ret = xsm_resource_setup_pci(XSM_HW_PRIV,
(pdev->seg << 16) | (pdev->bus << 8) |
pdev->devfn);
if ( ret )
@@ -358,7 +358,7 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
ret = -EFAULT;
if ( copy_from_guest(&apic, arg, 1) != 0 )
break;
- ret = xsm_apic(XSM_PRIV, currd, cmd);
+ ret = xsm_apic(XSM_HW_PRIV, currd, cmd);
if ( ret )
break;
ret = ioapic_guest_read(apic.apic_physbase, apic.reg, &apic.value);
@@ -372,7 +372,7 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
ret = -EFAULT;
if ( copy_from_guest(&apic, arg, 1) != 0 )
break;
- ret = xsm_apic(XSM_PRIV, currd, cmd);
+ ret = xsm_apic(XSM_HW_PRIV, currd, cmd);
if ( ret )
break;
ret = ioapic_guest_write(apic.apic_physbase, apic.reg, apic.value);
@@ -388,7 +388,7 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
/* Use the APIC check since this dummy hypercall should still only
* be called by the domain with access to program the ioapic */
- ret = xsm_apic(XSM_PRIV, currd, cmd);
+ ret = xsm_apic(XSM_HW_PRIV, currd, cmd);
if ( ret )
break;
@@ -490,7 +490,7 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
if ( copy_from_guest(&dev, arg, 1) )
ret = -EFAULT;
else
- ret = xsm_resource_setup_pci(XSM_PRIV,
+ ret = xsm_resource_setup_pci(XSM_HW_PRIV,
(dev.seg << 16) | (dev.bus << 8) |
dev.devfn) ?:
pci_prepare_msix(dev.seg, dev.bus, dev.devfn,
@@ -501,7 +501,7 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
case PHYSDEVOP_pci_mmcfg_reserved: {
struct physdev_pci_mmcfg_reserved info;
- ret = xsm_resource_setup_misc(XSM_PRIV);
+ ret = xsm_resource_setup_misc(XSM_HW_PRIV);
if ( ret )
break;
@@ -567,7 +567,7 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
if ( setup_gsi.gsi < 0 || setup_gsi.gsi >= nr_irqs_gsi )
break;
- ret = xsm_resource_setup_gsi(XSM_PRIV, setup_gsi.gsi);
+ ret = xsm_resource_setup_gsi(XSM_HW_PRIV, setup_gsi.gsi);
if ( ret )
break;
@@ -228,7 +228,7 @@ ret_t do_platform_op(
if ( op->interface_version != XENPF_INTERFACE_VERSION )
return -EACCES;
- ret = xsm_platform_op(XSM_PRIV, op->cmd);
+ ret = xsm_platform_op(XSM_HW_PRIV, op->cmd);
if ( ret )
return ret;
@@ -678,7 +678,7 @@ int pci_add_device(u16 seg, u8 bus, u8 devfn,
else
type = "device";
- ret = xsm_resource_plug_pci(XSM_PRIV, (seg << 16) | (bus << 8) | devfn);
+ ret = xsm_resource_plug_pci(XSM_HW_PRIV, (seg << 16) | (bus << 8) | devfn);
if ( ret )
return ret;
@@ -830,7 +830,8 @@ int pci_remove_device(u16 seg, u8 bus, u8 devfn)
struct pci_dev *pdev;
int ret;
- ret = xsm_resource_unplug_pci(XSM_PRIV, (seg << 16) | (bus << 8) | devfn);
+ ret = xsm_resource_unplug_pci(XSM_HW_PRIV,
+ (seg << 16) | (bus << 8) | devfn);
if ( ret )
return ret;
@@ -86,7 +86,7 @@ ret_t pci_physdev_op(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
dev_reset.dev.bus,
dev_reset.dev.devfn);
- ret = xsm_resource_setup_pci(XSM_PRIV, sbdf.sbdf);
+ ret = xsm_resource_setup_pci(XSM_HW_PRIV, sbdf.sbdf);
if ( ret )
break;
@@ -95,7 +95,11 @@ static always_inline int xsm_default_action(
return 0;
fallthrough;
case XSM_PRIV:
- if ( is_control_domain(src) )
+ case XSM_HW_PRIV:
+ if ( is_control_domain(src) && action != XSM_HW_PRIV )
+ return 0;
+ if ( is_hardware_domain(src) &&
+ (action == XSM_HW_PRIV || action == XSM_DM_PRIV) )
return 0;
return -EPERM;
default:
@@ -280,7 +284,7 @@ static XSM_INLINE int cf_check xsm_console_io(
if ( cmd == CONSOLEIO_write )
return xsm_default_action(XSM_HOOK, d, NULL);
#endif
- return xsm_default_action(XSM_PRIV, d, NULL);
+ return xsm_default_action(XSM_HW_PRIV, d, NULL);
}
static XSM_INLINE int cf_check xsm_profile(
@@ -460,33 +464,33 @@ static XSM_INLINE int cf_check xsm_resource_unplug_core(XSM_DEFAULT_VOID)
static XSM_INLINE int cf_check xsm_resource_plug_pci(
XSM_DEFAULT_ARG uint32_t machine_bdf)
{
- XSM_ASSERT_ACTION(XSM_PRIV);
+ XSM_ASSERT_ACTION(XSM_HW_PRIV);
return xsm_default_action(action, current->domain, NULL);
}
static XSM_INLINE int cf_check xsm_resource_unplug_pci(
XSM_DEFAULT_ARG uint32_t machine_bdf)
{
- XSM_ASSERT_ACTION(XSM_PRIV);
+ XSM_ASSERT_ACTION(XSM_HW_PRIV);
return xsm_default_action(action, current->domain, NULL);
}
static XSM_INLINE int cf_check xsm_resource_setup_pci(
XSM_DEFAULT_ARG uint32_t machine_bdf)
{
- XSM_ASSERT_ACTION(XSM_PRIV);
+ XSM_ASSERT_ACTION(XSM_HW_PRIV);
return xsm_default_action(action, current->domain, NULL);
}
static XSM_INLINE int cf_check xsm_resource_setup_gsi(XSM_DEFAULT_ARG int gsi)
{
- XSM_ASSERT_ACTION(XSM_PRIV);
+ XSM_ASSERT_ACTION(XSM_HW_PRIV);
return xsm_default_action(action, current->domain, NULL);
}
static XSM_INLINE int cf_check xsm_resource_setup_misc(XSM_DEFAULT_VOID)
{
- XSM_ASSERT_ACTION(XSM_PRIV);
+ XSM_ASSERT_ACTION(XSM_HW_PRIV);
return xsm_default_action(action, current->domain, NULL);
}
@@ -688,7 +692,7 @@ static XSM_INLINE int cf_check xsm_mem_sharing(XSM_DEFAULT_ARG struct domain *d)
static XSM_INLINE int cf_check xsm_platform_op(XSM_DEFAULT_ARG uint32_t op)
{
- XSM_ASSERT_ACTION(XSM_PRIV);
+ XSM_ASSERT_ACTION(XSM_HW_PRIV);
return xsm_default_action(action, current->domain, NULL);
}
@@ -716,7 +720,7 @@ static XSM_INLINE int cf_check xsm_mem_sharing_op(
static XSM_INLINE int cf_check xsm_apic(
XSM_DEFAULT_ARG struct domain *d, int cmd)
{
- XSM_ASSERT_ACTION(XSM_PRIV);
+ XSM_ASSERT_ACTION(XSM_HW_PRIV);
return xsm_default_action(action, d, NULL);
}
@@ -36,6 +36,7 @@ enum xsm_default {
XSM_DM_PRIV, /* Device model can perform on its target domain */
XSM_TARGET, /* Can perform on self or your target domain */
XSM_PRIV, /* Privileged - normally restricted to dom0 */
+ XSM_HW_PRIV, /* Hardware Privileged - normally restricted to dom0/hwdom */
XSM_XS_PRIV, /* Xenstore domain - can do some privileged operations */
XSM_OTHER /* Something more complex */
};
Xen includes disctinct concepts of a control domain (privileged) and a hardware domain, but there is only a single XSM_PRIV check. For dom0 this is not an issue as they are one and the same. With hyperlaunch and its build capabiliies, a non-privileged hwdom and a privileged control domain should be possible. Today the hwdom fails the XSM_PRIV checks for hardware-related hooks which it should be allowed access to. Introduce XSM_HW_PRIV, and use it to mark many of the physdev_op and platform_op. Previously, xsm_default_action() was almost linearly increasing in permissions with its fallthroughs. When it gets to XSM_PRIV, all permissions were allowed for the control domain. That needs to change so the control domain cannot access XSM_HW_PRIV. The hwdom is allowed access for XSM_HW_PRIV and XSM_DM_PRIV. The hardware domain providing a device model for a domU is an expected use case, so those permission are needed as well. Testing was performed with hardware+xenstore capabilities for dom0 and a control dom3 booted from hyperlaunch. The additional xenstore permissions allowed hwdom+xenstore XSM_XS_PRIV which are necesary for xenstore. A traditional dom0 will be both privileged and hardware domain, so it continues to have all accesses. Why not XSM:Flask? XSM:Flask is fine grain, and this aims to allow coarse grain. domUs are still domUs. If capabilities are meant to be a first class citizen, they should be usable by the default XSM policy. Signed-off-by: Jason Andryuk <jason.andryuk@amd.com> --- xen/arch/arm/platform_hypercall.c | 2 +- xen/arch/x86/msi.c | 2 +- xen/arch/x86/physdev.c | 12 ++++++------ xen/arch/x86/platform_hypercall.c | 2 +- xen/drivers/passthrough/pci.c | 5 +++-- xen/drivers/pci/physdev.c | 2 +- xen/include/xsm/dummy.h | 22 +++++++++++++--------- xen/include/xsm/xsm.h | 1 + 8 files changed, 27 insertions(+), 21 deletions(-)