mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
mem_sharing: allow forking domain with IOMMU enabled
The memory sharing subsystem by default doesn't allow a domain to share memory if it has an IOMMU active for obvious security reasons. However, when fuzzing a VM fork, the same security restrictions don't necessarily apply. While it makes no sense to try to create a full fork of a VM that has an IOMMU attached as only one domain can own the pass-through device at a time, creating a shallow fork without a device model is still very useful for fuzzing kernel-mode drivers. By allowing the parent VM to initialize the kernel-mode driver with a real device that's pass-through, the driver can enter into a state more suitable for fuzzing. Some of these initialization steps are quite complex and are easier to perform when a real device is present. After the initialization, shallow forks can be utilized for fuzzing code-segments in the device driver that don't directly interact with the device. Signed-off-by: Tamas K Lengyel <tamas.lengyel@intel.com> Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
This commit is contained in:
1 parent
732571959f
commit
bb215898d4
2 files changed
+16
-8
No files matched your search
@@ -1430,7 +1430,8 @@ static int range_share(struct domain *d, struct domain *cd,
|
||||
return rc;
|
||||
}
|
||||
|
||||
static inline int mem_sharing_control(struct domain *d, bool enable)
|
||||
static inline int mem_sharing_control(struct domain *d, bool enable,
|
||||
uint16_t flags)
|
||||
{
|
||||
if ( enable )
|
||||
{
|
||||
@@ -1440,7 +1441,8 @@ static inline int mem_sharing_control(struct domain *d, bool enable)
|
||||
if ( unlikely(!hap_enabled(d)) )
|
||||
return -ENODEV;
|
||||
|
||||
if ( unlikely(is_iommu_enabled(d)) )
|
||||
if ( unlikely(is_iommu_enabled(d) &&
|
||||
!(flags & XENMEM_FORK_WITH_IOMMU_ALLOWED)) )
|
||||
return -EXDEV;
|
||||
}
|
||||
|
||||
@@ -1827,7 +1829,8 @@ int mem_sharing_memop(XEN_GUEST_HANDLE_PARAM(xen_mem_sharing_op_t) arg)
|
||||
if ( rc )
|
||||
goto out;
|
||||
|
||||
if ( !mem_sharing_enabled(d) && (rc = mem_sharing_control(d, true)) )
|
||||
if ( !mem_sharing_enabled(d) &&
|
||||
(rc = mem_sharing_control(d, true, 0)) )
|
||||
return rc;
|
||||
|
||||
switch ( mso.op )
|
||||
@@ -2065,7 +2068,9 @@ int mem_sharing_memop(XEN_GUEST_HANDLE_PARAM(xen_mem_sharing_op_t) arg)
|
||||
struct domain *pd;
|
||||
|
||||
rc = -EINVAL;
|
||||
if ( mso.u.fork.pad[0] || mso.u.fork.pad[1] || mso.u.fork.pad[2] )
|
||||
if ( mso.u.fork.pad )
|
||||
goto out;
|
||||
if ( mso.u.fork.flags & ~XENMEM_FORK_WITH_IOMMU_ALLOWED )
|
||||
goto out;
|
||||
|
||||
rc = rcu_lock_live_remote_domain_by_id(mso.u.fork.parent_domain,
|
||||
@@ -2080,7 +2085,8 @@ int mem_sharing_memop(XEN_GUEST_HANDLE_PARAM(xen_mem_sharing_op_t) arg)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ( !mem_sharing_enabled(pd) && (rc = mem_sharing_control(pd, true)) )
|
||||
if ( !mem_sharing_enabled(pd) &&
|
||||
(rc = mem_sharing_control(pd, true, mso.u.fork.flags)) )
|
||||
{
|
||||
rcu_unlock_domain(pd);
|
||||
goto out;
|
||||
@@ -2101,7 +2107,7 @@ int mem_sharing_memop(XEN_GUEST_HANDLE_PARAM(xen_mem_sharing_op_t) arg)
|
||||
struct domain *pd;
|
||||
|
||||
rc = -EINVAL;
|
||||
if ( mso.u.fork.pad[0] || mso.u.fork.pad[1] || mso.u.fork.pad[2] )
|
||||
if ( mso.u.fork.pad || mso.u.fork.flags )
|
||||
goto out;
|
||||
|
||||
rc = -ENOSYS;
|
||||
@@ -2138,7 +2144,7 @@ int mem_sharing_domctl(struct domain *d, struct xen_domctl_mem_sharing_op *mec)
|
||||
switch ( mec->op )
|
||||
{
|
||||
case XEN_DOMCTL_MEM_SHARING_CONTROL:
|
||||
rc = mem_sharing_control(d, mec->u.enable);
|
||||
rc = mem_sharing_control(d, mec->u.enable, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
@@ -536,7 +536,9 @@ struct xen_mem_sharing_op {
|
||||
} debug;
|
||||
struct mem_sharing_op_fork { /* OP_FORK */
|
||||
domid_t parent_domain; /* IN: parent's domain id */
|
||||
uint16_t pad[3]; /* Must be set to 0 */
|
||||
#define XENMEM_FORK_WITH_IOMMU_ALLOWED (1u << 0)
|
||||
uint16_t flags; /* IN: optional settings */
|
||||
uint32_t pad; /* Must be set to 0 */
|
||||
} fork;
|
||||
} u;
|
||||
};
|
||||
|
||||