diff -Nur linux-2.6.11-rc3/fs/open.c linux-2.6.11-rc3.chroot-lsm/fs/open.c --- linux-2.6.11-rc3/fs/open.c 2005-02-06 21:40:40.000000000 +0100 +++ linux-2.6.11-rc3.chroot-lsm/fs/open.c 2005-02-08 15:29:40.544611912 +0100 @@ -578,9 +578,9 @@ error = permission(nd.dentry->d_inode,MAY_EXEC,&nd); if (error) goto dput_and_out; - - error = -EPERM; - if (!capable(CAP_SYS_CHROOT)) + + error = security_chroot(&nd); + if (error) goto dput_and_out; set_fs_root(current->fs, nd.mnt, nd.dentry); diff -Nur linux-2.6.11-rc3/include/linux/security.h linux-2.6.11-rc3.chroot-lsm/include/linux/security.h --- linux-2.6.11-rc3/include/linux/security.h 2005-02-06 21:40:27.000000000 +0100 +++ linux-2.6.11-rc3.chroot-lsm/include/linux/security.h 2005-02-08 15:30:54.434378960 +0100 @@ -1008,6 +1008,10 @@ * @ts contains new time * @tz contains new timezone * Return 0 if permission is granted. + * @chroot: + * Check permission to change the current root by sys_chroot() syscall. + * @nd contains the nameidata struct passed by sys_chroot() + * Return 0 if permission is granted. * @vm_enough_memory: * Check permissions for allocating a new virtual mapping. * @pages contains the number of pages. @@ -1040,6 +1044,7 @@ int (*acct) (struct file * file); int (*sysctl) (struct ctl_table * table, int op); int (*capable) (struct task_struct * tsk, int cap); + int (*chroot) (struct nameidata * nd); int (*quotactl) (int cmds, int type, int id, struct super_block * sb); int (*quota_on) (struct dentry * dentry); int (*syslog) (int type); @@ -1304,6 +1309,10 @@ return security_ops->settime(ts, tz); } +static inline int security_chroot(struct nameidata *nd) +{ + return security_ops->chroot(nd); +} static inline int security_vm_enough_memory(long pages) { @@ -1986,6 +1995,14 @@ return cap_settime(ts, tz); } +static inline int security_chroot(struct nameidata *nd) +{ + if (!capable(CAP_SYS_CHROOT)) + return -EPERM; + + return 0; +} + static inline int security_vm_enough_memory(long pages) { return cap_vm_enough_memory(pages); diff -Nur linux-2.6.11-rc3/security/dummy.c linux-2.6.11-rc3.chroot-lsm/security/dummy.c --- linux-2.6.11-rc3/security/dummy.c 2005-02-06 21:40:57.000000000 +0100 +++ linux-2.6.11-rc3.chroot-lsm/security/dummy.c 2005-02-08 15:29:55.034409128 +0100 @@ -101,6 +101,14 @@ return 0; } +static int dummy_chroot(struct nameidata *nd) +{ + if (!capable(CAP_SYS_CHROOT)) + return -EPERM; + + return 0; +} + static int dummy_settime(struct timespec *ts, struct timezone *tz) { if (!capable(CAP_SYS_TIME)) @@ -858,6 +866,7 @@ set_to_dummy_if_null(ops, sysctl); set_to_dummy_if_null(ops, syslog); set_to_dummy_if_null(ops, settime); + set_to_dummy_if_null(ops, chroot); set_to_dummy_if_null(ops, vm_enough_memory); set_to_dummy_if_null(ops, bprm_alloc_security); set_to_dummy_if_null(ops, bprm_free_security);