diff --git a/LKMPG-3.16.html b/LKMPG-3.16.html index 7d18d8f..0172894 100644 --- a/LKMPG-3.16.html +++ b/LKMPG-3.16.html @@ -3,7 +3,7 @@ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
- +/* - * procfs3.c - create a "file" in /proc, use the file_operation way - * to manage the file. - */ +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/proc_fs.h> +#include <linux/sched.h> +#include <asm/uaccess.h> -#include <linux/kernel.h> /* We're doing kernel work */ -#include <linux/module.h> /* Specifically, a module */ -#include <linux/proc_fs.h> /* Necessary because we use proc fs */ -#include <linux/sched.h> /* current_euid() */ -#include <asm/uaccess.h> /* for copy_*_user */ - -#define PROC_ENTRY_FILENAME "buffer2k" #define PROCFS_MAX_SIZE 2048 +#define PROCFS_ENTRY_FILENAME "buffer2k" -/** - * The buffer (2k) for this module - * - */ +struct proc_dir_entry *Our_Proc_File; static char procfs_buffer[PROCFS_MAX_SIZE]; - -/** - * The size of the data hold in the buffer - * - */ static unsigned long procfs_buffer_size = 0; -/** - * The structure keeping information about the /proc file - * - */ -static struct proc_dir_entry *Our_Proc_File; - -/** - * This funtion is called when the /proc file is read - * - */ -static ssize_t procfs_read(struct file *filp, /* see include/linux/fs.h */ - char *buffer, /* buffer to fill with data */ - size_t length, /* length of the buffer */ - loff_t * offset) +static ssize_t procfs_read(struct file *filp, char *buffer, + size_t length, loff_t *offset) { static int finished = 0; - - /* - * We return 0 to indicate end of file, that we have - * no more information. Otherwise, processes will - * continue to read from us in an endless loop. - */ - if ( finished ) { - printk(KERN_INFO "procfs_read: END\n"); + if(finished) + { + printk(KERN_DEBUG "procfs_read: END\n"); finished = 0; return 0; } - finished = 1; - - /* - * We use put_to_user to copy the string from the kernel's - * memory segment to the memory segment of the process - * that called us. get_from_user, BTW, is - * used for the reverse. - */ - if ( copy_to_user(buffer, procfs_buffer, procfs_buffer_size) ) { + if(copy_to_user(buffer, procfs_buffer, procfs_buffer_size)) return -EFAULT; - } - - printk(KERN_INFO "procfs_read: read %lu bytes\n", procfs_buffer_size); - - return procfs_buffer_size; /* Return the number of bytes "read" */ -} - -/* - * This function is called when /proc is written - */ -static ssize_t -procfs_write(struct file *file, const char *buffer, size_t len, loff_t * off) -{ - if ( len > PROCFS_MAX_SIZE ) { - procfs_buffer_size = PROCFS_MAX_SIZE; - } - else { - procfs_buffer_size = len; - } - - if ( copy_from_user(procfs_buffer, buffer, procfs_buffer_size) ) { - return -EFAULT; - } - - printk(KERN_INFO "procfs_write: write %lu bytes\n", procfs_buffer_size); - + printk(KERN_DEBUG "procfs_read: read %lu bytes\n", procfs_buffer_size); return procfs_buffer_size; } - -/* - * This function decides whether to allow an operation - * (return zero) or not allow it (return a non-zero - * which indicates why it is not allowed). - * - * The operation can be one of the following values: - * 0 - Execute (run the "file" - meaningless in our case) - * 2 - Write (input to the kernel module) - * 4 - Read (output from the kernel module) - * - * This is the real function that checks file - * permissions. The permissions returned by ls -l are - * for referece only, and can be overridden here. - */ -static int module_permission(struct inode *inode, int op) +static ssize_t procfs_write(struct file *file, const char *buffer, + size_t len, loff_t *off) { - /* - * We allow everybody to read from our module, but - * only root (uid 0) may write to it - */ - if (op == 4 || (op == 2 && current_euid() == 0)) - return 0; - - /* - * If it's anything else, access is denied - */ - return -EACCES; + if(len>PROCFS_MAX_SIZE) + procfs_buffer_size = PROCFS_MAX_SIZE; + else + procfs_buffer_size = len; + if(copy_from_user(procfs_buffer, buffer, procfs_buffer_size)) + return -EFAULT; + printk(KERN_DEBUG "procfs_write: write %lu bytes\n", procfs_buffer_size); + return procfs_buffer_size; } - -/* - * The file is opened - we don't really care about - * that, but it does mean we need to increment the - * module's reference count. - */ int procfs_open(struct inode *inode, struct file *file) { try_module_get(THIS_MODULE); return 0; } - -/* - * The file is closed - again, interesting only because - * of the reference count. - */ int procfs_close(struct inode *inode, struct file *file) { module_put(THIS_MODULE); - return 0; /* success */ + return 0; } static struct file_operations File_Ops_4_Our_Proc_File = { - .read = procfs_read, - .write = procfs_write, - .open = procfs_open, - .release = procfs_close, + .read = procfs_read, + .write = procfs_write, + .open = procfs_open, + .release = procfs_close, }; -/* - * Inode operations for our proc file. We need it so - * we'll have some place to specify the file operations - * structure we want to use, and the function we use for - * permissions. It's also possible to specify functions - * to be called for anything else which could be done to - * an inode (although we don't bother, we just put - * NULL). - */ - -static struct inode_operations Inode_Ops_4_Our_Proc_File = { - .permission = module_permission, /* check for permissions */ -}; - -/* - * Module initialization and cleanup - */ int init_module() { - /* create the /proc file */ - Our_Proc_File = proc_create(PROC_ENTRY_FILENAME, 0644, NULL, NULL); - - /* check if the /proc file was created successfuly */ - if (Our_Proc_File == NULL){ - printk(KERN_ALERT "Error: Could not initialize /proc/%s\n", - PROC_ENTRY_FILENAME); + Our_Proc_File = proc_create(PROCFS_ENTRY_FILENAME, 0644, NULL,&File_Ops_4_Our_Proc_File); + if(Our_Proc_File == NULL) + { + remove_proc_entry(PROCFS_ENTRY_FILENAME, NULL); + printk(KERN_DEBUG "Error: Could not initialize /proc/%s\n", PROCFS_ENTRY_FILENAME); return -ENOMEM; } + proc_set_size(Our_Proc_File, 80); + proc_set_user(Our_Proc_File, GLOBAL_ROOT_UID, GLOBAL_ROOT_GID); - Our_Proc_File->proc_iops = &Inode_Ops_4_Our_Proc_File; - Our_Proc_File->proc_fops = &File_Ops_4_Our_Proc_File; - Our_Proc_File->mode = S_IFREG | S_IRUGO | S_IWUSR; - Our_Proc_File->uid = 0; - Our_Proc_File->gid = 0; - Our_Proc_File->size = 80; - - printk(KERN_INFO "/proc/%s created\n", PROC_ENTRY_FILENAME); - - return 0; /* success */ + printk(KERN_DEBUG "/proc/%s created\n", PROCFS_ENTRY_FILENAME); + return 0; } - void cleanup_module() { - remove_proc_entry(PROC_ENTRY_FILENAME, NULL); - printk(KERN_INFO "/proc/%s removed\n", PROC_ENTRY_FILENAME); + remove_proc_entry(PROCFS_ENTRY_FILENAME, NULL); + printk(KERN_DEBUG "/proc/%s removed\n", PROCFS_ENTRY_FILENAME); }
-TODO: this will be out of date because of create_proc_entry -
-/** @@ -2522,9 +2401,12 @@ MODULE_LICENSE("GPL"); { struct proc_dir_entry *entry; - entry = create_proc_entry(PROC_NAME, 0, NULL); - if (entry) { - entry->proc_fops = &my_file_ops; + entry = proc_create(PROC_NAME, 0, NULL, &my_file_ops); + if(entry == NULL) + { + remove_proc_entry(PROC_NAME, NULL); + printk(KERN_DEBUG "Error: Could not initialize /proc/%s\n", PROC_NAME); + return -ENOMEM; } return 0; @@ -2537,6 +2419,7 @@ MODULE_LICENSE("GPL"); void cleanup_module(void) { remove_proc_entry(PROC_NAME, NULL); + printk(KERN_DEBUG "/proc/%s removed\n", PROC_NAME); }