summaryrefslogtreecommitdiff
path: root/include/linux
diff options
context:
space:
mode:
authorAndrew Morton <akpm@osdl.org>2004-04-26 08:55:51 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2004-04-26 08:55:51 -0700
commit10c189cdc6b127955068fcfb812d021b5ed32be6 (patch)
treefa62ae052c2ccd3861534987bd23b18944431db2 /include/linux
parentf6cfe4f8ce4b5bc13a0ade4daf267fdf5b0e61c9 (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.h19
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)