diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-02-07 05:52:55 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-02-07 05:52:55 +0300 |
commit | ccfef64621ef1e8c7726581b38eb8b98fd2a8afb (patch) | |
tree | 74d99dcecbd7adad1dcd5d61fac408855b43a267 /fs | |
parent | ae1a25da8448271a99745da03100d5299575a269 (diff) | |
parent | 0bf2f3aec5474da80a60e1baca629af87ecb67b6 (diff) | |
download | linux-ccfef64621ef1e8c7726581b38eb8b98fd2a8afb.tar.xz |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6:
CRED: Fix SUID exec regression
Diffstat (limited to 'fs')
-rw-r--r-- | fs/compat.c | 2 | ||||
-rw-r--r-- | fs/exec.c | 28 | ||||
-rw-r--r-- | fs/internal.h | 2 |
3 files changed, 24 insertions, 8 deletions
diff --git a/fs/compat.c b/fs/compat.c index 65a070e705ab..d0145ca27572 100644 --- a/fs/compat.c +++ b/fs/compat.c @@ -1407,7 +1407,7 @@ int compat_do_execve(char * filename, bprm->cred = prepare_exec_creds(); if (!bprm->cred) goto out_unlock; - check_unsafe_exec(bprm); + check_unsafe_exec(bprm, current->files); file = open_exec(filename); retval = PTR_ERR(file); diff --git a/fs/exec.c b/fs/exec.c index 0dd60a01f1b4..929b58004b7e 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -1049,16 +1049,32 @@ EXPORT_SYMBOL(install_exec_creds); * - the caller must hold current->cred_exec_mutex to protect against * PTRACE_ATTACH */ -void check_unsafe_exec(struct linux_binprm *bprm) +void check_unsafe_exec(struct linux_binprm *bprm, struct files_struct *files) { - struct task_struct *p = current; + struct task_struct *p = current, *t; + unsigned long flags; + unsigned n_fs, n_files, n_sighand; bprm->unsafe = tracehook_unsafe_exec(p); - if (atomic_read(&p->fs->count) > 1 || - atomic_read(&p->files->count) > 1 || - atomic_read(&p->sighand->count) > 1) + n_fs = 1; + n_files = 1; + n_sighand = 1; + lock_task_sighand(p, &flags); + for (t = next_thread(p); t != p; t = next_thread(t)) { + if (t->fs == p->fs) + n_fs++; + if (t->files == files) + n_files++; + n_sighand++; + } + + if (atomic_read(&p->fs->count) > n_fs || + atomic_read(&p->files->count) > n_files || + atomic_read(&p->sighand->count) > n_sighand) bprm->unsafe |= LSM_UNSAFE_SHARE; + + unlock_task_sighand(p, &flags); } /* @@ -1273,7 +1289,7 @@ int do_execve(char * filename, bprm->cred = prepare_exec_creds(); if (!bprm->cred) goto out_unlock; - check_unsafe_exec(bprm); + check_unsafe_exec(bprm, displaced); file = open_exec(filename); retval = PTR_ERR(file); diff --git a/fs/internal.h b/fs/internal.h index 53af885f1732..0d8ac497b3d5 100644 --- a/fs/internal.h +++ b/fs/internal.h @@ -43,7 +43,7 @@ extern void __init chrdev_init(void); /* * exec.c */ -extern void check_unsafe_exec(struct linux_binprm *); +extern void check_unsafe_exec(struct linux_binprm *, struct files_struct *); /* * namespace.c |