@@ -15,6 +15,7 @@
#include <linux/prefetch.h> /* prefetchw */
#include <linux/context_tracking.h> /* exception_enter(), ... */
#include <linux/uaccess.h> /* faulthandler_disabled() */
+#include <linux/security.h> /* security_pagefault_handler */
#include <asm/cpufeature.h> /* boot_cpu_has, ... */
#include <asm/traps.h> /* dotraplinkage, ... */
@@ -1358,6 +1359,11 @@ static inline bool smap_violation(int error_code, struct pt_regs *regs)
local_irq_enable();
}
+ if (unlikely(security_pagefault_handler_x86(regs,
+ error_code,
+ address)))
+ return;
+
perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
if (error_code & PF_WRITE)
@@ -487,6 +487,11 @@
* Check if the requested @vmflags are allowed.
* @vmflags contains requested the vmflags.
* Return 0 if the operation is allowed to continue.
+ * @pagefault_handler_x86:
+ * Handle pagefaults on x86.
+ * @regs contains process' registers.
+ * @error_code contains error code for the pagefault.
+ * @address contains the address that caused the pagefault.
* @file_lock:
* Check permission before performing file locking operations.
* Note: this hook mediates both flock and fcntl style locks.
@@ -1487,6 +1492,9 @@
int (*file_mprotect)(struct vm_area_struct *vma, unsigned long reqprot,
unsigned long prot);
int (*check_vmflags)(vm_flags_t vmflags);
+ int (*pagefault_handler_x86)(struct pt_regs *regs,
+ unsigned long error_code,
+ unsigned long address);
int (*file_lock)(struct file *file, unsigned int cmd);
int (*file_fcntl)(struct file *file, unsigned int cmd,
unsigned long arg);
@@ -1759,6 +1767,7 @@ struct security_hook_heads {
struct list_head mmap_file;
struct list_head file_mprotect;
struct list_head check_vmflags;
+ struct list_head pagefault_handler_x86;
struct list_head file_lock;
struct list_head file_fcntl;
struct list_head file_set_fowner;
@@ -303,6 +303,9 @@ int security_mmap_file(struct file *file, unsigned long prot,
int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot,
unsigned long prot);
int security_check_vmflags(vm_flags_t vmflags);
+int __maybe_unused security_pagefault_handler_x86(struct pt_regs *regs,
+ unsigned long error_code,
+ unsigned long address);
int security_file_lock(struct file *file, unsigned int cmd);
int security_file_fcntl(struct file *file, unsigned int cmd, unsigned long arg);
void security_file_set_fowner(struct file *file);
@@ -836,6 +839,14 @@ static inline int security_check_vmflags(vm_flags_t vmflags)
return 0;
}
+static inline int __maybe_unused security_pagefault_handler_x86(
+ struct pt_regs *regs,
+ unsigned long error_code,
+ unsigned long address)
+{
+ return 0;
+}
+
static inline int security_file_lock(struct file *file, unsigned int cmd)
{
return 0;
@@ -910,6 +910,17 @@ int security_check_vmflags(vm_flags_t vmflags)
return call_int_hook(check_vmflags, 0, vmflags);
}
+int __maybe_unused security_pagefault_handler_x86(struct pt_regs *regs,
+ unsigned long error_code,
+ unsigned long address)
+{
+ return call_int_hook(pagefault_handler_x86,
+ 0,
+ regs,
+ error_code,
+ address);
+}
+
int security_file_lock(struct file *file, unsigned int cmd)
{
return call_int_hook(file_lock, 0, file, cmd);
Creation of a new hook to let LSM modules handle user-space pagefaults on x86. It can be used to avoid segfaulting the originating process. If it's the case it can modify process registers before returning. Signed-off-by: Salvatore Mesoraca <s.mesoraca16@gmail.com> Cc: x86@kernel.org Cc: Ingo Molnar <mingo@redhat.com> --- arch/x86/mm/fault.c | 6 ++++++ include/linux/lsm_hooks.h | 9 +++++++++ include/linux/security.h | 11 +++++++++++ security/security.c | 11 +++++++++++ 4 files changed, 37 insertions(+)