X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=procprotect.c;h=d4f57d74c9c9345beea181b7bbd2397dd9d7765f;hb=5d514e9b7a3dc5f7017c5c6c03df883f32ee4aef;hp=2672ef817da335d933e03f907530a421538c4e9c;hpb=c48fc2de287117f7d339fe085dd582c8f301f51f;p=procprotect.git diff --git a/procprotect.c b/procprotect.c index 2672ef8..d4f57d7 100644 --- a/procprotect.c +++ b/procprotect.c @@ -28,6 +28,12 @@ #include #include +#include +#include +#include /* Specifically, a module */ +#include /* We're doing kernel work */ +#include /* Necessary because we use the proc fs */ + #define VERSION_STR "0.0.1" #ifndef CONFIG_X86_64 @@ -58,7 +64,7 @@ struct acl_entry { struct hlist_node hlist; }; -#define HASH_SIZE (1<<16) +#define HASH_SIZE (1<<10) struct hlist_head procprotect_hash[HASH_SIZE]; @@ -66,7 +72,7 @@ struct proc_dir_entry *proc_entry; static int run_acl(unsigned long ino) { struct acl_entry *entry; - hlist_for_each_entry_rcu(entry, + hlist_for_each_entry_rcu_notrace(entry, &procprotect_hash[ino & (HASH_SIZE-1)], hlist) { if (entry->ino==ino) { @@ -85,13 +91,21 @@ static int lookup_fast_entry(struct kretprobe_instance *ri, struct pt_regs *regs int ret = -1; struct procprotect_ctx *ctx; struct nameidata *nd = (struct nameidata *) regs->di; - struct dentry *parent = nd->path.dentry; - struct inode *pinode = parent->d_inode; + struct dentry *parent; + struct inode *pinode; + + if (!nd) return ret; + parent = nd->path.dentry; + + if (!parent) return ret; + pinode = parent->d_inode; + + if (!pinode || !pinode->i_sb || !current || !current->nsproxy) return ret; if (pinode->i_sb->s_magic == PROC_SUPER_MAGIC && current->nsproxy->mnt_ns!=init_task.nsproxy->mnt_ns) { ctx = (struct procprotect_ctx *) ri->data; - ctx->inode = regs->dx; + ctx->inode = (struct inode **)regs->dx; ctx->flags = nd->flags; ret = 0; } @@ -126,11 +140,13 @@ static int lookup_slow_entry(struct kretprobe_instance *ri, struct pt_regs *regs struct procprotect_ctx *ctx; struct nameidata *nd = (struct nameidata *) regs->di; struct path *p = (struct path *) regs->si; + struct dentry *parent; + struct inode *pinode; - struct dentry *parent = nd->path.dentry; - struct inode *pinode = parent->d_inode; - - + if (!nd) return ret; + parent = nd->path.dentry; + if (!parent) return ret; + pinode= parent->d_inode; if (pinode->i_sb->s_magic == PROC_SUPER_MAGIC && current->nsproxy->mnt_ns!=init_task.nsproxy->mnt_ns) { @@ -148,11 +164,12 @@ static int lookup_slow_entry(struct kretprobe_instance *ri, struct pt_regs *regs /* The entry hook ensures that the return hook is only called for accesses to /proc */ -static int print_once = 0; +/*static int print_once = 0;*/ static int lookup_slow_ret(struct kretprobe_instance *ri, struct pt_regs *regs) { struct procprotect_ctx *ctx; + struct inode *inode; int ret; if (!ri || !ri->data) {return 0;} @@ -165,7 +182,7 @@ static int lookup_slow_ret(struct kretprobe_instance *ri, struct pt_regs *regs) if (!p || !p->dentry || !p->dentry->d_inode /* This last check was responsible for the f18 bug*/) { return 0; } - struct inode *inode = p->dentry->d_inode; + inode = p->dentry->d_inode; if (!run_acl(inode->i_ino)) { regs->ax = -EPERM; } @@ -185,7 +202,7 @@ static struct file *do_last_probe(struct nameidata *nd, struct path *path, struc struct open_flags *op, const char *pathname) { struct dentry *parent = nd->path.dentry; struct inode *pinode = parent->d_inode; - struct qstr *q = &nd->last; + /*struct qstr *q = &nd->last;*/ if (pinode->i_sb->s_magic == PROC_SUPER_MAGIC && current->nsproxy->mnt_ns!=init_task.nsproxy->mnt_ns) { @@ -195,26 +212,76 @@ static struct file *do_last_probe(struct nameidata *nd, struct path *path, struc op->open_flag &= ~O_CREAT; } jprobe_return(); + return file; } static struct jprobe dolast_probe = { - .entry = (kprobe_opcode_t *) do_last_probe + .entry = do_last_probe }; static struct kretprobe fast_probe = { - .entry_handler = (kprobe_opcode_t *) lookup_fast_entry, - .handler = (kprobe_opcode_t *) lookup_fast_ret, + .entry_handler = lookup_fast_entry, + .handler = lookup_fast_ret, .maxactive = 20, .data_size = sizeof(struct procprotect_ctx) }; static struct kretprobe slow_probe = { - .entry_handler = (kprobe_opcode_t *) lookup_slow_entry, - .handler = (kprobe_opcode_t *) lookup_slow_ret, + .entry_handler = lookup_slow_entry, + .handler = lookup_slow_ret, .maxactive = 20, .data_size = sizeof(struct procprotect_ctx) }; +int once_only = 0; + +static int init_probes(void) { + int ret; + dolast_probe.kp.addr = + (kprobe_opcode_t *) kallsyms_lookup_name("do_last"); + + if (!dolast_probe.kp.addr) { + printk("Couldn't find %s to plant kretprobe\n", "do_last"); + return -1; + } + + if ((ret = register_jprobe(&dolast_probe)) <0) { + printk("register_jprobe failed, returned %u\n", ret); + return -1; + } + fast_probe.kp.addr = + (kprobe_opcode_t *) kallsyms_lookup_name("lookup_fast"); + + if (!fast_probe.kp.addr) { + printk("Couldn't find %s to plant kretprobe\n", "lookup_fast"); + return -1; + } + + slow_probe.kp.addr = + (kprobe_opcode_t *) kallsyms_lookup_name("lookup_slow"); + + if (!slow_probe.kp.addr) { + printk("Couldn't find %s to plant kretprobe\n", "lookup_slow"); + return -1; + } + + if ((ret = register_kretprobe(&fast_probe)) <0) { + printk("register_kretprobe failed, returned %d\n", ret); + return -1; + } + + printk("Planted kretprobe at %p, handler addr %p\n", + fast_probe.kp.addr, fast_probe.handler); + + if ((ret = register_kretprobe(&slow_probe)) <0) { + printk("register_kretprobe failed, returned %d\n", ret); + return -1; + } + printk("Planted kretprobe at %p, handler addr %p\n", + slow_probe.kp.addr, slow_probe.handler); + return 0; +} + static void add_entry(char *pathname) { struct path path; if (kern_path(pathname, 0, &path)) { @@ -239,17 +306,19 @@ static void add_entry(char *pathname) { } } } + } static void __exit procprotect_exit(void) { - unregister_kretprobe(&fast_probe); - unregister_kretprobe(&slow_probe); - unregister_jprobe(&dolast_probe); struct acl_entry *entry; int i; + unregister_kretprobe(&fast_probe); + unregister_kretprobe(&slow_probe); + unregister_jprobe(&dolast_probe); + for (i=0;insproxy->mnt_ns!=init_task.nsproxy->mnt_ns) @@ -280,13 +349,25 @@ int procfile_write(struct file *file, const char *buffer, unsigned long count, v pathname[count]='\0'; add_entry(pathname); - printk(KERN_CRIT "Length of buffer=%d",strlen(pathname)); + + if (!once_only) { + once_only=1; + if (init_probes()==-1) + printk(KERN_CRIT "Could not install procprotect probes. Reload module to retry."); + } + printk(KERN_CRIT "Length of buffer=%d",(int)strlen(pathname)); return count; } +static const struct file_operations procprotect_fops = { + .owner = THIS_MODULE, + .write = procfile_write +}; + + static int __init procprotect_init(void) { - int ret; + int ret = 0; int i; printk("Procprotect: starting procprotect version %s with ACLs at path %s.\n", @@ -299,51 +380,7 @@ static int __init procprotect_init(void) aclqpath.name = aclpath; aclqpath.len = strnlen(aclpath, PATH_MAX); - dolast_probe.kp.addr = - (kprobe_opcode_t *) kallsyms_lookup_name("do_last"); - - if (!dolast_probe.kp.addr) { - printk("Couldn't find %s to plant kretprobe\n", "do_last"); - return -1; - } - - if ((ret = register_jprobe(&dolast_probe)) <0) { - printk("register_jprobe failed, returned %u\n", ret); - return -1; - } - fast_probe.kp.addr = - (kprobe_opcode_t *) kallsyms_lookup_name("lookup_fast"); - if (!fast_probe.kp.addr) { - printk("Couldn't find %s to plant kretprobe\n", "lookup_fast"); - return -1; - } - - slow_probe.kp.addr = - (kprobe_opcode_t *) kallsyms_lookup_name("lookup_slow"); - if (!slow_probe.kp.addr) { - printk("Couldn't find %s to plant kretprobe\n", "lookup_slow"); - return -1; - } - - - - if ((ret = register_kretprobe(&fast_probe)) <0) { - printk("register_kretprobe failed, returned %d\n", ret); - return -1; - } - - printk("Planted kretprobe at %p, handler addr %p\n", - fast_probe.kp.addr, fast_probe.handler); - - if ((ret = register_kretprobe(&slow_probe)) <0) { - printk("register_kretprobe failed, returned %d\n", ret); - return -1; - } - printk("Planted kretprobe at %p, handler addr %p\n", - slow_probe.kp.addr, slow_probe.handler); - - proc_entry = create_proc_entry("procprotect", 0644, NULL); - proc_entry->write_proc = procfile_write; + proc_entry = proc_create("procprotect", 0644, NULL, &procprotect_fops); return ret; }