[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH v2] x86/mm: Add mem access rights to NPT



On 22.08.2019 16:02, Alexandru Stefan ISAILA wrote:
> This patch adds access control for NPT mode.
> 
> The access rights are stored in the NPT p2m table 56:53.

Why starting from bit 53? I can't seem to find any use of bit 52.

> The bits are free after clearing the IOMMU flags [1].
> 
> Modify p2m_type_to_flags() to accept and interpret an access value,
> parallel to the ept code.
> 
> Add a set_default_access() method to the p2m-pt and p2m-ept versions
> of the p2m rather than setting it directly, to deal with different
> default permitted access values.

I think this would better be a separate change.

> --- a/xen/arch/x86/mm/p2m-pt.c
> +++ b/xen/arch/x86/mm/p2m-pt.c
> @@ -63,10 +63,13 @@
>  #define needs_recalc(level, ent) _needs_recalc(level##e_get_flags(ent))
>  #define valid_recalc(level, ent) (!(level##e_get_flags(ent) & 
> _PAGE_ACCESSED))
>  
> +#define _PAGE_ACCESS_BITS  (0x1e00) /* mem_access rights 16:13 */

I guess this is too disconnected from the two page.h headers where
the correlation between bit positions gets explained, so I guess
you want to extend the comment and either refer there, or replicate
some of it to make understandable why 16:13 matches 56:53.

I'm also concerned how easy it'll be for someone to find this
definition when wanting to use other of the available bits.

> @@ -104,8 +112,32 @@ static unsigned long p2m_type_to_flags(const struct 
> p2m_domain *p2m,
>              flags |= _PAGE_PWT;
>              ASSERT(!level);
>          }
> -        return flags | P2M_BASE_FLAGS | _PAGE_PCD;
> +        flags |= P2M_BASE_FLAGS | _PAGE_PCD;
> +        break;
>      }
> +
> +    switch ( access )
> +    {
> +    case p2m_access_r:
> +        flags |= _PAGE_NX_BIT;
> +        flags &= ~_PAGE_RW;
> +        break;
> +    case p2m_access_rw:
> +        flags |= _PAGE_NX_BIT;
> +        break;
> +    case p2m_access_rx:
> +    case p2m_access_rx2rw:
> +        flags &= ~(_PAGE_NX_BIT | _PAGE_RW);
> +        break;
> +    case p2m_access_x:
> +        flags &= ~_PAGE_RW;
> +        break;

I can't seem to be able to follow you here. In fact I don't see
how you would be able to express execute-only with NPT. If this
is really needed for some reason, then a justifying comment
should be added.

> @@ -152,6 +184,17 @@ p2m_free_entry(struct p2m_domain *p2m, l1_pgentry_t 
> *p2m_entry, int page_order)
>      p2m_free_ptp(p2m, l1e_get_page(*p2m_entry));
>  }
>  
> +static void p2m_set_access(intpte_t *entry, p2m_access_t access)
> +{
> +    *entry |= put_pte_flags((get_pte_flags(*entry) & ~_PAGE_ACCESS_BITS) |
> +                            (MASK_INSR(access, _PAGE_ACCESS_BITS)));
> +}
> +
> +static p2m_access_t p2m_get_access(intpte_t entry)
> +{
> +    return (p2m_access_t)(MASK_EXTR(get_pte_flags(entry), 
> _PAGE_ACCESS_BITS));

Is the cast really needed here?

> @@ -226,6 +269,7 @@ p2m_next_level(struct p2m_domain *p2m, void **table,
>          {
>              new_entry = l1e_from_pfn(pfn | (i << ((level - 1) * 
> PAGETABLE_ORDER)),
>                                       flags);
> +            p2m_set_access(&new_entry.l1, p2m->default_access);
>              rc = p2m->write_p2m_entry(p2m, gfn, l1_entry + i, new_entry, 
> level);
>              if ( rc )
>              {
> @@ -237,6 +281,7 @@ p2m_next_level(struct p2m_domain *p2m, void **table,
>          unmap_domain_page(l1_entry);
>  
>          new_entry = l1e_from_mfn(mfn, P2M_BASE_FLAGS | _PAGE_RW);
> +        p2m_set_access(&new_entry.l1, p2m->default_access);
>          rc = p2m->write_p2m_entry(p2m, gfn, p2m_entry, new_entry,
>                                    level + 1);
>          if ( rc )

Is it really intended to insert the access bits also into non-leaf
entries (which may be what is being processed here)? (May also
apply further down.)

> @@ -474,6 +520,32 @@ int p2m_pt_handle_deferred_changes(uint64_t gpa)
>      return rc;
>  }
>  
> +static int p2m_pt_check_access(p2m_access_t p2ma)
> +{
> +    switch ( p2ma )
> +    {
> +    case p2m_access_n:
> +    case p2m_access_w:
> +    case p2m_access_wx:
> +    case p2m_access_n2rwx:
> +        return -EINVAL;

I'm not convinced EINVAL is appropriate here - the argument isn't
invalid, it's just that there's no way to represent it.

Jan

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.