On Wed, May 08, 2019 at 05:44:05PM +0300, Kirill A. Shutemov wrote: > @@ -347,7 +348,8 @@ static int prot_none_walk(struct vm_area_struct *vma, unsigned long start, > > int > mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev, > - unsigned long start, unsigned long end, unsigned long newflags) > + unsigned long start, unsigned long end, unsigned long newflags, > + int newkeyid) > { > struct mm_struct *mm = vma->vm_mm; > unsigned long oldflags = vma->vm_flags; > @@ -357,7 +359,14 @@ mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev, > int error; > int dirty_accountable = 0; > > - if (newflags == oldflags) { > + /* > + * Flags match and Keyids match or we have NO_KEY. > + * This _fixup is usually called from do_mprotect_ext() except > + * for one special case: caller fs/exec.c/setup_arg_pages() > + * In that case, newkeyid is passed as -1 (NO_KEY). > + */ > + if (newflags == oldflags && > + (newkeyid == vma_keyid(vma) || newkeyid == NO_KEY)) { > *pprev = vma; > return 0; > } > @@ -423,6 +432,8 @@ mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev, > } > > success: > + if (newkeyid != NO_KEY) > + mprotect_set_encrypt(vma, newkeyid, start, end); > /* > * vm_flags and vm_page_prot are protected by the mmap_sem > * held in write mode. > @@ -454,10 +465,15 @@ mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev, > } > > /* > - * When pkey==NO_KEY we get legacy mprotect behavior here. > + * do_mprotect_ext() supports the legacy mprotect behavior plus extensions > + * for Protection Keys and Memory Encryption Keys. These extensions are > + * mutually exclusive and the behavior is: > + * (pkey==NO_KEY && keyid==NO_KEY) ==> legacy mprotect > + * (pkey is valid) ==> legacy mprotect plus Protection Key extensions > + * (keyid is valid) ==> legacy mprotect plus Encryption Key extensions > */ > static int do_mprotect_ext(unsigned long start, size_t len, > - unsigned long prot, int pkey) > + unsigned long prot, int pkey, int keyid) > { > unsigned long nstart, end, tmp, reqprot; > struct vm_area_struct *vma, *prev; > @@ -555,7 +571,8 @@ static int do_mprotect_ext(unsigned long start, size_t len, > tmp = vma->vm_end; > if (tmp > end) > tmp = end; > - error = mprotect_fixup(vma, &prev, nstart, tmp, newflags); > + error = mprotect_fixup(vma, &prev, nstart, tmp, newflags, > + keyid); > if (error) > goto out; > nstart = tmp; I've missed the part where pkey && keyid results in a WARN or error or whatever.