X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=procprotect.c;h=1c3e8035e01f840e61fe6e1e74742835b3e6ed6e;hb=45362125880411ebb94253979d98df1b04a3e02c;hp=4431ff848e8c548fbedacd0aaf6581802da9b7f2;hpb=09d0dae85015c19d0c1c18d917900d60974041d6;p=procprotect.git diff --git a/procprotect.c b/procprotect.c index 4431ff8..1c3e803 100644 --- a/procprotect.c +++ b/procprotect.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -27,13 +28,20 @@ #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 #error "This code does not support your architecture" #endif -static char *aclpath __devinitdata = "procprotect"; +static char *aclpath = "procprotect"; + static struct qstr aclqpath; module_param(aclpath, charp, 0); @@ -56,18 +64,17 @@ struct acl_entry { struct hlist_node hlist; }; -#define HASH_SIZE (1<<16) +#define HASH_SIZE (1<<10) struct hlist_head procprotect_hash[HASH_SIZE]; struct proc_dir_entry *proc_entry; static int run_acl(unsigned long ino) { - struct hlist_node *n; struct acl_entry *entry; - hlist_for_each_entry_rcu(entry, - n, &procprotect_hash[ino & (HASH_SIZE-1)], - hlist) { + hlist_for_each_entry_rcu_notrace(entry, + &procprotect_hash[ino & (HASH_SIZE-1)], + hlist) { if (entry->ino==ino) { return 0; } @@ -84,14 +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 qstr *q = (struct qstr *) regs->si; - 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->cx; + ctx->inode = regs->dx; ctx->flags = nd->flags; ret = 0; } @@ -113,9 +127,7 @@ static int lookup_fast_ret(struct kretprobe_instance *ri, struct pt_regs *regs) /* The kernel is going to honor the request. Here's where we step in */ struct inode *inode = *(ctx->inode); if (!run_acl(inode->i_ino)) { - if (current->nsproxy->mnt_ns!=init_task.nsproxy->mnt_ns) { - regs->ax = -EPERM; - } + regs->ax = -EPERM; } } @@ -127,19 +139,20 @@ static int lookup_slow_entry(struct kretprobe_instance *ri, struct pt_regs *regs int ret = -1; struct procprotect_ctx *ctx; struct nameidata *nd = (struct nameidata *) regs->di; - struct qstr *q = (struct qstr *) regs->si; - struct path *p = (struct path *) regs->dx; - - struct dentry *parent = nd->path.dentry; - struct inode *pinode = parent->d_inode; + struct path *p = (struct path *) regs->si; + struct dentry *parent; + struct inode *pinode; - + if (!nd) return; + parent = nd->path.dentry; + if (!parent) return; + pinode= parent->d_inode; 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->q = q; + ctx->q = &nd->last; ctx->flags = nd->flags; ctx->path = p; ret = 0; @@ -151,19 +164,26 @@ 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 lookup_slow_ret(struct kretprobe_instance *ri, struct pt_regs *regs) { - struct procprotect_ctx *ctx = (struct procprotect_ctx *) ri->data; - int ret = regs->ax; + struct procprotect_ctx *ctx; + int ret; + + if (!ri || !ri->data) {return 0;} + ctx = (struct procprotect_ctx *) ri->data; + + ret = regs->ax; if (ret==0) { - /* The kernel is going to honor the request. Here's where we step in */ struct path *p = ctx->path; + 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; if (!run_acl(inode->i_ino)) { - if (current->nsproxy->mnt_ns!=init_task.nsproxy->mnt_ns) { - regs->ax = -EPERM; - } + regs->ax = -EPERM; } } @@ -177,12 +197,17 @@ struct open_flags { int intent; }; -static struct file *do_last_probe(struct nameidata *nd, struct path *path, +static struct file *do_last_probe(struct nameidata *nd, struct path *path, struct file *file, struct open_flags *op, const char *pathname) { struct dentry *parent = nd->path.dentry; struct inode *pinode = parent->d_inode; + struct qstr *q = &nd->last; + if (pinode->i_sb->s_magic == PROC_SUPER_MAGIC && current->nsproxy->mnt_ns!=init_task.nsproxy->mnt_ns) { + /*if (!strncmp(q->name,"sysrq-trigger",13)) { + printk(KERN_CRIT "do_last sysrqtrigger: %d",op->open_flag); + }*/ op->open_flag &= ~O_CREAT; } jprobe_return(); @@ -206,6 +231,55 @@ static struct kretprobe slow_probe = { .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)) { @@ -230,6 +304,7 @@ static void add_entry(char *pathname) { } } } + } @@ -237,15 +312,14 @@ static void __exit procprotect_exit(void) { unregister_kretprobe(&fast_probe); unregister_kretprobe(&slow_probe); - unregister_jprobe(&dolast_probe); - struct hlist_node *n; + unregister_jprobe(&dolast_probe); struct acl_entry *entry; int i; for (i=0;iwrite_proc = procfile_write; + proc_entry = proc_create("procprotect", 0644, NULL, &procprotect_fops); return ret; }