diff options
| author | Andrew Morton <akpm@osdl.org> | 2004-04-26 08:55:51 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2004-04-26 08:55:51 -0700 |
| commit | 10c189cdc6b127955068fcfb812d021b5ed32be6 (patch) | |
| tree | fa62ae052c2ccd3861534987bd23b18944431db2 /include/linux | |
| parent | f6cfe4f8ce4b5bc13a0ade4daf267fdf5b0e61c9 (diff) | |
[PATCH] credentials locking fix
From: Chris Wright <chrisw@osdl.org>
Contributions from:
Stephen Smalley <sds@epoch.ncsc.mil>
Andy Lutomirski <luto@stanford.edu>
During exec the LSM bprm_apply_creds() hooks may tranisition the program to a
new security context (like setuid binaries). The security context of the new
task is dependent on state such as if the task is being ptraced.
ptrace_detach() doesn't take the task_lock() when clearing task->ptrace. So
there is a race possible where a process starts off being ptraced, the
malicious ptracer detaches and if any checks agains task->ptrace are done more
than once, the results are indeterminate.
This patch ensures task_lock() is held while bprm_apply_creds() hooks are
called, keeping it safe against ptrace_attach() races. Additionally, tests
against task->ptrace (and ->fs->count, ->files->count and ->sighand->count all
of which signify potential unsafe resource sharing during a security context
transition) are done only once the results are passed down to hooks, making it
safe against ptrace_detach() races.
Additionally:
- s/must_must_not_trace_exec/unsafe_exec/
- move unsafe_exec() call above security_bprm_apply_creds() call rather than
in call for readability.
- fix dummy hook to honor the case where root is ptracing
- couple minor formatting/spelling fixes
Diffstat (limited to 'include/linux')
| -rw-r--r-- | include/linux/security.h | 19 |
1 files changed, 13 insertions, 6 deletions
diff --git a/include/linux/security.h b/include/linux/security.h index 2d16f6577669..5bc1ac328495 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -44,7 +44,7 @@ extern int cap_capget (struct task_struct *target, kernel_cap_t *effective, kern extern int cap_capset_check (struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted); extern void cap_capset_set (struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted); extern int cap_bprm_set_security (struct linux_binprm *bprm); -extern void cap_bprm_apply_creds (struct linux_binprm *bprm); +extern void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe); extern int cap_bprm_secureexec(struct linux_binprm *bprm); extern int cap_inode_setxattr(struct dentry *dentry, char *name, void *value, size_t size, int flags); extern int cap_inode_removexattr(struct dentry *dentry, char *name); @@ -86,6 +86,11 @@ struct nfsctl_arg; struct sched_param; struct swap_info_struct; +/* bprm_apply_creds unsafe reasons */ +#define LSM_UNSAFE_SHARE 1 +#define LSM_UNSAFE_PTRACE 2 +#define LSM_UNSAFE_PTRACE_CAP 4 + #ifdef CONFIG_SECURITY /** @@ -112,6 +117,8 @@ struct swap_info_struct; * also perform other state changes on the process (e.g. closing open * file descriptors to which access is no longer granted if the attributes * were changed). + * bprm_apply_creds is called under task_lock. @unsafe indicates various + * reasons why it may be unsafe to change security state. * @bprm contains the linux_binprm structure. * @bprm_set_security: * Save security information in the bprm->security field, typically based @@ -1026,7 +1033,7 @@ struct security_operations { int (*bprm_alloc_security) (struct linux_binprm * bprm); void (*bprm_free_security) (struct linux_binprm * bprm); - void (*bprm_apply_creds) (struct linux_binprm * bprm); + void (*bprm_apply_creds) (struct linux_binprm * bprm, int unsafe); int (*bprm_set_security) (struct linux_binprm * bprm); int (*bprm_check_security) (struct linux_binprm * bprm); int (*bprm_secureexec) (struct linux_binprm * bprm); @@ -1290,9 +1297,9 @@ static inline void security_bprm_free (struct linux_binprm *bprm) { security_ops->bprm_free_security (bprm); } -static inline void security_bprm_apply_creds (struct linux_binprm *bprm) +static inline void security_bprm_apply_creds (struct linux_binprm *bprm, int unsafe) { - security_ops->bprm_apply_creds (bprm); + security_ops->bprm_apply_creds (bprm, unsafe); } static inline int security_bprm_set (struct linux_binprm *bprm) { @@ -1962,9 +1969,9 @@ static inline int security_bprm_alloc (struct linux_binprm *bprm) static inline void security_bprm_free (struct linux_binprm *bprm) { } -static inline void security_bprm_apply_creds (struct linux_binprm *bprm) +static inline void security_bprm_apply_creds (struct linux_binprm *bprm, int unsafe) { - cap_bprm_apply_creds (bprm); + cap_bprm_apply_creds (bprm, unsafe); } static inline int security_bprm_set (struct linux_binprm *bprm) |
