From e4c2931a26f154518e003891ca538a98f3de1d51 Mon Sep 17 00:00:00 2001 From: Ryan Gordon Date: Tue, 21 Apr 2015 00:58:24 -0700 Subject: [PATCH 1/4] Adding code to let a kernel module register a function to handle page faults in network_mmap syscall --- Makefile | 2 +- arch/x86/syscalls/syscall_32.tbl | 1 + arch/x86/syscalls/syscall_64.tbl | 1 + include/linux/mm.h | 3 ++ include/linux/syscalls.h | 4 +++ mm/mmap.c | 48 ++++++++++++++++++++++++++++++++ 6 files changed, 58 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index b8b7f74696b409..f6d989a042a710 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 3 PATCHLEVEL = 13 SUBLEVEL = 0 -EXTRAVERSION = +EXTRAVERSION = -networkmmapv0.1 NAME = One Giant Leap for Frogkind # *DOCUMENTATION* diff --git a/arch/x86/syscalls/syscall_32.tbl b/arch/x86/syscalls/syscall_32.tbl index aabfb8380a1c6c..e055f59e1136af 100644 --- a/arch/x86/syscalls/syscall_32.tbl +++ b/arch/x86/syscalls/syscall_32.tbl @@ -357,3 +357,4 @@ 348 i386 process_vm_writev sys_process_vm_writev compat_sys_process_vm_writev 349 i386 kcmp sys_kcmp 350 i386 finit_module sys_finit_module +351 i386 network_mmap sys_network_mmap_pgoff diff --git a/arch/x86/syscalls/syscall_64.tbl b/arch/x86/syscalls/syscall_64.tbl index 38ae65dfd14ffe..4582f7c49f1387 100644 --- a/arch/x86/syscalls/syscall_64.tbl +++ b/arch/x86/syscalls/syscall_64.tbl @@ -320,6 +320,7 @@ 311 64 process_vm_writev sys_process_vm_writev 312 common kcmp sys_kcmp 313 common finit_module sys_finit_module +314 common network_mmap sys_network_mmap_pgoff # # x32-specific system call numbers start at 512 to avoid cache impact diff --git a/include/linux/mm.h b/include/linux/mm.h index 35527173cf50c7..bbe7c1abda2fdc 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -2011,5 +2011,8 @@ void __init setup_nr_node_ids(void); static inline void setup_nr_node_ids(void) {} #endif +typedef int (*network_mmap_fault_handler)(struct vm_area_struct *vma, struct vm_fault *vmf); +extern void set_kmod_network_mmap_fault_handler(network_mmap_fault_handler func); + #endif /* __KERNEL__ */ #endif /* _LINUX_MM_H */ diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index 94273bbe605007..bee4c18a230174 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -847,4 +847,8 @@ asmlinkage long sys_process_vm_writev(pid_t pid, asmlinkage long sys_kcmp(pid_t pid1, pid_t pid2, int type, unsigned long idx1, unsigned long idx2); asmlinkage long sys_finit_module(int fd, const char __user *uargs, int flags); + +asmlinkage long sys_network_mmap_pgoff(unsigned long addr, unsigned long len, + unsigned long prot, unsigned long flags, + unsigned long fd, unsigned long pgoff); #endif diff --git a/mm/mmap.c b/mm/mmap.c index 834b2d785f1e2f..3e77aef581161d 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -1400,6 +1400,54 @@ SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len, return retval; } +network_mmap_fault_handler network_mmap_fault_handler_ptr = NULL; + +static int default_network_mmap_fault_handler(struct vm_area_struct *vma, struct vm_fault *vmf) { + if (network_mmap_fault_handler_ptr) { + return network_mmap_fault_handler_ptr(vma, vmf); + } + + return VM_FAULT_SIGBUS; +} + +static const struct vm_operations_struct network_mmap_vm_ops = { + .fault = default_network_mmap_fault_handler, +}; + +SYSCALL_DEFINE6(network_mmap_pgoff, unsigned long, addr, unsigned long, len, + unsigned long, prot, unsigned long, flags, + unsigned long, fd, unsigned long, pgoff) +{ + unsigned long retval; + struct vm_area_struct *vma; + + printk(KERN_INFO "network_mmap_pgoff: 1. Entering network_mmap_pgoff\n"); + + printk(KERN_INFO "network_mmap_pgoff: 2. Calling sys_mmap_pgoff\n"); + retval = sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff); + printk(KERN_INFO "network_mmap_pgoff: 3. Completed sys_mmap_pgoff: %lu\n", retval); + + printk(KERN_INFO "network_mmap_pgoff: 4. Getting vma\n"); + // Override the fault handler with our own! + vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL); + if (!vma) { + retval = -ENOMEM; + } + printk(KERN_INFO "network_mmap_pgoff: 5. Completed getting vma: %lu\n", retval); + printk(KERN_INFO "network_mmap_pgoff: 6. Overriding fault handler: %p\n", network_mmap_fault_handler_ptr); + vma->vm_ops = &network_mmap_vm_ops; + printk(KERN_INFO "network_mmap_pgoff: 7. Completed overriding fault handler\n"); + + return retval; +} + +void set_kmod_network_mmap_fault_handler(network_mmap_fault_handler func) { + printk(KERN_INFO "set_kmod_network_mmap_fault_handler: 1. Entering set_kmod_network_mmap_fault_handler: %p\n", func); + network_mmap_fault_handler_ptr = func; + printk(KERN_INFO "set_kmod_network_mmap_fault_handler: 2. Completed setting set_kmod_network_mmap_fault_handler: %p\n", network_mmap_fault_handler_ptr); +} +EXPORT_SYMBOL(set_kmod_network_mmap_fault_handler); + #ifdef __ARCH_WANT_SYS_OLD_MMAP struct mmap_arg_struct { unsigned long addr; From 5c1426d2bf4d3cbfb21c9a46128c262ce0c97a68 Mon Sep 17 00:00:00 2001 From: Ryan Gordon Date: Thu, 23 Apr 2015 02:58:25 -0700 Subject: [PATCH 2/4] Working on some additional fixes and cleanup --- mm/mmap.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/mm/mmap.c b/mm/mmap.c index 3e77aef581161d..7855f5db30f9fd 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -1403,11 +1403,16 @@ SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len, network_mmap_fault_handler network_mmap_fault_handler_ptr = NULL; static int default_network_mmap_fault_handler(struct vm_area_struct *vma, struct vm_fault *vmf) { + int retval = VM_FAULT_SIGBUS; + printk(KERN_INFO "1. Calling default_network_mmap_fault_handler: %016llX\n", (uint64_t)network_mmap_fault_handler_ptr); if (network_mmap_fault_handler_ptr) { - return network_mmap_fault_handler_ptr(vma, vmf); + printk(KERN_INFO "2. Calling network_mmap_fault_handler_ptr\n"); + retval = network_mmap_fault_handler_ptr(vma, vmf); + printk(KERN_INFO "3. Done calling network_mmap_fault_handler_ptr: %d\n", retval); } + printk(KERN_INFO "4. default_network_mmap_fault_handler: %d\n", retval); - return VM_FAULT_SIGBUS; + return retval; } static const struct vm_operations_struct network_mmap_vm_ops = { @@ -1420,6 +1425,7 @@ SYSCALL_DEFINE6(network_mmap_pgoff, unsigned long, addr, unsigned long, len, { unsigned long retval; struct vm_area_struct *vma; + struct mm_struct *mm = current->mm; printk(KERN_INFO "network_mmap_pgoff: 1. Entering network_mmap_pgoff\n"); @@ -1427,14 +1433,19 @@ SYSCALL_DEFINE6(network_mmap_pgoff, unsigned long, addr, unsigned long, len, retval = sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff); printk(KERN_INFO "network_mmap_pgoff: 3. Completed sys_mmap_pgoff: %lu\n", retval); + // Was there an error? Just return the error code + if ((signed long)retval < 0 && (signed long)retval >= -133) { + return retval; + } + printk(KERN_INFO "network_mmap_pgoff: 4. Getting vma\n"); // Override the fault handler with our own! - vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL); + vma = find_vma(mm, retval); // retval contains our address at the start of our mmaped region if (!vma) { retval = -ENOMEM; } - printk(KERN_INFO "network_mmap_pgoff: 5. Completed getting vma: %lu\n", retval); - printk(KERN_INFO "network_mmap_pgoff: 6. Overriding fault handler: %p\n", network_mmap_fault_handler_ptr); + printk(KERN_INFO "network_mmap_pgoff: 5. Completed getting vma: %016llX\n", (uint64_t)vma); + printk(KERN_INFO "network_mmap_pgoff: 6. Overriding fault handler to: %016llX\n", (uint64_t)&network_mmap_vm_ops); vma->vm_ops = &network_mmap_vm_ops; printk(KERN_INFO "network_mmap_pgoff: 7. Completed overriding fault handler\n"); @@ -1442,9 +1453,9 @@ SYSCALL_DEFINE6(network_mmap_pgoff, unsigned long, addr, unsigned long, len, } void set_kmod_network_mmap_fault_handler(network_mmap_fault_handler func) { - printk(KERN_INFO "set_kmod_network_mmap_fault_handler: 1. Entering set_kmod_network_mmap_fault_handler: %p\n", func); + printk(KERN_INFO "set_kmod_network_mmap_fault_handler: 1. Entering set_kmod_network_mmap_fault_handler: %016llX\n", (uint64_t)func); network_mmap_fault_handler_ptr = func; - printk(KERN_INFO "set_kmod_network_mmap_fault_handler: 2. Completed setting set_kmod_network_mmap_fault_handler: %p\n", network_mmap_fault_handler_ptr); + printk(KERN_INFO "set_kmod_network_mmap_fault_handler: 2. Completed setting set_kmod_network_mmap_fault_handler: %016llX\n", (uint64_t)network_mmap_fault_handler_ptr); } EXPORT_SYMBOL(set_kmod_network_mmap_fault_handler); From e07d70ee822bf2bf6f69434d104f6c8f4b1eca1c Mon Sep 17 00:00:00 2001 From: Ryan Gordon Date: Thu, 23 Apr 2015 03:01:02 -0700 Subject: [PATCH 3/4] Update version number to latest --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index f6d989a042a710..981c58c3fb117f 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 3 PATCHLEVEL = 13 SUBLEVEL = 0 -EXTRAVERSION = -networkmmapv0.1 +EXTRAVERSION = -networkmmapv0.7 NAME = One Giant Leap for Frogkind # *DOCUMENTATION* From 82602cbbeaab5b1624e420acebe0587aed6cf3ac Mon Sep 17 00:00:00 2001 From: Ryan Gordon Date: Tue, 28 Apr 2015 02:35:12 -0700 Subject: [PATCH 4/4] Adding v0.8 version of kernel with network_msync syscall --- Makefile | 2 +- arch/x86/syscalls/syscall_32.tbl | 1 + arch/x86/syscalls/syscall_64.tbl | 1 + include/linux/mm.h | 3 +++ include/linux/syscalls.h | 2 ++ mm/msync.c | 23 +++++++++++++++++++++++ 6 files changed, 31 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 981c58c3fb117f..d7292df8122ccc 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 3 PATCHLEVEL = 13 SUBLEVEL = 0 -EXTRAVERSION = -networkmmapv0.7 +EXTRAVERSION = -networkmmapv0.8 NAME = One Giant Leap for Frogkind # *DOCUMENTATION* diff --git a/arch/x86/syscalls/syscall_32.tbl b/arch/x86/syscalls/syscall_32.tbl index e055f59e1136af..c7827a4a8ed7fd 100644 --- a/arch/x86/syscalls/syscall_32.tbl +++ b/arch/x86/syscalls/syscall_32.tbl @@ -358,3 +358,4 @@ 349 i386 kcmp sys_kcmp 350 i386 finit_module sys_finit_module 351 i386 network_mmap sys_network_mmap_pgoff +352 i386 network_msync sys_network_msync diff --git a/arch/x86/syscalls/syscall_64.tbl b/arch/x86/syscalls/syscall_64.tbl index 4582f7c49f1387..a4ec20349bb8b5 100644 --- a/arch/x86/syscalls/syscall_64.tbl +++ b/arch/x86/syscalls/syscall_64.tbl @@ -321,6 +321,7 @@ 312 common kcmp sys_kcmp 313 common finit_module sys_finit_module 314 common network_mmap sys_network_mmap_pgoff +315 common network_msync sys_network_msync # # x32-specific system call numbers start at 512 to avoid cache impact diff --git a/include/linux/mm.h b/include/linux/mm.h index bbe7c1abda2fdc..c131c8125ca9cc 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -2014,5 +2014,8 @@ static inline void setup_nr_node_ids(void) {} typedef int (*network_mmap_fault_handler)(struct vm_area_struct *vma, struct vm_fault *vmf); extern void set_kmod_network_mmap_fault_handler(network_mmap_fault_handler func); +typedef int (*network_msync)(unsigned long start, size_t len, int flags); +extern void set_kmod_network_msync(network_msync func); + #endif /* __KERNEL__ */ #endif /* _LINUX_MM_H */ diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index bee4c18a230174..14fa4cfbbb0dcc 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -851,4 +851,6 @@ asmlinkage long sys_finit_module(int fd, const char __user *uargs, int flags); asmlinkage long sys_network_mmap_pgoff(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long pgoff); + +asmlinkage long sys_network_msync(unsigned long start, size_t len, int flags); #endif diff --git a/mm/msync.c b/mm/msync.c index 632df4527c0122..4aae51e709f6ec 100644 --- a/mm/msync.c +++ b/mm/msync.c @@ -101,3 +101,26 @@ SYSCALL_DEFINE3(msync, unsigned long, start, size_t, len, int, flags) out: return error ? : unmapped_error; } + +network_msync network_msync_ptr = NULL; + +SYSCALL_DEFINE3(network_msync, unsigned long, start, size_t, len, int, flags) +{ + int retval = -EINVAL; + printk(KERN_INFO "1. Calling default_network_msync: %016llX\n", (uint64_t)network_msync_ptr); + if (network_msync_ptr) { + printk(KERN_INFO "2. Calling network_msync_ptr\n"); + retval = network_msync_ptr(start, len, flags); + printk(KERN_INFO "3. Done calling network_msync_ptr: %d\n", retval); + } + printk(KERN_INFO "4. default_network_msync: %d\n", retval); + + return retval; +} + +void set_kmod_network_msync(network_msync func) { + printk(KERN_INFO "set_kmod_network_msync: 1. Entering set_kmod_network_msync: %016llX\n", (uint64_t)func); + network_msync_ptr = func; + printk(KERN_INFO "set_kmod_network_msync: 2. Completed setting set_kmod_network_msync: %016llX\n", (uint64_t)network_msync_ptr); +} +EXPORT_SYMBOL(set_kmod_network_msync);