[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v15 2/3] mem_sharing: allow forking domain with IOMMU enabled
On Mon, Apr 20, 2020 at 1:57 AM Roger Pau Monné <roger.pau@xxxxxxxxxx> wrote: > > On Fri, Apr 17, 2020 at 10:06:32AM -0700, Tamas K Lengyel wrote: > > 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 > ^ passed > > 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. > > If I understand this correctly, the forked VM won't have an IOMMU > setup, and the only domain allowed to interact with the device would > be the parent? Correct, this mode would only be for forks that have no access to devices at all (--launch-dm no). > > > > > Signed-off-by: Tamas K Lengyel <tamas.lengyel@xxxxxxxxx> > > --- > > xen/arch/x86/mm/mem_sharing.c | 18 ++++++++++++------ > > xen/include/public/memory.h | 4 +++- > > 2 files changed, 15 insertions(+), 7 deletions(-) > > > > diff --git a/xen/arch/x86/mm/mem_sharing.c b/xen/arch/x86/mm/mem_sharing.c > > index 4b31a8b8f6..a5063d5992 100644 > > --- a/xen/arch/x86/mm/mem_sharing.c > > +++ b/xen/arch/x86/mm/mem_sharing.c > > @@ -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, > > + bool allow_iommu) > > { > > if ( enable ) > > { > > @@ -1440,7 +1441,7 @@ 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(!allow_iommu && is_iommu_enabled(d)) ) > > Coding style (missing space) Ack > > > return -EXDEV; > > } > > > > @@ -1827,7 +1828,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, false)) ) > > return rc; > > > > switch ( mso.op ) > > @@ -2063,9 +2065,10 @@ int > > mem_sharing_memop(XEN_GUEST_HANDLE_PARAM(xen_mem_sharing_op_t) arg) > > case XENMEM_sharing_op_fork: > > { > > struct domain *pd; > > + bool allow_iommu; > > > > rc = -EINVAL; > > - if ( mso.u.fork.pad[0] || mso.u.fork.pad[1] || mso.u.fork.pad[2] ) > > + if ( mso.u.fork.pad[0] || mso.u.fork.pad[1] ) > > goto out; > > > > rc = rcu_lock_live_remote_domain_by_id(mso.u.fork.parent_domain, > > @@ -2080,7 +2083,10 @@ 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)) ) > > + allow_iommu = mso.u.fork.flags & XENMEM_FORK_WITH_IOMMU_ALLOWED; > > I'm not sure whether it is worth to extract the flags into booleans at > this level. As you add more flags it might make sense to just pass the > whole flags field to mem_sharing_control? Sure. > > mem_sharing_memop itself doesn't need to know which flags are > specified. > > > + > > + if ( !mem_sharing_enabled(pd) && > > + (rc = mem_sharing_control(pd, true, allow_iommu)) ) > > { > > rcu_unlock_domain(pd); > > goto out; > > @@ -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, false); > > break; > > > > default: > > diff --git a/xen/include/public/memory.h b/xen/include/public/memory.h > > index d36d64b8dc..1d2149def3 100644 > > --- a/xen/include/public/memory.h > > +++ b/xen/include/public/memory.h > > @@ -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 1 /* Allow forking domain with > > IOMMU */ > > Since this is a flags field, can you express this is as: (1u << 0). I was thinking of doing that then it won't fit into a single line. For this particular flag it would also make no difference. > > > + uint16_t flags; /* IN: optional settings */ > > + uint16_t pad[2]; /* Must be set to 0 */ > > Nit: padding can be made a uint32_t now instead of an array of two > uint16_t. > > Or add an uint16_t between parent_domain and flags and make flags an > uint32_t. True. Thanks, Tamas
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |