Re: [PATCH v8 11/27] x86/mm: Introduce _PAGE_DIRTY_SW

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

 



> +#if defined(CONFIG_X86_INTEL_SHADOW_STACK_USER)
> +static inline pte_t pte_move_flags(pte_t pte, pteval_t from, pteval_t to)
> +{
> +	if (pte_flags(pte) & from)
> +		pte = pte_set_flags(pte_clear_flags(pte, from), to);
> +	return pte;

Why is this conditional on the compile option and not a runtime check?

> +}
> +#else
> +static inline pte_t pte_move_flags(pte_t pte, pteval_t from, pteval_t to)
> +{
> +	return pte;
> +}
> +#endif

Why do we need this function?  It's not mentioned in the changelog or
commented.

>  static inline pte_t pte_mkclean(pte_t pte)
>  {
> -	return pte_clear_flags(pte, _PAGE_DIRTY);
> +	return pte_clear_flags(pte, _PAGE_DIRTY_BITS);
>  }
>  
>  static inline pte_t pte_mkold(pte_t pte)
> @@ -322,6 +336,7 @@ static inline pte_t pte_mkold(pte_t pte)
>  
>  static inline pte_t pte_wrprotect(pte_t pte)
>  {
> +	pte = pte_move_flags(pte, _PAGE_DIRTY_HW, _PAGE_DIRTY_SW);
>  	return pte_clear_flags(pte, _PAGE_RW);
>  }

Please comment what this is doing and why.

> @@ -332,9 +347,24 @@ static inline pte_t pte_mkexec(pte_t pte)
>  
>  static inline pte_t pte_mkdirty(pte_t pte)
>  {
> +	pteval_t dirty = (!IS_ENABLED(CONFIG_X86_INTEL_SHADOW_STACK_USER) ||
> +			   pte_write(pte)) ? _PAGE_DIRTY_HW:_PAGE_DIRTY_SW;

This is *really* hard for me to read and parse.  How about:

	pte_t dirty = _PAGE_DIRTY_HW;

	/*
	 * When Shadow Stacks are enabled, read-only PTEs can
	 * not have the hardware dirty bit set and must use
	 * the software bit.
	 */
	if (IS_ENABLED(CONFIG_X86_INTEL_SHADOW_STACK_USER) &&
	    !pte_write(pte))
		dirty = _PAGE_DIRTY_SW;


> +	return pte_set_flags(pte, dirty | _PAGE_SOFT_DIRTY);
> +}
> +
> +#ifdef CONFIG_ARCH_HAS_SHSTK
> +static inline pte_t pte_mkdirty_shstk(pte_t pte)
> +{
> +	pte = pte_clear_flags(pte, _PAGE_DIRTY_SW);
>  	return pte_set_flags(pte, _PAGE_DIRTY_HW | _PAGE_SOFT_DIRTY);
>  }

Why does the _PAGE_DIRTY_SW *HAVE* to be cleared on shstk pages?

> +static inline bool pte_dirty_hw(pte_t pte)
> +{
> +	return pte_flags(pte) & _PAGE_DIRTY_HW;
> +}
> +#endif

Why are these #ifdef'd?

>  static inline pte_t pte_mkyoung(pte_t pte)
>  {
>  	return pte_set_flags(pte, _PAGE_ACCESSED);
> @@ -342,6 +372,7 @@ static inline pte_t pte_mkyoung(pte_t pte)
>  
>  static inline pte_t pte_mkwrite(pte_t pte)
>  {
> +	pte = pte_move_flags(pte, _PAGE_DIRTY_SW, _PAGE_DIRTY_HW);
>  	return pte_set_flags(pte, _PAGE_RW);
>  }

It also isn't clear to me why this *must* move bits here.  Its doubly
unclear why you would need to do this on systems when shadow stacks are
compiled in but disabled.

<snip>

Same comments for pmds and puds.

> -
>  /* mprotect needs to preserve PAT bits when updating vm_page_prot */
>  #define pgprot_modify pgprot_modify
>  static inline pgprot_t pgprot_modify(pgprot_t oldprot, pgprot_t newprot)
> @@ -1178,6 +1254,19 @@ static inline int pmd_write(pmd_t pmd)
>  	return pmd_flags(pmd) & _PAGE_RW;
>  }
>  
> +static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
> +{
> +	pmdval_t val = pmd_val(pmd), oldval = val;
> +
> +	val &= _HPAGE_CHG_MASK;
> +	val |= check_pgprot(newprot) & ~_HPAGE_CHG_MASK;
> +	val = flip_protnone_guard(oldval, val, PHYSICAL_PMD_PAGE_MASK);
> +	if ((pmd_write(pmd) && !(pgprot_val(newprot) & _PAGE_RW)))
> +		return pmd_move_flags(__pmd(val), _PAGE_DIRTY_HW,
> +				      _PAGE_DIRTY_SW);
> +	return __pmd(val);
> +}

Why was this function moved?  This makes it really hard to review what
you changed

I'm going to stop reading this code now.  It needs a lot more care and
feeding to make it reviewable.  Please go back, double-check your
changelogs and flesh them out, then please try to make the code more
readable and understandable by commenting it.

Please take all of the compile-time checks and ask yourself whether they
need to be or *can* be runtime checks.  Consider what the overhead is of
non-shadowstack systems running shadowstack-required code.

Please also reconcile the supervisor XSAVE portion of your patches with
the ones that Fenghua has been sending around.  I've given quite a bit
of feedback to improve those.  Please consolidate and agree on a common
set of patches with him.



[Index of Archives]     [Linux Kernel]     [Kernel Newbies]     [x86 Platform Driver]     [Netdev]     [Linux Wireless]     [Netfilter]     [Bugtraq]     [Linux Filesystems]     [Yosemite Discussion]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Device Mapper]

  Powered by Linux