@@ -1446,6 +1446,27 @@
* @bpf_prog_free_security:
* Clean up the security information stored inside bpf prog.
*
+ * Security hooks for SGX enclaves
+ *
+ * @enclave_load:
+ * Check permissions before loading pages into enclaves. Must be called
+ * with current->mm->mmap_sem locked.
+ * @encl: file pointer identifying the enclave
+ * @addr: linear address to which new pages are being added. Must be page
+ * aligned
+ * @size: total size of pages being added. Must be integral multiple of
+ * page size
+ * @prot: requested protection. Shall be the same protection as the VMA
+ * covering the target linear range, or 0 if target range not mapped
+ * @source: the VMA containing the source pages. Shall be NULL if there's
+ * no source pages (e.g. EAUG)
+ *
+ * @enclave_init:
+ * Check SIGSTRUCT before initializing (EINIT) enclaves. Must be called
+ * with current->mm->mmap_sem locked.
+ * @encl: file pointer identifying the enclave being initialized
+ * @sigstruct: pointer to sigstruct in kernel memory
+ * @sigstruct_vma: vma containing the original sigstruct in user space
*/
union security_list_options {
int (*binder_set_context_mgr)(struct task_struct *mgr);
@@ -1807,6 +1828,14 @@ union security_list_options {
int (*bpf_prog_alloc_security)(struct bpf_prog_aux *aux);
void (*bpf_prog_free_security)(struct bpf_prog_aux *aux);
#endif /* CONFIG_BPF_SYSCALL */
+#ifdef CONFIG_INTEL_SGX
+ int (*enclave_load)(struct file *encl, unsigned long addr,
+ unsigned long size, unsigned long prot,
+ struct vm_area_struct *source);
+ int (*enclave_init)(struct file *encl,
+ const struct sgx_sigstruct *sigstruct,
+ struct vm_area_struct *sigstruct_vma);
+#endif /* CONFIG_INTEL_SGX */
};
struct security_hook_heads {
@@ -2046,6 +2075,10 @@ struct security_hook_heads {
struct hlist_head bpf_prog_alloc_security;
struct hlist_head bpf_prog_free_security;
#endif /* CONFIG_BPF_SYSCALL */
+#ifdef CONFIG_INTEL_SGX
+ struct hlist_head enclave_load;
+ struct hlist_head enclave_init;
+#endif /* CONFIG_INTEL_SGX */
} __randomize_layout;
/*
@@ -1829,5 +1829,31 @@ static inline void security_bpf_prog_free(struct bpf_prog_aux *aux)
#endif /* CONFIG_SECURITY */
#endif /* CONFIG_BPF_SYSCALL */
+#ifdef CONFIG_INTEL_SGX
+struct sgx_sigstruct;
+#ifdef CONFIG_SECURITY
+extern int security_enclave_load(struct file *encl, unsigned long addr,
+ unsigned long size, unsigned long prot,
+ struct vm_area_struct *source);
+extern int security_enclave_init(struct file *encl,
+ const struct sgx_sigstruct *sigstruct,
+ struct vm_area_struct *sigstruct_vma);
+#else
+static inline int security_enclave_load(struct file *encl, unsigned long addr,
+ unsigned long size, unsigned long prot,
+ struct vm_area_struct *source)
+{
+ return 0;
+}
+
+static inline int security_enclave_init(struct file *encl,
+ const struct sigstruct *sigstruct,
+ struct vm_area_struct *sigstruct_vma)
+{
+ return 0;
+}
+#endif /* CONFIG_SECURITY */
+#endif /* CONFIG_INTEL_SGX */
+
#endif /* ! __LINUX_SECURITY_H */
@@ -1420,6 +1420,7 @@ int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot,
{
return call_int_hook(file_mprotect, 0, vma, reqprot, prot);
}
+EXPORT_SYMBOL(security_file_mprotect);
int security_file_lock(struct file *file, unsigned int cmd)
{
@@ -2355,3 +2356,23 @@ void security_bpf_prog_free(struct bpf_prog_aux *aux)
call_void_hook(bpf_prog_free_security, aux);
}
#endif /* CONFIG_BPF_SYSCALL */
+
+#ifdef CONFIG_INTEL_SGX
+
+int security_enclave_load(struct file *encl, unsigned long addr,
+ unsigned long size, unsigned long prot,
+ struct vm_area_struct *source)
+{
+ return call_int_hook(enclave_load, 0, encl, addr, size, prot, source);
+}
+EXPORT_SYMBOL(security_enclave_load);
+
+int security_enclave_init(struct file *encl,
+ const struct sgx_sigstruct *sigstruct,
+ struct vm_area_struct *sigstruct_vma)
+{
+ return call_int_hook(enclave_init, 0, encl, sigstruct, sigstruct_vma);
+}
+EXPORT_SYMBOL(security_enclave_init);
+
+#endif /* CONFIG_INTEL_SGX */
This patch has made two changes to LSM hooks. The first change is the addition of two new SGX specific LSM hooks. security_enclave_load() - is called whenever new EPC pages are added to an enclave, so that an LSM module could initialize internal states for those pages. An LSM module may track protections ever granted to enclave pages in order to come to reasonable decisions in security_file_mprotect() hook in future. security_enclave_init() - is called when an enclave is about to be intialized (by EINIT). An LSM module may approve/decline the request by looking into the SIGSTRUCT, or the file from which the SIGSTRUCT was loaded from. The second change is to export symbol security_file_mprotect() to make it available to kernel modules. The SGX module will invoke security_file_mprotect() to validate protection for the virtual memory range being mmap()'ed. Please see include/linux/lsm_hooks.h for more information. Signed-off-by: Cedric Xing <cedric.xing@intel.com> --- include/linux/lsm_hooks.h | 33 +++++++++++++++++++++++++++++++++ include/linux/security.h | 26 ++++++++++++++++++++++++++ security/security.c | 21 +++++++++++++++++++++ 3 files changed, 80 insertions(+)