@@ -458,6 +458,8 @@ 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 (*may_mprotect)(struct vm_area_struct *vma, unsigned long start,
+ unsigned long end, unsigned long prot);
vm_fault_t (*fault)(struct vm_fault *vmf);
vm_fault_t (*huge_fault)(struct vm_fault *vmf,
enum page_entry_size pe_size);
@@ -547,13 +547,20 @@ static int do_mprotect_pkey(unsigned long start, size_t len,
goto out;
}
- error = security_file_mprotect(vma, reqprot, prot);
- if (error)
- goto out;
-
tmp = vma->vm_end;
if (tmp > end)
tmp = end;
+
+ if (vma->vm_ops && vma->vm_ops->may_mprotect) {
+ error = vma->vm_ops->may_mprotect(vma, nstart, tmp, prot);
+ if (error)
+ goto out;
+ }
+
+ error = security_file_mprotect(vma, reqprot, prot);
+ if (error)
+ goto out;
+
error = mprotect_fixup(vma, &prev, nstart, tmp, newflags);
if (error)
goto out;
SGX will use ->may_mprotect() to invoke an SGX variant of the existing file_mprotect() and mmap_file() LSM hooks. The name may_mprotect() is intended to reflect the hook's purpose as a way to restrict mprotect() as opposed to a wholesale replacement. Due to the nature of SGX and its Enclave Page Cache (EPC), all enclave VMAs are backed by a single file, i.e. /dev/sgx/enclave, that must be MAP_SHARED. Furthermore, all enclaves need read, write and execute VMAs. As a result, applying W^X restrictions on /dev/sgx/enclave using existing LSM hooks is for all intents and purposes impossible, e.g. denying either W or X would deny access to *any* enclave. By hooking mprotect(), SGX can invoke an SGX specific LSM hook, which in turn allows LSMs to enforce W^X policies. Alternatively, SGX could provide a helper to identify enclaves given a vma or file. LSMs could then check if a mapping is for enclave and take action according. A second alternative would be to have SGX implement its own LSM hooks for file_mprotect() and mmap_file(), using them to "forward" the call to the SGX specific hook. The major con to both alternatives is that they provide zero flexibility for the SGX specific LSM hook. The "is_sgx_enclave()" helper doesn't allow SGX can't supply any additional information whatsoever, and the mmap_file() hook is called before the final address is known, e.g. SGX can't provide any information about the specific enclave being mapped. Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com> --- include/linux/mm.h | 2 ++ mm/mprotect.c | 15 +++++++++++---- 2 files changed, 13 insertions(+), 4 deletions(-)