All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC][PATCH] exec: Use init rlimits for setuid exec
@ 2017-07-06  4:32 Kees Cook
  2017-07-06  4:59 ` Andy Lutomirski
                   ` (3 more replies)
  0 siblings, 4 replies; 36+ messages in thread
From: Kees Cook @ 2017-07-06  4:32 UTC (permalink / raw)
  To: Linus Torvalds, Andy Lutomirski
  Cc: Michal Hocko, Ben Hutchings, Willy Tarreau, Hugh Dickins,
	Oleg Nesterov, Jason A. Donenfeld, Rik van Riel, Larry Woodman,
	Kirill A. Shutemov, Tony Luck, James E.J. Bottomley,
	Helge Diller, James Hogan, Laura Abbott, Greg KH, security,
	Qualys Security Advisory, LKML, Ximin Luo

In an attempt to provide sensible rlimit defaults for setuid execs, this
inherits the namespace's init rlimits:

$ ulimit -s
8192
$ ulimit -s unlimited
$ /bin/sh -c 'ulimit -s'
unlimited
$ sudo /bin/sh -c 'ulimit -s'
8192

This is modified from Brad Spengler/PaX Team's hard-coded setuid exec
stack rlimit (8MB) in the last public patch of grsecurity/PaX based on
my understanding of the code. Changes or omissions from the original
code are mine and don't reflect the original grsecurity/PaX code.

Signed-off-by: Kees Cook <keescook@chromium.org>
---
Instead of copying all rlimits, we could also pick specific ones to copy
(e.g. RLIMIT_STACK, or ones from Andy's list) or exclude from copying
(probably better to blacklist than whitelist).

I think this is the right way to find the ns init task, but maybe it
needs locking?
---
 fs/exec.c | 34 ++++++++++++++++++++++++++++++----
 1 file changed, 30 insertions(+), 4 deletions(-)

diff --git a/fs/exec.c b/fs/exec.c
index 904199086490..80e8b2bd4284 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1675,6 +1675,12 @@ static int exec_binprm(struct linux_binprm *bprm)
 	return ret;
 }
 
+static inline bool is_setuid_exec(struct linux_binprm *bprm)
+{
+	return (!uid_eq(bprm->cred->euid, current_euid()) ||
+		!gid_eq(bprm->cred->egid, current_egid()));
+}
+
 /*
  * sys_execve() executes a new program.
  */
@@ -1687,6 +1693,7 @@ static int do_execveat_common(int fd, struct filename *filename,
 	struct linux_binprm *bprm;
 	struct file *file;
 	struct files_struct *displaced;
+	struct rlimit saved_rlim[RLIM_NLIMITS];
 	int retval;
 
 	if (IS_ERR(filename))
@@ -1771,24 +1778,38 @@ static int do_execveat_common(int fd, struct filename *filename,
 	if (retval < 0)
 		goto out;
 
+	/*
+	 * From here forward, we've got credentials set up and we're
+	 * using resources, so do rlimit replacement before we start
+	 * copying strings. (Note that the RLIMIT_NPROC check has
+	 * already happened.)
+	 */
+	BUILD_BUG_ON(sizeof(saved_rlim) != sizeof(current->signal->rlim));
+	if (is_setuid_exec(bprm)) {
+		memcpy(saved_rlim, current->signal->rlim, sizeof(saved_rlim));
+		memcpy(current->signal->rlim,
+		       task_active_pid_ns(current)->child_reaper->signal->rlim,
+		       sizeof(current->signal->rlim));
+	}
+
 	retval = copy_strings_kernel(1, &bprm->filename, bprm);
 	if (retval < 0)
-		goto out;
+		goto out_restore;
 
 	bprm->exec = bprm->p;
 	retval = copy_strings(bprm->envc, envp, bprm);
 	if (retval < 0)
-		goto out;
+		goto out_restore;
 
 	retval = copy_strings(bprm->argc, argv, bprm);
 	if (retval < 0)
-		goto out;
+		goto out_restore;
 
 	would_dump(bprm, bprm->file);
 
 	retval = exec_binprm(bprm);
 	if (retval < 0)
-		goto out;
+		goto out_restore;
 
 	/* execve succeeded */
 	current->fs->in_exec = 0;
@@ -1802,6 +1823,11 @@ static int do_execveat_common(int fd, struct filename *filename,
 		put_files_struct(displaced);
 	return retval;
 
+out_restore:
+	if (is_setuid_exec(bprm)) {
+		memcpy(current->signal->rlim, saved_rlim, sizeof(saved_rlim));
+	}
+
 out:
 	if (bprm->mm) {
 		acct_arg_size(bprm, 0);
-- 
2.7.4


-- 
Kees Cook
Pixel Security

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

end of thread, other threads:[~2017-07-12 23:52 UTC | newest]

Thread overview: 36+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-07-06  4:32 [RFC][PATCH] exec: Use init rlimits for setuid exec Kees Cook
2017-07-06  4:59 ` Andy Lutomirski
2017-07-06 12:45   ` Eric W. Biederman
2017-07-06 15:27     ` Andy Lutomirski
2017-07-06  5:47 ` Willy Tarreau
2017-07-06 12:38 ` Eric W. Biederman
2017-07-06 15:30   ` Andy Lutomirski
2017-07-06 16:34 ` Linus Torvalds
2017-07-06 16:50   ` Linus Torvalds
2017-07-06 17:29   ` Kees Cook
2017-07-06 17:52     ` Linus Torvalds
2017-07-06 19:12       ` Kees Cook
2017-07-07  4:48         ` Andy Lutomirski
2017-07-07  5:03           ` Linus Torvalds
2017-07-07  5:10           ` Kees Cook
2017-07-07  5:15             ` Kees Cook
2017-07-07  5:36               ` Andy Lutomirski
2017-07-07  5:45                 ` Kees Cook
2017-07-07  6:02                   ` Linus Torvalds
2017-07-07  6:10                     ` Kees Cook
2017-07-07 16:06                       ` Linus Torvalds
2017-07-07 18:28                         ` Kees Cook
2017-07-07 14:48                   ` Andy Lutomirski
2017-07-07  5:39               ` Linus Torvalds
2017-07-07  5:49                 ` Kees Cook
2017-07-07  6:40                   ` Kees Cook
2017-07-07 16:22                     ` Linus Torvalds
2017-07-07 18:27                       ` Kees Cook
2017-07-10  8:44         ` Michal Hocko
2017-07-10 16:12           ` Kees Cook
2017-07-10 16:18             ` Linus Torvalds
2017-07-10 16:52               ` Willy Tarreau
2017-07-10 16:27             ` Michal Hocko
2017-07-10 18:16               ` Michal Hocko
2017-07-10 18:29                 ` Rik van Riel
2017-07-12 23:50   ` Alan Cox

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.