All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] Patches to enable chroot for all users
@ 2013-03-20 13:09 tal.tchwella
  2013-03-20 13:09 ` [PATCH 1/3] enabled " tal.tchwella
                   ` (3 more replies)
  0 siblings, 4 replies; 6+ messages in thread
From: tal.tchwella @ 2013-03-20 13:09 UTC (permalink / raw)
  To: linux-kernel; +Cc: tchwella

From: Tal Tchwella <tchwella@mit.edu>

I want to suggest adding chroot capability to all users.
The following patches enable that capability, while considering the security mechanism needed to disable escape routes for chroots by non-root users,
and keeping chroot backward-compatible for root users.
The first patch establishes the concept of multi-user chroot, while disabling checks for root user in the chroot process.
The second patch checks whether a fd that is sent to a chroot application by a non-root user refers to a directory. 
If that is the case, that fd is skipped, to disable an escape route. 
The third patch disables the option for applications that have open fds to directories to be chrooted by a non-root user.

These patches were applied and test on linux-kernel 3.2.0-31-generic.

Any comments, feedback and suggestions are appreciated!

Thanks,
Tal


Tal Tchwella (3):
  enabled chroot for all users
  socket checks for uds fds transfer
  open fds check when starting chroot

 fs/exec.c             |    3 +++
 fs/open.c             |   32 ++++++++++++++++++++++++++++++--
 include/linux/sched.h |   12 ++++++++++++
 init/main.c           |    1 +
 kernel/fork.c         |    2 ++
 net/core/scm.c        |    9 +++++++++
 6 files changed, 57 insertions(+), 2 deletions(-)

-- 
1.7.9.5


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 1/3] enabled chroot for all users
  2013-03-20 13:09 [PATCH 0/3] Patches to enable chroot for all users tal.tchwella
@ 2013-03-20 13:09 ` tal.tchwella
  2013-03-20 13:09 ` [PATCH 2/3] socket checks for uds fds transfer tal.tchwella
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 6+ messages in thread
From: tal.tchwella @ 2013-03-20 13:09 UTC (permalink / raw)
  To: linux-kernel; +Cc: tchwella

From: Tal Tchwella <tchwella@mit.edu>

This patch enables chroot for all users, not just root users,
by disabling the appropriate checks in fs/open.c.
It also disables nested chroots by non-root users,
so they will not be able to break out of a chroot using classic techniques.

Signed-off-by: Tal Tchwella <tchwella@mit.edu>
---
 fs/exec.c             |    3 +++
 fs/open.c             |    8 ++++++--
 include/linux/sched.h |   12 ++++++++++++
 init/main.c           |    1 +
 kernel/fork.c         |    2 ++
 5 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/fs/exec.c b/fs/exec.c
index 7d27def..e2303ef 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1299,6 +1299,9 @@ int prepare_binprm(struct linux_binprm *bprm)
 	    !current->no_new_privs) {
 		/* Set-uid? */
 		if (mode & S_ISUID) {
+			/* chroot by a regular, non root, user? */
+			if (current->user_chroot == CHROOT_USER_MODE)
+				return -EACCES;
 			bprm->per_clear |= PER_CLEAR_ON_SETID;
 			bprm->cred->euid = inode->i_uid;
 		}
diff --git a/fs/open.c b/fs/open.c
index a47a0a7..82832d8 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -435,9 +435,13 @@ SYSCALL_DEFINE1(chroot, const char __user *, filename)
 	if (error)
 		goto dput_and_out;
 
-	error = -EPERM;
+	/* Are we in a nested chroot by a regular, non root, user? */
+	if (current->user_chroot != CHROOT_USER_MODE)
+		current->user_chroot = CHROOT_ROOT_MODE;
+
 	if (!capable(CAP_SYS_CHROOT))
-		goto dput_and_out;
+		current->user_chroot = CHROOT_USER_MODE;
+
 	error = security_path_chroot(&path);
 	if (error)
 		goto dput_and_out;
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 9e960d4..315e6fe 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -30,6 +30,16 @@
 #define CLONE_NEWNET		0x40000000	/* New network namespace */
 #define CLONE_IO		0x80000000	/* Clone io context */
 
+ /*
+  * chroot syscall Modes: INIT, USER, ROOT
+  * Init mode is to be used only by main.
+  * User mode is initialized when a non-root user tries to enter chroot mode.
+  * ROOT mode is the normal mode of operation for chroot.
+  */
+#define CHROOT_INIT		0
+#define CHROOT_USER_MODE	1
+#define CHROOT_ROOT_MODE	2
+
 /*
  * Scheduling policies
  */
@@ -1232,6 +1242,8 @@ struct task_struct {
 	unsigned int flags;	/* per process flags, defined below */
 	unsigned int ptrace;
 
+	unsigned int user_chroot;
+
 #ifdef CONFIG_SMP
 	struct llist_node wake_entry;
 	int on_cpu;
diff --git a/init/main.c b/init/main.c
index 0ec0731..044c655 100644
--- a/init/main.c
+++ b/init/main.c
@@ -781,6 +781,7 @@ static noinline int init_post(void)
 
 
 	current->signal->flags |= SIGNAL_UNKILLABLE;
+	current->user_chroot = CHROOT_INIT;
 
 	if (ramdisk_execute_command) {
 		run_init_process(ramdisk_execute_command);
diff --git a/kernel/fork.c b/kernel/fork.c
index 0269b2a..7f6d662 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -276,6 +276,8 @@ static struct task_struct *dup_task_struct(struct task_struct *orig)
 	if (err)
 		goto out;
 
+	tsk->user_chroot = orig->user_chroot;
+
 	tsk->stack = ti;
 
 	setup_thread_stack(tsk, orig);
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 2/3] socket checks for uds fds transfer
  2013-03-20 13:09 [PATCH 0/3] Patches to enable chroot for all users tal.tchwella
  2013-03-20 13:09 ` [PATCH 1/3] enabled " tal.tchwella
@ 2013-03-20 13:09 ` tal.tchwella
  2013-03-20 13:09 ` [PATCH 3/3] open fds check when starting chroot tal.tchwella
  2013-03-20 15:35 ` [PATCH 0/3] Patches to enable chroot for all users Casey Schaufler
  3 siblings, 0 replies; 6+ messages in thread
From: tal.tchwella @ 2013-03-20 13:09 UTC (permalink / raw)
  To: linux-kernel; +Cc: tchwella

From: Tal Tchwella <tchwella@mit.edu>

This patch checks whether another user is trying to send a chrooted application by
a non-root user a fd to a directory, which will allow it to escape.
By preventing this kind of fd transfer to chrooted applications by non-root users,
certain security risks are mitigated.

Signed-off-by: Tal Tchwella <tchwella@mit.edu>
---
 net/core/scm.c |    9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/net/core/scm.c b/net/core/scm.c
index ff52ad0..e505528 100644
--- a/net/core/scm.c
+++ b/net/core/scm.c
@@ -282,6 +282,15 @@ void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm)
 	for (i=0, cmfptr=(__force int __user *)CMSG_DATA(cm); i<fdmax;
 	     i++, cmfptr++)
 	{
+		/*
+		 * Restricts passing of fds via unix domain sockets to non-root
+		 * chrooted applications to files and does not allow directories
+		 * to be passed.
+		 */
+		if (current->user_chroot == CHROOT_USER_MODE) {
+			if (S_ISDIR(fp[i]->f_dentry->d_inode->i_mode))
+				continue;
+		}
 		int new_fd;
 		err = security_file_receive(fp[i]);
 		if (err)
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 3/3] open fds check when starting chroot
  2013-03-20 13:09 [PATCH 0/3] Patches to enable chroot for all users tal.tchwella
  2013-03-20 13:09 ` [PATCH 1/3] enabled " tal.tchwella
  2013-03-20 13:09 ` [PATCH 2/3] socket checks for uds fds transfer tal.tchwella
@ 2013-03-20 13:09 ` tal.tchwella
  2013-03-20 15:35 ` [PATCH 0/3] Patches to enable chroot for all users Casey Schaufler
  3 siblings, 0 replies; 6+ messages in thread
From: tal.tchwella @ 2013-03-20 13:09 UTC (permalink / raw)
  To: linux-kernel; +Cc: tchwella

From: Tal Tchwella <tchwella@mit.edu>

This patch checks for open fds to directories when a non-root user tries to chroot,
and does not allow that user to chroot if the application has an open fd to a directory
because the appilcation has an escape path with that fd.

Signed-off-by: Tal Tchwella <tchwella@mit.edu>
---
 fs/open.c |   24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/fs/open.c b/fs/open.c
index 82832d8..6dc6443 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -426,6 +426,30 @@ SYSCALL_DEFINE1(chroot, const char __user *, filename)
 {
 	struct path path;
 	int error;
+	struct files_struct *current_files;
+	struct fdtable *files_table;
+	int i = 0;
+
+	error = -EPERM;
+	/*
+	 * Checks to see if there are open file descriptors to directories
+	 * when a user that does not have the chroot capability
+	 * tries to chroot. Since chroot is availble to all users,
+	 * want to eliminate ways to break out. The second part
+	 * of the if statement, is true by default,
+	 * since during the initilization of the kernel, it
+	 * goes into chroot mode.
+	 */
+	if (!capable(CAP_SYS_CHROOT) && current->user_chroot != CHROOT_INIT) {
+		current_files = current->files;
+		files_table = files_fdtable(current_files);
+		while (files_table->fd[i] != NULL) {
+			if (S_ISDIR(files_table->fd[i]->
+				f_dentry->d_inode->i_mode))
+					 goto out;
+			i++;
+		}
+	}
 
 	error = user_path_dir(filename, &path);
 	if (error)
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH 0/3] Patches to enable chroot for all users
  2013-03-20 13:09 [PATCH 0/3] Patches to enable chroot for all users tal.tchwella
                   ` (2 preceding siblings ...)
  2013-03-20 13:09 ` [PATCH 3/3] open fds check when starting chroot tal.tchwella
@ 2013-03-20 15:35 ` Casey Schaufler
  3 siblings, 0 replies; 6+ messages in thread
From: Casey Schaufler @ 2013-03-20 15:35 UTC (permalink / raw)
  To: tal.tchwella; +Cc: linux-kernel, tchwella, Casey Schaufler

On 3/20/2013 6:09 AM, tal.tchwella@gmail.com wrote:
> From: Tal Tchwella <tchwella@mit.edu>
>
> I want to suggest adding chroot capability to all users.

It is much too easy to create an environment for
tricking privileged programs using chroot to allow
unprivileged processes to use chroot. /etc/shadow
is your trivial attack surface.

> The following patches enable that capability, while considering the security mechanism needed to disable escape routes for chroots by non-root users,
> and keeping chroot backward-compatible for root users.
> The first patch establishes the concept of multi-user chroot, while disabling checks for root user in the chroot process.
> The second patch checks whether a fd that is sent to a chroot application by a non-root user refers to a directory. 
> If that is the case, that fd is skipped, to disable an escape route. 
> The third patch disables the option for applications that have open fds to directories to be chrooted by a non-root user.
>
> These patches were applied and test on linux-kernel 3.2.0-31-generic.
>
> Any comments, feedback and suggestions are appreciated!
>
> Thanks,
> Tal
>
>
> Tal Tchwella (3):
>   enabled chroot for all users
>   socket checks for uds fds transfer
>   open fds check when starting chroot
>
>  fs/exec.c             |    3 +++
>  fs/open.c             |   32 ++++++++++++++++++++++++++++++--
>  include/linux/sched.h |   12 ++++++++++++
>  init/main.c           |    1 +
>  kernel/fork.c         |    2 ++
>  net/core/scm.c        |    9 +++++++++
>  6 files changed, 57 insertions(+), 2 deletions(-)
>


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 3/3] open fds check when starting chroot
  2013-03-20 12:53 Tal Tchwella
@ 2013-03-20 12:53 ` Tal Tchwella
  0 siblings, 0 replies; 6+ messages in thread
From: Tal Tchwella @ 2013-03-20 12:53 UTC (permalink / raw)
  To: linux-kernel; +Cc: tchwella

This patch checks for open fds to directories when a non-root user tries to chroot,
and does not allow that user to chroot if the application has an open fd to a directory
because the appilcation has an escape path with that fd.

Signed-off-by: Tal Tchwella <tchwella@mit.edu>
---
 fs/open.c |   24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/fs/open.c b/fs/open.c
index 82832d8..6dc6443 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -426,6 +426,30 @@ SYSCALL_DEFINE1(chroot, const char __user *, filename)
 {
 	struct path path;
 	int error;
+	struct files_struct *current_files;
+	struct fdtable *files_table;
+	int i = 0;
+
+	error = -EPERM;
+	/*
+	 * Checks to see if there are open file descriptors to directories
+	 * when a user that does not have the chroot capability
+	 * tries to chroot. Since chroot is availble to all users,
+	 * want to eliminate ways to break out. The second part
+	 * of the if statement, is true by default,
+	 * since during the initilization of the kernel, it
+	 * goes into chroot mode.
+	 */
+	if (!capable(CAP_SYS_CHROOT) && current->user_chroot != CHROOT_INIT) {
+		current_files = current->files;
+		files_table = files_fdtable(current_files);
+		while (files_table->fd[i] != NULL) {
+			if (S_ISDIR(files_table->fd[i]->
+				f_dentry->d_inode->i_mode))
+					 goto out;
+			i++;
+		}
+	}
 
 	error = user_path_dir(filename, &path);
 	if (error)
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2013-03-20 15:35 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-03-20 13:09 [PATCH 0/3] Patches to enable chroot for all users tal.tchwella
2013-03-20 13:09 ` [PATCH 1/3] enabled " tal.tchwella
2013-03-20 13:09 ` [PATCH 2/3] socket checks for uds fds transfer tal.tchwella
2013-03-20 13:09 ` [PATCH 3/3] open fds check when starting chroot tal.tchwella
2013-03-20 15:35 ` [PATCH 0/3] Patches to enable chroot for all users Casey Schaufler
  -- strict thread matches above, loose matches on Subject: below --
2013-03-20 12:53 Tal Tchwella
2013-03-20 12:53 ` [PATCH 3/3] open fds check when starting chroot Tal Tchwella

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.