--- /dev/null
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/fs_struct.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/reboot.h>
+#include <linux/delay.h>
+#include <linux/proc_fs.h>
+#include <asm/uaccess.h>
+#include <linux/sysrq.h>
+#include <linux/timer.h>
+#include <linux/time.h>
+#include <linux/lglock.h>
+#include <linux/init.h>
+#include <linux/idr.h>
+#include <linux/namei.h>
+#include <linux/bitops.h>
+#include <linux/mnt_namespace.h>
+#include <linux/path.h>
+#include <linux/dcache.h>
+#include <linux/spinlock.h>
+#include <linux/completion.h>
+#include <linux/sched.h>
+#include <linux/seq_file.h>
+#include <linux/file.h>
+#include <linux/kprobes.h>
+#include <linux/kallsyms.h>
+#include <linux/nsproxy.h>
+#include "mount.h"
+
+#define VERSION_STR "0.0.1"
+
+#ifndef CONFIG_X86_64
+#error "This code does not support your architecture"
+#endif
+
+MODULE_AUTHOR("Sapan Bhatia <sapanb@cs.princeton.edu>");
+MODULE_DESCRIPTION("Hack to enable mount namespace switching via setns. Based on a patch by Eric Biederman.");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(VERSION_STR);
+
+struct proc_dir_entry *proc_entry;
+
+static void *mntns_get(struct task_struct *task)
+{
+ struct mnt_namespace *ns;
+ rcu_read_lock();
+ ns = task->nsproxy->mnt_ns;
+ atomic_inc(&ns->count);
+ rcu_read_unlock();
+ return ns;
+}
+
+void (*put_mnt_ns2)(struct mnt_namespace *ns);
+
+static void mntns_put(void *ns)
+{
+ (*put_mnt_ns2)(ns);
+}
+
+static int mntns_install(struct nsproxy *nsproxy, void *ns)
+{
+ struct fs_struct *fs = current->fs;
+ struct mnt_namespace *mnt_ns = ns;
+ struct path root;
+
+ if (fs->users != 1)
+ return -EINVAL;
+
+ atomic_inc(&mnt_ns->count);
+ (*put_mnt_ns2)(nsproxy->mnt_ns);
+ nsproxy->mnt_ns = mnt_ns;
+
+ root.mnt = &mnt_ns->root->mnt;
+ root.dentry = mnt_ns->root->mnt.mnt_root;
+ path_get(&root);
+ while(d_mountpoint(root.dentry) && follow_down(&root))
+ ;
+
+ path_get(&root);
+ path_get(&root);
+ path_put(&fs->root);
+ path_put(&fs->pwd);
+ fs->root = root;
+ fs->pwd = root;
+ path_put(&root);
+
+ return 0;
+}
+
+const struct proc_ns_operations mntns_operations = {
+ .name = "mnt_ns",
+ .get = mntns_get,
+ .put = mntns_put,
+ .install = mntns_install,
+};
+
+void (*free_nsproxy2)(struct nsproxy *ns);
+
+struct nsproxy * (*create_new_namespaces)(unsigned long flags,
+ struct task_struct *tsk, struct fs_struct *new_fs);
+
+void (*switch_task_namespaces2)(struct task_struct *p, struct nsproxy *new);
+
+static int setns(struct task_struct *reftask) {
+ const struct proc_ns_operations *ops;
+ struct task_struct *tsk = current;
+ struct nsproxy *new_nsproxy;
+ int err;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ err = -EINVAL;
+ ops = &mntns_operations;
+
+ new_nsproxy = (*create_new_namespaces)(0, tsk, tsk->fs);
+ if (IS_ERR(new_nsproxy)) {
+ err = PTR_ERR(new_nsproxy);
+ goto out;
+ }
+
+ err = ops->install(new_nsproxy, reftask->nsproxy->mnt_ns);
+ if (err) {
+ (*free_nsproxy2)(new_nsproxy);
+ goto out;
+ }
+ (*switch_task_namespaces2)(tsk, new_nsproxy);
+ return 0;
+out:
+ return err;
+
+}
+
+static void __exit lxcsu_exit(void)
+{
+ remove_proc_entry("lxcsu",NULL);
+ printk("Procprotect: Stopped lxcsu.\n");
+}
+
+int lxcsu_write(struct file *file, const char *buffer, unsigned long count, void *data) {
+ char pidname[PATH_MAX];
+ int pid;
+ struct pid *p;
+ char **s;
+ struct task_struct *task;
+
+ if (current->nsproxy->mnt_ns!=init_task.nsproxy->mnt_ns)
+ return -EPERM;
+
+ if (copy_from_user(pidname, buffer, count)) {
+ return -EFAULT;
+ }
+ if (count && (pidname[count-1]==10 || pidname[count-1]==13)) {
+ pidname[count-1]='\0';
+ }
+ else
+ pidname[count]='\0';
+
+ pid = simple_strtol(pidname,s,10);
+ p = find_vpid(pid);
+ task = get_pid_task(p,PIDTYPE_PID);
+ if (task) {
+ setns(task);
+ }
+ else {
+ printk(KERN_CRIT "Task %d not found",pid);
+ }
+
+ return count;
+}
+static int __init lxcsu_init(void)
+{
+ int ret=0;
+ printk("Mntsu: starting lxcsu version %s.\n",
+ VERSION_STR);
+
+ free_nsproxy2 = kallsyms_lookup_name("free_nsproxy");
+ printk(KERN_CRIT "free_nsproxy = %x",free_nsproxy2);
+
+ switch_task_namespaces2 = kallsyms_lookup_name("switch_task_namespaces");
+ printk(KERN_CRIT "switch_task_namespaces = %x",switch_task_namespaces2);
+
+ create_new_namespaces = kallsyms_lookup_name("create_new_namespaces");
+ printk(KERN_CRIT "create_new_namespaces = %x",create_new_namespaces);
+
+ put_mnt_ns2 = kallsyms_lookup_name("put_mnt_ns");
+ printk(KERN_CRIT "Put mnt ns = %x",put_mnt_ns2);
+
+ proc_entry = create_proc_entry("lxcsu", 0644, NULL);
+ proc_entry->write_proc = lxcsu_write;
+ return ret;
+}
+
+module_init(lxcsu_init);
+module_exit(lxcsu_exit);
#include <linux/completion.h>
#include <linux/sched.h>
#include <linux/seq_file.h>
+#include <linux/file.h>
#include <linux/kprobes.h>
#include <linux/kallsyms.h>
#include <linux/nsproxy.h>
MODULE_LICENSE("GPL");
MODULE_VERSION(VERSION_STR);
-static int setns_entry(struct kretprobe_instance *ri, struct pt_regs *regs) {
- int nstype = regs->si;
- printk(KERN_CRIT "nstype: %d",nstype);
-
- if (nstype==666) regs->si = 0;
- return 0;
-}
-
-static int setns_ret(struct kretprobe_instance *ri, struct pt_regs *regs)
-{
- int nstype = regs->si;
- printk(KERN_CRIT "nstype 2: %d",nstype);
-
- return 0;
-}
-
-static struct kretprobe setns_probe = {
- .entry_handler = (kprobe_opcode_t *) setns_entry,
- .handler = (kprobe_opcode_t *) setns_ret,
- .maxactive = 20,
- .data_size = 0
-};
-
-static void __exit mntsu_exit(void)
-{
- unregister_kretprobe(&setns_probe);
- printk("Procprotect: Stopped mntsu.\n");
-}
-
-static int __init mntsu_init(void)
-{
- int ret=0;
-printk("Mntsu: starting mntsu version %s.\n",
- VERSION_STR);
-
- setns_probe.kp.addr =
- (kprobe_opcode_t *) kallsyms_lookup_name("sys_setns");
- if (!setns_probe.kp.addr) {
- printk("Couldn't find %s to plant kretprobe\n", "do_execve");
- return -1;
- }
-
- if ((ret = register_kretprobe(&setns_probe)) <0) {
- printk("register_kretprobe failed, returned %d\n", ret);
- return -1;
- }
- printk("Planted kretprobe at %p, handler addr %p\n",
- setns_probe.kp.addr, setns_probe.handler);
-
- return ret;
-}
static void *mntns_get(struct task_struct *task)
{
return ns;
}
+void (*put_mnt_ns2)(struct mnt_namespace *ns);
+
static void mntns_put(void *ns)
{
- put_mnt_ns(ns);
+ (*put_mnt_ns2)(ns);
}
static int mntns_install(struct nsproxy *nsproxy, void *ns)
return -EINVAL;
atomic_inc(&mnt_ns->count);
- put_mnt_ns(nsproxy->mnt_ns);
+ (*put_mnt_ns2)(nsproxy->mnt_ns);
nsproxy->mnt_ns = mnt_ns;
/* Find the root */
.install = mntns_install,
};
+void (*free_nsproxy2)(struct nsproxy *ns);
+struct file *(*proc_ns_fget2)(int fd);
+
+struct nsproxy * (*create_new_namespaces)(unsigned long flags,
+ struct task_struct *tsk, struct fs_struct *new_fs);
+
+void (*switch_task_namespaces2)(struct task_struct *p, struct nsproxy *new);
+
+static int setns_entry(int fd, int nstype) {
+ if (nstype==666) {
+ const struct proc_ns_operations *ops;
+ struct task_struct *tsk = current;
+ struct nsproxy *new_nsproxy;
+ struct proc_inode *ei;
+ struct file *file;
+ int err;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ file = (*proc_ns_fget2)(fd);
+ if (IS_ERR(file))
+ return PTR_ERR(file);
+
+ err = -EINVAL;
+ ei = PROC_I(file->f_dentry->d_inode);
+ ops = &mntns_operations;
+
+ new_nsproxy = (*create_new_namespaces)(0, tsk, tsk->fs);
+ if (IS_ERR(new_nsproxy)) {
+ err = PTR_ERR(new_nsproxy);
+ goto out;
+ }
+
+ err = ops->install(new_nsproxy, ei->ns);
+ if (err) {
+ (*free_nsproxy2)(new_nsproxy);
+ goto out;
+ }
+ (*switch_task_namespaces2)(tsk, new_nsproxy);
+out:
+ fput(file);
+ }
+
+ jprobe_return();
+ return 0;
+}
+
+static struct jprobe setns_jprobe = {
+ .entry = (kprobe_opcode_t *) setns_entry
+};
+
+static void __exit mntsu_exit(void)
+{
+ unregister_jprobe(&setns_jprobe);
+ printk("Procprotect: Stopped mntsu.\n");
+}
+
+static int __init mntsu_init(void)
+{
+ int ret=0;
+ printk("Mntsu: starting mntsu version %s.\n",
+ VERSION_STR);
+ proc_ns_fget2 = kallsyms_lookup_name("proc_ns_fget");
+ printk(KERN_CRIT "proc_ns_fget = %x",proc_ns_fget2);
+
+
+ free_nsproxy2 = kallsyms_lookup_name("free_nsproxy");
+ printk(KERN_CRIT "free_nsproxy = %x",free_nsproxy2);
+
+ switch_task_namespaces2 = kallsyms_lookup_name("switch_task_namespaces");
+ printk(KERN_CRIT "switch_task_namespaces = %x",switch_task_namespaces2);
+
+ create_new_namespaces = kallsyms_lookup_name("create_new_namespaces");
+ printk(KERN_CRIT "create_new_namespaces = %x",create_new_namespaces);
+
+ put_mnt_ns2 = kallsyms_lookup_name("put_mnt_ns");
+ printk(KERN_CRIT "Put mnt ns = %x",put_mnt_ns2);
+
+ setns_jprobe.kp.addr =
+ (kprobe_opcode_t *) kallsyms_lookup_name("sys_setns");
+ if (!setns_jprobe.kp.addr) {
+ printk("Couldn't find %s to plant jprobe\n", "do_execve");
+ return -1;
+ }
+
+ if ((ret = register_jprobe(&setns_jprobe)) <0) {
+ printk("register_jprobe failed, returned %d\n", ret);
+ return -1;
+ }
+
+ return ret;
+}
+
module_init(mntsu_init);
module_exit(mntsu_exit);