first attempt at making chroot nestable
Subsystems (4)
RFC PATCH 1/1 first attempt at making chroot nestable
This is a first attempt at a change that lets kernel's chroot's and wont let you use an fd to break out of a chroot, it will only let you get as far as the root as of when you got the fd (or possibly even less).
I've discussed the algorithm I've implemented below a couple times already on the list, but I doubt my coding style is up to snuff, so criticize away on that. I also haven't had a chance to test it yet (need to get into school to use the test machines), so all I know is that it compiles w/o any warnings.
please comment away (as well as tell me if I did right my inline'ing the patch, or if I should attach it, if it matters the mail client I normally use is evolution)
thanks,
shaya
fs/open.c +2 -0
@@ -475,10 +475,12 @@set_fs_root (current->fs, nd.mnt, nd.dentry);set_fs_altroot (); +write_lock (¤t->fs->lock); cp->mnt =mntget (nd.mnt); cp->root =dget (nd.dentry); cp->next = current->cp; current->cp = cp; +write_unlock (¤t>fs->lock); error =0 ; dput_and_out:
include/linux/sched.h +2 -0
@@ -418,6 +418,7 @@/* journalling filesystem info */ void *journal_info; +struct chroot_point *cp; };/*
@@ -511,6 +512,7 @@ blocked: {{0}}, \ alloc_lock: SPIN_LOCK_UNLOCKED, \ journal_info: NULL, \ + cp: NULL, \ }
kernel/exit.c +26 -0
@@ -286,6 +286,31 @@__exit_fs (tsk); } +static inline void __exit_chroot (struct task_struct *tsk) +{ +struct chroot_point *cur, *next; + + cur = tsk->cp; + +task_lock (tsk); + tsk->cp =NULL ; +task_unlock (tsk); + +while (cur) + { +kfree (cur->mnt); +kfree (cur->root); + next = cur->next; +kfree (cur); + cur = next; + } +} + +void exit_chroot (struct task_struct *tsk) +{ +__exit_chroot (tsk); +} +/* * We can use these to temporarily drop into * "lazy TLB" mode and back.
@@ -459,6 +484,7 @@sem_exit ();__exit_files (tsk);__exit_fs (tsk); +__exit_chroot (tsk);exit_namespace (tsk);exit_sighand (tsk);exit_thread ();
kernel/fork.c +23 -0
@@ -580,6 +580,7 @@int retval;struct task_struct *p;struct completion vfork; +struct chroot_point *cp_p, *cp_c;if ((clone_flags & (CLONE_NEWNS |CLONE_FS )) == (CLONE_NEWNS |CLONE_FS ))return -EINVAL ;
@@ -726,6 +727,28 @@ p->tgid = retval;INIT_LIST_HEAD (&p->thread_group); +/* copy chroot_point list from parent to child */ + cp_p = current->cp; + cp_c =NULL ; + +if (cp_p) + cp_c = (struct chroot_point *)kmalloc (sizeof (struct chroot_point ),GFP_KERNEL ); + + p->cp = cp_c; + +while (cp_p) + { + cp_c->root =dget (cp_p->root); + cp_c->mnt =mntget (cp_p->mnt); + cp_c->next =NULL ; + +if (cp_p->next) { + cp_c->next = (struct chroot_point *)kmalloc (sizeof (struct chroot_point ),GFP_KERNEL ); + cp_c = cp_c->next; + } + cp_p = cp_p->next; + } +/* Need tasklist lock for parent etc handling! */ write_lock_irq (&tasklist_lock);