X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=procprotect.c;h=4763e1713e4c1fbd2f8a18a0e162652ac1fd9313;hb=6287e895062de52bfe9478085edc005baedd3d50;hp=c1c016273e165ae99607666a3ca62b0033278cfb;hpb=f042ad58bae8446f25e2762fe4de413aad57026f;p=procprotect.git diff --git a/procprotect.c b/procprotect.c index c1c0162..4763e17 100644 --- a/procprotect.c +++ b/procprotect.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -33,7 +34,12 @@ #error "This code does not support your architecture" #endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0) +static char *aclpath = "procprotect"; +#else static char *aclpath __devinitdata = "procprotect"; +#endif + static struct qstr aclqpath; module_param(aclpath, charp, 0); @@ -46,6 +52,8 @@ MODULE_VERSION(VERSION_STR); struct procprotect_ctx { struct inode **inode; + struct qstr *q; + struct path *path; int flags; }; @@ -60,12 +68,25 @@ 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) { + if (entry->ino==ino) { + return 0; + } + } + return 1; +} + /* Entry point of intercepted call. We need to do two things here: - Decide if we need the heavier return hook to be called - Save the first argument, which is in a register, for consideration in the return hook */ -static int do_lookup_entry(struct kretprobe_instance *ri, struct pt_regs *regs) { +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; @@ -84,23 +105,12 @@ static int do_lookup_entry(struct kretprobe_instance *ri, struct pt_regs *regs) return ret; } -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) { - if (entry->ino==ino) { - return 0; - } - } - return 1; -} - /* The entry hook ensures that the return hook is only called for accesses to /proc */ -static int do_lookup_ret(struct kretprobe_instance *ri, struct pt_regs *regs) +int printed=0; + +static int lookup_fast_ret(struct kretprobe_instance *ri, struct pt_regs *regs) { struct procprotect_ctx *ctx = (struct procprotect_ctx *) ri->data; int ret = regs->ax; @@ -109,9 +119,62 @@ static int do_lookup_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; + } + } + + + return 0; +} + +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; + + + + 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->flags = nd->flags; + ctx->path = p; + ret = 0; + } + + return ret; +} + +/* 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; + int ret; + + if (!ri || !ri->data) {return 0;} + ctx = (struct procprotect_ctx *) ri->data; + + ret = regs->ax; + + if (ret==0) { + 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)) { + regs->ax = -EPERM; } } @@ -125,12 +188,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(); @@ -140,9 +208,16 @@ static struct jprobe dolast_probe = { .entry = (kprobe_opcode_t *) do_last_probe }; -static struct kretprobe proc_probe = { - .entry_handler = (kprobe_opcode_t *) do_lookup_entry, - .handler = (kprobe_opcode_t *) do_lookup_ret, +static struct kretprobe fast_probe = { + .entry_handler = (kprobe_opcode_t *) lookup_fast_entry, + .handler = (kprobe_opcode_t *) 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, .maxactive = 20, .data_size = sizeof(struct procprotect_ctx) }; @@ -176,7 +251,8 @@ static void add_entry(char *pathname) { static void __exit procprotect_exit(void) { - unregister_kretprobe(&proc_probe); + unregister_kretprobe(&fast_probe); + unregister_kretprobe(&slow_probe); unregister_jprobe(&dolast_probe); struct hlist_node *n; struct acl_entry *entry; @@ -210,6 +286,7 @@ int procfile_write(struct file *file, const char *buffer, unsigned long count, v } else pathname[count]='\0'; + add_entry(pathname); printk(KERN_CRIT "Length of buffer=%d",strlen(pathname)); return count; @@ -217,11 +294,12 @@ int procfile_write(struct file *file, const char *buffer, unsigned long count, v static int __init procprotect_init(void) { - printk("Procprotect: starting procprotect version %s with ACLs at path %s.\n", - VERSION_STR, aclpath); int ret; int i; + printk("Procprotect: starting procprotect version %s with ACLs at path %s.\n", + VERSION_STR, aclpath); + for(i=0;iwrite_proc = procfile_write;