2020-07-16 13:59:05

by Jarkko Sakkinen

[permalink] [raw]
Subject: [PATCH v36 10/24] mm: Add vm_ops->mprotect()

From: Sean Christopherson <[email protected]>

Add vm_ops()->mprotect() for additional constraints for a VMA.

Intel Software Guard eXtensions (SGX) will use this callback to add two
constraints:

1. Verify that the address range does not have holes: each page address
must be filled with an enclave page.
2. Verify that VMA permissions won't surpass the permissions of any enclave
page within the address range. Enclave cryptographically sealed
permissions for each page address that set the upper limit for possible
VMA permissions. Not respecting this can cause #GP's to be emitted.

Cc: [email protected]
Cc: Andrew Morton <[email protected]>
Cc: Matthew Wilcox <[email protected]>
Acked-by: Jethro Beekman <[email protected]>
Signed-off-by: Sean Christopherson <[email protected]>
Co-developed-by: Jarkko Sakkinen <[email protected]>
Signed-off-by: Jarkko Sakkinen <[email protected]>
---
include/linux/mm.h | 3 +++
mm/mprotect.c | 5 ++++-
2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/include/linux/mm.h b/include/linux/mm.h
index dc7b87310c10..458e8cb99aaf 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -542,6 +542,9 @@ struct vm_operations_struct {
void (*close)(struct vm_area_struct * area);
int (*split)(struct vm_area_struct * area, unsigned long addr);
int (*mremap)(struct vm_area_struct * area);
+ int (*mprotect)(struct vm_area_struct *vma,
+ struct vm_area_struct **pprev, unsigned long start,
+ unsigned long end, unsigned long newflags);
vm_fault_t (*fault)(struct vm_fault *vmf);
vm_fault_t (*huge_fault)(struct vm_fault *vmf,
enum page_entry_size pe_size);
diff --git a/mm/mprotect.c b/mm/mprotect.c
index ce8b8a5eacbb..f170f3da8a4f 100644
--- a/mm/mprotect.c
+++ b/mm/mprotect.c
@@ -610,7 +610,10 @@ static int do_mprotect_pkey(unsigned long start, size_t len,
tmp = vma->vm_end;
if (tmp > end)
tmp = end;
- error = mprotect_fixup(vma, &prev, nstart, tmp, newflags);
+ if (vma->vm_ops && vma->vm_ops->mprotect)
+ error = vma->vm_ops->mprotect(vma, &prev, nstart, tmp, newflags);
+ else
+ error = mprotect_fixup(vma, &prev, nstart, tmp, newflags);
if (error)
goto out;
nstart = tmp;
--
2.25.1


2020-08-06 16:38:58

by Darren Kenny

[permalink] [raw]
Subject: Re: [PATCH v36 10/24] mm: Add vm_ops->mprotect()

On Thursday, 2020-07-16 at 16:52:49 +03, Jarkko Sakkinen wrote:
> From: Sean Christopherson <[email protected]>
>
> Add vm_ops()->mprotect() for additional constraints for a VMA.
>
> Intel Software Guard eXtensions (SGX) will use this callback to add two
> constraints:
>
> 1. Verify that the address range does not have holes: each page address
> must be filled with an enclave page.
> 2. Verify that VMA permissions won't surpass the permissions of any enclave
> page within the address range. Enclave cryptographically sealed
> permissions for each page address that set the upper limit for possible
> VMA permissions. Not respecting this can cause #GP's to be emitted.
>
> Cc: [email protected]
> Cc: Andrew Morton <[email protected]>
> Cc: Matthew Wilcox <[email protected]>
> Acked-by: Jethro Beekman <[email protected]>
> Signed-off-by: Sean Christopherson <[email protected]>
> Co-developed-by: Jarkko Sakkinen <[email protected]>
> Signed-off-by: Jarkko Sakkinen <[email protected]>

Reviewed-by: Darren Kenny <[email protected]>

> ---
> include/linux/mm.h | 3 +++
> mm/mprotect.c | 5 ++++-
> 2 files changed, 7 insertions(+), 1 deletion(-)
>
> diff --git a/include/linux/mm.h b/include/linux/mm.h
> index dc7b87310c10..458e8cb99aaf 100644
> --- a/include/linux/mm.h
> +++ b/include/linux/mm.h
> @@ -542,6 +542,9 @@ struct vm_operations_struct {
> void (*close)(struct vm_area_struct * area);
> int (*split)(struct vm_area_struct * area, unsigned long addr);
> int (*mremap)(struct vm_area_struct * area);
> + int (*mprotect)(struct vm_area_struct *vma,
> + struct vm_area_struct **pprev, unsigned long start,
> + unsigned long end, unsigned long newflags);
> vm_fault_t (*fault)(struct vm_fault *vmf);
> vm_fault_t (*huge_fault)(struct vm_fault *vmf,
> enum page_entry_size pe_size);
> diff --git a/mm/mprotect.c b/mm/mprotect.c
> index ce8b8a5eacbb..f170f3da8a4f 100644
> --- a/mm/mprotect.c
> +++ b/mm/mprotect.c
> @@ -610,7 +610,10 @@ static int do_mprotect_pkey(unsigned long start, size_t len,
> tmp = vma->vm_end;
> if (tmp > end)
> tmp = end;
> - error = mprotect_fixup(vma, &prev, nstart, tmp, newflags);
> + if (vma->vm_ops && vma->vm_ops->mprotect)
> + error = vma->vm_ops->mprotect(vma, &prev, nstart, tmp, newflags);
> + else
> + error = mprotect_fixup(vma, &prev, nstart, tmp, newflags);
> if (error)
> goto out;
> nstart = tmp;
> --
> 2.25.1