From ab6cb2626f7b1d55a9ff2bdaf1fcc074b86b2d43 Mon Sep 17 00:00:00 2001 From: Ciro Santilli Date: Thu, 27 Jul 2017 00:25:36 +0100 Subject: [PATCH] failed mmap fop attempt --- kernel_module/README.md | 1 + kernel_module/mmap.c | 165 ++++++++++++++++++++++++++++++++++++++ kernel_module/user/mmap.c | 35 ++++++++ rootfs_overlay/mmap.sh | 4 + 4 files changed, 205 insertions(+) create mode 100644 kernel_module/mmap.c create mode 100644 kernel_module/user/mmap.c create mode 100755 rootfs_overlay/mmap.sh diff --git a/kernel_module/README.md b/kernel_module/README.md index 978d1c0..d580361 100644 --- a/kernel_module/README.md +++ b/kernel_module/README.md @@ -11,6 +11,7 @@ 1. [fops](fops.c) 1. [ioctl](ioctl.c) 1. [poll](poll.c) + 1. [mmap](mmap.c) 1. [anonymous_inode](anonymous_inode.c) 1. [seq_file](seq_file.c) 1. [seq_file_single](seq_file_inode.c) diff --git a/kernel_module/mmap.c b/kernel_module/mmap.c new file mode 100644 index 0000000..1fb3b6a --- /dev/null +++ b/kernel_module/mmap.c @@ -0,0 +1,165 @@ +/* TODO neither works, mmap never gets called. */ + +#if 0 + +/* +Adapted from: +https://coherentmusings.wordpress.com/2014/06/10/implementing-mmap-for-transferring-data-from-user-space-to-kernel-space/ +*/ + +#include +#include +#include +#include +#include +#include +#include + +#ifndef VM_RESERVED +# define VM_RESERVED (VM_DONTEXPAND | VM_DONTDUMP) +#endif + +static struct dentry *debugfs_file; + +struct mmap_info +{ + char *data; + int reference; +}; + +static void vm_close(struct vm_area_struct *vma) +{ + struct mmap_info *info; + + pr_info("vm_close\n"); + info = (struct mmap_info *)vma->vm_private_data; + info->reference--; +} + +static int vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) +{ + struct page *page; + struct mmap_info *info; + + pr_info("vm_fault\n"); + info = (struct mmap_info *)vma->vm_private_data; + if (info->data) { + page = virt_to_page(info->data); + get_page(page); + vmf->page = page; + } + return 0; +} + +static void vm_open(struct vm_area_struct *vma) +{ + struct mmap_info *info; + + pr_info("vm_open\n"); + info = (struct mmap_info *)vma->vm_private_data; + info->reference++; +} + +static struct vm_operations_struct vm_ops = +{ + .close = vm_close, + .fault = vm_fault, + .open = vm_open, +}; + +static int mmap(struct file *filp, struct vm_area_struct *vma) +{ + pr_info("mmap\n"); + vma->vm_ops = &vm_ops; + vma->vm_flags |= VM_RESERVED; + vma->vm_private_data = filp->private_data; + vm_open(vma); + return 0; +} + +static int open(struct inode *inode, struct file *filp) +{ + struct mmap_info *info; + + pr_info("open\n"); + info = kmalloc(sizeof(struct mmap_info), GFP_KERNEL); + info->data = (char *)get_zeroed_page(GFP_KERNEL); + memcpy(info->data, "abc", 4); + filp->private_data = info; + return 0; +} + +static int release(struct inode *inode, struct file *filp) +{ + struct mmap_info *info; + + pr_info("release\n"); + info = filp->private_data; + free_page((unsigned long)info->data); + kfree(info); + filp->private_data = NULL; + return 0; +} + +static const struct file_operations fops = { + .mmap = mmap, + .open = open, + .release = release, +}; + +static int myinit(void) +{ + debugfs_file = debugfs_create_file("lkmc_mmap", S_IRWXU, NULL, NULL, &fops); + return 0; +} + +static void myexit(void) +{ + debugfs_remove(debugfs_file); +} + +module_init(myinit); +module_exit(myexit); +MODULE_LICENSE("GPL"); + +#endif + +#include +#include +#include +#include +#include +#include + +static struct dentry *debugfs_file; + +static int map_mmap(struct file *filp, struct vm_area_struct *vma) +{ + if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, + vma->vm_end - vma->vm_start, vma->vm_page_prot)) { + return -EAGAIN; + } + return 0; +} + +struct file_operations fops = +{ + .owner = THIS_MODULE, + .open = nonseekable_open, + .mmap = map_mmap +}; + +static int myinit(void) +{ + debugfs_file = debugfs_create_file("lkmc_mmap", S_IRWXU, NULL, NULL, &fops); + return 0; +} + +static void myexit(void) +{ + debugfs_remove(debugfs_file); +} + +module_init(myinit); +module_exit(myexit); +MODULE_LICENSE("GPL"); diff --git a/kernel_module/user/mmap.c b/kernel_module/user/mmap.c new file mode 100644 index 0000000..901b0f9 --- /dev/null +++ b/kernel_module/user/mmap.c @@ -0,0 +1,35 @@ +#include +#include +#include +#include +#include +#include + +#define PAGE_SIZE 4096 + +int main(int argc, char **argv) +{ + int fd; + char *address = NULL; + + if (argc < 2) { + printf("Usage: %s \n", argv[0]); + return EXIT_FAILURE; + } + fd = open(argv[1], O_RDWR | O_SYNC); + if (fd < 0) { + perror("open"); + return EXIT_FAILURE; + } + printf("fd = %d\n", fd); + address = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (address == MAP_FAILED) { + perror("mmap"); + return EXIT_FAILURE; + } + printf("%s\n", address); + memcpy(address + 11 , "qwer", 6); + printf("%s\n", address); + close(fd); + return EXIT_SUCCESS; +} diff --git a/rootfs_overlay/mmap.sh b/rootfs_overlay/mmap.sh new file mode 100755 index 0000000..500413c --- /dev/null +++ b/rootfs_overlay/mmap.sh @@ -0,0 +1,4 @@ +#!/bin/sh +insmod /mmap.ko +/mmap.out /sys/kernel/debug/lkmc_mmap +rmmod /mmap.ko