[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v4] x86/mm: Add mem access rights to NPT
[Resending] On Wed, Sep 26, 2018 at 5:02 PM George Dunlap <George.Dunlap@xxxxxxxxxxxxx> wrote: > > On Mon, Jul 23, 2018 at 2:48 PM Alexandru Isaila > <aisaila@xxxxxxxxxxxxxxx> wrote: > > > > From: Isaila Alexandru <aisaila@xxxxxxxxxxxxxxx> > > > > This patch adds access control for NPT mode. > > > > There aren’t enough extra bits to store the access rights in the NPT p2m > > table, so we add a radix tree to store the rights. For efficiency, > > remove entries which match the default permissions rather than > > continuing to store them. > > > > Modify p2m-pt.c:p2m_type_to_flags() to mirror the ept version: taking an > > access, and removing / adding RW or NX flags as appropriate. > > > > Note: It was tested with xen-access write > > > > Signed-off-by: Alexandru Isaila <aisaila@xxxxxxxxxxxxxxx> > > > > --- > > Changes since V3: > > - Add p2m_pt_check_access() to filter n, w, wx, n2rwx from > > supported page rights > > - Add rights check for the default_access change in the > > IVALID_GFN case > > - Add blank lines > > - Remove cpu_has_svm if from p2m_mem_access_check() > > - Add xfree(msr_bitmap) in case of error on > > xalloc(raxid_tree_root). > > --- > > xen/arch/x86/mm/mem_access.c | 17 +++--- > > xen/arch/x86/mm/p2m-ept.c | 7 +++ > > xen/arch/x86/mm/p2m-pt.c | 124 > > ++++++++++++++++++++++++++++++++++----- > > xen/arch/x86/mm/p2m.c | 6 ++ > > xen/arch/x86/monitor.c | 15 +++++ > > xen/include/asm-x86/mem_access.h | 2 +- > > xen/include/asm-x86/p2m.h | 7 +++ > > 7 files changed, 156 insertions(+), 22 deletions(-) > > > > diff --git a/xen/arch/x86/mm/mem_access.c b/xen/arch/x86/mm/mem_access.c > > index c0cd017..cab72bc 100644 > > --- a/xen/arch/x86/mm/mem_access.c > > +++ b/xen/arch/x86/mm/mem_access.c > > @@ -221,12 +221,12 @@ bool p2m_mem_access_check(paddr_t gpa, unsigned long > > gla, > > { > > req->u.mem_access.flags |= MEM_ACCESS_GLA_VALID; > > req->u.mem_access.gla = gla; > > - > > - if ( npfec.kind == npfec_kind_with_gla ) > > - req->u.mem_access.flags |= MEM_ACCESS_FAULT_WITH_GLA; > > - else if ( npfec.kind == npfec_kind_in_gpt ) > > - req->u.mem_access.flags |= MEM_ACCESS_FAULT_IN_GPT; > > } > > + > > + if ( npfec.kind == npfec_kind_with_gla ) > > + req->u.mem_access.flags |= MEM_ACCESS_FAULT_WITH_GLA; > > + else if ( npfec.kind == npfec_kind_in_gpt ) > > + req->u.mem_access.flags |= MEM_ACCESS_FAULT_IN_GPT; > > req->u.mem_access.flags |= npfec.read_access ? MEM_ACCESS_R : 0; > > req->u.mem_access.flags |= npfec.write_access ? MEM_ACCESS_W : 0; > > req->u.mem_access.flags |= npfec.insn_fetch ? MEM_ACCESS_X : 0; > > @@ -366,8 +366,11 @@ long p2m_set_mem_access(struct domain *d, gfn_t gfn, > > uint32_t nr, > > /* If request to set default access. */ > > if ( gfn_eq(gfn, INVALID_GFN) ) > > { > > - p2m->default_access = a; > > - return 0; > > + if ( (rc = p2m->check_access(a)) == 0 ) > > + { > > + p2m->default_access = a; > > + return 0; > > + } > > } > > BTW this introduces a bug -- if the check fails, this will fall > through into the gfn loop below, rather than returning the error. > > > @@ -87,23 +88,27 @@ static unsigned long p2m_type_to_flags(const struct > > p2m_domain *p2m, > > case p2m_ram_paged: > > case p2m_ram_paging_in: > > default: > > - return flags | _PAGE_NX_BIT; > > + flags |= P2M_BASE_FLAGS | _PAGE_NX_BIT; > > + break; > > Why did you add in P2M_BASE_FLAGS here? > > > case p2m_grant_map_ro: > > return flags | P2M_BASE_FLAGS | _PAGE_NX_BIT; > > And is this `return` left here on purpose, or was it missed? > > > /* Returns: 0 for success, -errno for failure */ > > static int > > p2m_next_level(struct p2m_domain *p2m, void **table, > > @@ -201,6 +268,7 @@ p2m_next_level(struct p2m_domain *p2m, void **table, > > new_entry = l1e_from_mfn(mfn, P2M_BASE_FLAGS | _PAGE_RW); > > > > p2m_add_iommu_flags(&new_entry, level, > > IOMMUF_readable|IOMMUF_writable); > > + p2m_set_access(p2m, gfn, p2m->default_access); > > This is clearly wrong -- this isn't a leaf node, it's an intermediate > p2m table; and p2m_next_level() is just acting "under the covers", > filling in missing bits of the p2m table or breaking down superpages. > Since the access information is in a completely separate structure, it > shouldn't need to be modified here at all (indeed, it would be a bug > to do so). > > But that does bring up an important issue -- it would appear that this > code is incorrect when setting superpages -- if we set a 2MiB page but > then read a non-2MiB-aligned entry within that page, we'll get the > default access rather than the one we set; same thing with splintering > a superpage into smaller pages. > > There's a draft patch addressing this on the way. > > -George _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |