Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1701378 > unrolled thread
| Started by | Kees Cook <keescook@chromium.org> |
|---|---|
| First post | 2017-08-01 21:30 +0200 |
| Last post | 2017-08-01 21:30 +0200 |
| Articles | 3 — 1 participant |
Back to article view | Back to linux.kernel
[PATCH v5 00/15] exec: Use sane stack rlimit under secureexec Kees Cook <keescook@chromium.org> - 2017-08-01 21:30 +0200
[PATCH v5 02/15] exec: Correct comments about "point of no return" Kees Cook <keescook@chromium.org> - 2017-08-01 21:30 +0200
[PATCH v5 05/15] selinux: Refactor to remove bprm_secureexec hook Kees Cook <keescook@chromium.org> - 2017-08-01 21:30 +0200
| From | Kees Cook <keescook@chromium.org> |
|---|---|
| Date | 2017-08-01 21:30 +0200 |
| Subject | [PATCH v5 00/15] exec: Use sane stack rlimit under secureexec |
| Message-ID | <u9KRX-82o-3@gated-at.bofh.it> |
Based Linus's comments, my intent is to carry this series for -next and
send it as a distinct pull request during the v4.14 merge window. I'm
happy to adjust this plan as needed.
Changes from v4:
- fixed typo introduced during patch reordering
- rebased to v4.13-rc2 (mainly apparmor changes)
- fixed bisect error if building only to patch 7 and 8 under !CONFIG_SECURITY
- added more Acks/Reviews
Main cover letter contents:
As discussed with Linus and Andy, we need to reset the stack rlimit
before we do memory layouts when execing a privilege-gaining (e.g.
setuid) program. To do this, we need to know the results of the
bprm_secureexec hook before memory layouts. As it turns out, this
can be made _mostly_ trivial by collapsing bprm_secureexec into
bprm_set_creds.
The LSMs using bprm_secureexec nearly always save state between
bprm_set_creds and bprm_secureexec. In the face of multiple calls to
bprm_set_creds (via prepare_binprm() calls from binfmt_script, etc),
all LSMs except commoncap only pay attention to the first call, so
that aligns well with collapsing bprm_secureexec into bprm_set_creds.
The commoncaps, though, needs to check the _last_ bprm_set_creds, so
this series just swaps one bprm flag for another (cap_effective is no
longer needed to save state between bprm_set_creds and bprm_secureexec,
but we do need to keep a separate state, so we add the cap_elevated flag).
Once secureexec is available to setup_new_exec() before the memory
layout, we can add an rlimit sanity-check for setuid execs. (With no
need to clean up since we're past the point of no return.)
Along the way, this fixes comments, renames a variable, and consolidates
dumpability and pdeath_signal clearing, which includes some commit log
archeology to examine the subtle differences between what we had and
what we need.
Several folks have looked at this already (thank you!) but I'd appreciate
any other eyes on this to make sure it isn't broken in some special
way. Looking at the diffstat, even after all my long comments, this is
a net reduction in lines. :)
Thanks!
-Kees
----------------------------------------------------------------
Kees Cook (15):
exec: Rename bprm->cred_prepared to called_set_creds
exec: Correct comments about "point of no return"
binfmt: Introduce secureexec flag
apparmor: Refactor to remove bprm_secureexec hook
selinux: Refactor to remove bprm_secureexec hook
smack: Refactor to remove bprm_secureexec hook
commoncap: Refactor to remove bprm_secureexec hook
commoncap: Move cap_elevated calculation into bprm_set_creds
LSM: drop bprm_secureexec hook
exec: Use secureexec for setting dumpability
exec: Use secureexec for clearing pdeath_signal
smack: Remove redundant pdeath_signal clearing
exec: Consolidate dumpability logic
exec: Use sane stack rlimit under secureexec
exec: Consolidate pdeath_signal clearing
fs/binfmt_elf.c | 2 +-
fs/binfmt_elf_fdpic.c | 2 +-
fs/binfmt_flat.c | 2 +-
fs/exec.c | 56 ++++++++++++++++++++++++++++----------
include/linux/binfmts.h | 24 ++++++++++++----
include/linux/lsm_hooks.h | 14 ++++------
include/linux/security.h | 7 -----
security/apparmor/domain.c | 21 ++------------
security/apparmor/include/domain.h | 1 -
security/apparmor/include/file.h | 3 --
security/apparmor/lsm.c | 1 -
security/commoncap.c | 50 ++++++++--------------------------
security/security.c | 5 ----
security/selinux/hooks.c | 26 ++++--------------
security/smack/smack_lsm.c | 34 ++---------------------
security/tomoyo/tomoyo.c | 2 +-
16 files changed, 91 insertions(+), 159 deletions(-)
v5:
- fixed typo introduced during patch reordering
- rebased to v4.13-rc2 (mainly apparmor changes)
- fixed bisect error if building only to patch 7 and 8 under !CONFIG_SECURITY
- added more Acks/Reviews
v4:
- add {Ack,Review,Test}ed-bys
- reorder patches to move trivial refactoring to the front
- move secureexec flag set earlier in the series to setup_new_exec(); amluto
v3:
- collapse brpm_secureexec into bprm_set_creds; ebiederm.
- continue to improve various comments
v2:
- fix missed current_security() uses in LSMs.
- research/consolidate dumpability setting logic
- research/consolidate pdeath_signal clearing logic
- split up logical steps a little more for easier review (and bisection)
- fix some old broken comments
[toc] | [next] | [standalone]
| From | Kees Cook <keescook@chromium.org> |
|---|---|
| Date | 2017-08-01 21:30 +0200 |
| Subject | [PATCH v5 02/15] exec: Correct comments about "point of no return" |
| Message-ID | <u9L1F-85L-19@gated-at.bofh.it> |
| In reply to | #1701378 |
In commit 221af7f87b97 ("Split 'flush_old_exec' into two functions"),
the comment about the point of no return should have stayed in
flush_old_exec() since it refers to "bprm->mm = NULL;" line, but prior
changes in commits c89681ed7d0e ("remove steal_locks()"), and
fd8328be874f ("sanitize handling of shared descriptor tables in failing
execve()") made it look like it meant the current->sas_ss_sp line instead.
The comment was referring to the fact that once bprm->mm is NULL, all
failures from a binfmt load_binary hook (e.g. load_elf_binary), will
get SEGV raised against current. Move this comment and expand the
explanation a bit, putting it above the assignment this time, and add
details about the true nature of "point of no return" being the call
to flush_old_exec() itself.
This also removes an erroneous commet about when credentials are being
installed. That has its own dedicated function, install_exec_creds(),
which carries a similar (and correct) comment, so remove the bogus comment
where installation is not actually happening.
Cc: David Howells <dhowells@redhat.com>
Cc: Eric W. Biederman <ebiederm@xmission.com>
Signed-off-by: Kees Cook <keescook@chromium.org>
Acked-by: "Eric W. Biederman" <ebiederm@xmission.com>
Acked-by: Serge Hallyn <serge@hallyn.com>
---
fs/exec.c | 16 +++++++++++++---
1 file changed, 13 insertions(+), 3 deletions(-)
diff --git a/fs/exec.c b/fs/exec.c
index a0fff86269e4..26b98072be50 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1259,6 +1259,12 @@ void __set_task_comm(struct task_struct *tsk, const char *buf, bool exec)
perf_event_comm(tsk, exec);
}
+/*
+ * Calling this is the point of no return. None of the failures will be
+ * seen by userspace since either the process is already taking a fatal
+ * signal (via de_thread() or coredump), or will have SEGV raised
+ * (after exec_mmap()) by search_binary_handlers (see below).
+ */
int flush_old_exec(struct linux_binprm * bprm)
{
int retval;
@@ -1286,7 +1292,13 @@ int flush_old_exec(struct linux_binprm * bprm)
if (retval)
goto out;
- bprm->mm = NULL; /* We're using it now */
+ /*
+ * After clearing bprm->mm (to mark that current is using the
+ * prepared mm now), we have nothing left of the original
+ * process. If anything from here on returns an error, the check
+ * in search_binary_handler() will SEGV current.
+ */
+ bprm->mm = NULL;
set_fs(USER_DS);
current->flags &= ~(PF_RANDOMIZE | PF_FORKNOEXEC | PF_KTHREAD |
@@ -1333,7 +1345,6 @@ void setup_new_exec(struct linux_binprm * bprm)
{
arch_pick_mmap_layout(current->mm);
- /* This is the point of no return */
current->sas_ss_sp = current->sas_ss_size = 0;
if (uid_eq(current_euid(), current_uid()) && gid_eq(current_egid(), current_gid()))
@@ -1351,7 +1362,6 @@ void setup_new_exec(struct linux_binprm * bprm)
*/
current->mm->task_size = TASK_SIZE;
- /* install the new credentials */
if (!uid_eq(bprm->cred->uid, current_euid()) ||
!gid_eq(bprm->cred->gid, current_egid())) {
current->pdeath_signal = 0;
--
2.7.4
[toc] | [prev] | [next] | [standalone]
| From | Kees Cook <keescook@chromium.org> |
|---|---|
| Date | 2017-08-01 21:30 +0200 |
| Subject | [PATCH v5 05/15] selinux: Refactor to remove bprm_secureexec hook |
| Message-ID | <u9L1F-85L-29@gated-at.bofh.it> |
| In reply to | #1701378 |
The SELinux bprm_secureexec hook can be merged with the bprm_set_creds
hook since it's dealing with the same information, and all of the details
are finalized during the first call to the bprm_set_creds hook via
prepare_binprm() (subsequent calls due to binfmt_script, etc, are ignored
via bprm->called_set_creds).
Here, the test can just happen at the end of the bprm_set_creds hook,
and the bprm_secureexec hook can be dropped.
Cc: Stephen Smalley <sds@tycho.nsa.gov>
Signed-off-by: Kees Cook <keescook@chromium.org>
Acked-by: Paul Moore <paul@paul-moore.com>
Tested-by: Paul Moore <paul@paul-moore.com>
Acked-by: Serge Hallyn <serge@hallyn.com>
Reviewed-by: James Morris <james.l.morris@oracle.com>
Reviewed-by: Andy Lutomirski <luto@kernel.org>
---
security/selinux/hooks.c | 24 +++++-------------------
1 file changed, 5 insertions(+), 19 deletions(-)
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 1db40195d178..a1f5f5ddfba7 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2442,30 +2442,17 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)
/* Clear any possibly unsafe personality bits on exec: */
bprm->per_clear |= PER_CLEAR_ON_SETID;
- }
-
- return 0;
-}
-
-static int selinux_bprm_secureexec(struct linux_binprm *bprm)
-{
- const struct task_security_struct *tsec = current_security();
- u32 sid, osid;
- int atsecure = 0;
-
- sid = tsec->sid;
- osid = tsec->osid;
- if (osid != sid) {
/* Enable secure mode for SIDs transitions unless
the noatsecure permission is granted between
the two SIDs, i.e. ahp returns 0. */
- atsecure = avc_has_perm(osid, sid,
- SECCLASS_PROCESS,
- PROCESS__NOATSECURE, NULL);
+ rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
+ SECCLASS_PROCESS, PROCESS__NOATSECURE,
+ NULL);
+ bprm->secureexec |= !!rc;
}
- return !!atsecure;
+ return 0;
}
static int match_file(const void *p, struct file *file, unsigned fd)
@@ -6266,7 +6253,6 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
LSM_HOOK_INIT(bprm_set_creds, selinux_bprm_set_creds),
LSM_HOOK_INIT(bprm_committing_creds, selinux_bprm_committing_creds),
LSM_HOOK_INIT(bprm_committed_creds, selinux_bprm_committed_creds),
- LSM_HOOK_INIT(bprm_secureexec, selinux_bprm_secureexec),
LSM_HOOK_INIT(sb_alloc_security, selinux_sb_alloc_security),
LSM_HOOK_INIT(sb_free_security, selinux_sb_free_security),
--
2.7.4
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web