summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2020-05-31 23:02:36 +0300
committerEric W. Biederman <ebiederm@xmission.com>2020-05-31 23:02:36 +0300
commit3977e285ee89a94699255dbbf6eeea13889a1083 (patch)
tree378ea4452668d448b0834fd08008a5f81619f1fd /include
parente32f8879019535b899bc3d51f371e17526f208d1 (diff)
parent56305aa9b6fab91a5555a45796b79c1b0a6353d1 (diff)
downloadlinux-3977e285ee89a94699255dbbf6eeea13889a1083.tar.xz
exec: Remove the recomputation of bprm->cred
Recomputing the uids, gids, capabilities, and related flags each time a new bprm->file is set is error prone and unnecessary. This set of changes splits per_clear temporarily into two separate variables. This is the last change necessary to ensure that everything that is computed from brpm->file in bprm->cred is recomputed every time a new bprm->file is set. Then the code is refactored to compute bprm->cred from bprm->file when the final brpm->file is known, removing the need for recomputation entirely. Doing this in two steps should allow anyone who has problems later to bisect and tell if it was the semantic change or the refactoring that caused them problems. Eric W. Biederman (2): exec: Add a per bprm->file version of per_clear exec: Compute file based creds only once fs/binfmt_misc.c | 2 +- fs/exec.c | 57 ++++++++++++++++++------------------------- include/linux/binfmts.h | 9 ++----- include/linux/lsm_hook_defs.h | 2 +- include/linux/lsm_hooks.h | 22 +++++++++-------- include/linux/security.h | 9 ++++--- security/commoncap.c | 22 +++++++++-------- security/security.c | 4 +-- 8 files changed, 59 insertions(+), 68 deletions(-) Merge branch 'exec-norecompute-v2' into exec-next
Diffstat (limited to 'include')
-rw-r--r--include/linux/binfmts.h9
-rw-r--r--include/linux/lsm_hook_defs.h2
-rw-r--r--include/linux/lsm_hooks.h22
-rw-r--r--include/linux/security.h9
4 files changed, 20 insertions, 22 deletions
diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h
index 7fc05929c967..aece1b340e7d 100644
--- a/include/linux/binfmts.h
+++ b/include/linux/binfmts.h
@@ -29,13 +29,8 @@ struct linux_binprm {
/* Should an execfd be passed to userspace? */
have_execfd:1,
- /* It is safe to use the creds of a script (see binfmt_misc) */
- preserve_creds:1,
- /*
- * True if most recent call to security_bprm_set_creds
- * resulted in elevated privileges.
- */
- active_secureexec:1,
+ /* Use the creds of a script (see binfmt_misc) */
+ execfd_creds:1,
/*
* Set by bprm_creds_for_exec hook to indicate a
* privilege-gaining exec has happened. Used to set
diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h
index 1e295ba12c0d..adbc6603abba 100644
--- a/include/linux/lsm_hook_defs.h
+++ b/include/linux/lsm_hook_defs.h
@@ -50,7 +50,7 @@ LSM_HOOK(int, 0, settime, const struct timespec64 *ts,
const struct timezone *tz)
LSM_HOOK(int, 0, vm_enough_memory, struct mm_struct *mm, long pages)
LSM_HOOK(int, 0, bprm_creds_for_exec, struct linux_binprm *bprm)
-LSM_HOOK(int, 0, bprm_repopulate_creds, struct linux_binprm *bprm)
+LSM_HOOK(int, 0, bprm_creds_from_file, struct linux_binprm *bprm, struct file *file)
LSM_HOOK(int, 0, bprm_check_security, struct linux_binprm *bprm)
LSM_HOOK(void, LSM_RET_VOID, bprm_committing_creds, struct linux_binprm *bprm)
LSM_HOOK(void, LSM_RET_VOID, bprm_committed_creds, struct linux_binprm *bprm)
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index d618ecc4d660..c523c18efa0e 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -44,17 +44,19 @@
* request libc enable secure mode.
* @bprm contains the linux_binprm structure.
* Return 0 if the hook is successful and permission is granted.
- * @bprm_repopulate_creds:
- * Assuming that the relevant bits of @bprm->cred->security have been
- * previously set, examine @bprm->file and regenerate them. This is
- * so that the credentials derived from the interpreter the code is
- * actually going to run are used rather than credentials derived
- * from a script. This done because the interpreter binary needs to
- * reopen script, and may end up opening something completely different.
- * This hook may also optionally check permissions (e.g. for
- * transitions between security domains).
- * The hook must set @bprm->active_secureexec to 1 if AT_SECURE should be set to
+ * @bprm_creds_from_file:
+ * If @file is setpcap, suid, sgid or otherwise marked to change
+ * privilege upon exec, update @bprm->cred to reflect that change.
+ * This is called after finding the binary that will be executed.
+ * without an interpreter. This ensures that the credentials will not
+ * be derived from a script that the binary will need to reopen, which
+ * when reopend may end up being a completely different file. This
+ * hook may also optionally check permissions (e.g. for transitions
+ * between security domains).
+ * The hook must set @bprm->secureexec to 1 if AT_SECURE should be set to
* request libc enable secure mode.
+ * The hook must add to @bprm->per_clear any personality flags that
+ * should be cleared from current->personality.
* @bprm contains the linux_binprm structure.
* Return 0 if the hook is successful and permission is granted.
* @bprm_check_security:
diff --git a/include/linux/security.h b/include/linux/security.h
index 6dcec9375e8f..8444fae7c5b9 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -140,7 +140,7 @@ extern int cap_capset(struct cred *new, const struct cred *old,
const kernel_cap_t *effective,
const kernel_cap_t *inheritable,
const kernel_cap_t *permitted);
-extern int cap_bprm_repopulate_creds(struct linux_binprm *bprm);
+extern int cap_bprm_creds_from_file(struct linux_binprm *bprm, struct file *file);
extern int cap_inode_setxattr(struct dentry *dentry, const char *name,
const void *value, size_t size, int flags);
extern int cap_inode_removexattr(struct dentry *dentry, const char *name);
@@ -277,7 +277,7 @@ int security_syslog(int type);
int security_settime64(const struct timespec64 *ts, const struct timezone *tz);
int security_vm_enough_memory_mm(struct mm_struct *mm, long pages);
int security_bprm_creds_for_exec(struct linux_binprm *bprm);
-int security_bprm_repopulate_creds(struct linux_binprm *bprm);
+int security_bprm_creds_from_file(struct linux_binprm *bprm, struct file *file);
int security_bprm_check(struct linux_binprm *bprm);
void security_bprm_committing_creds(struct linux_binprm *bprm);
void security_bprm_committed_creds(struct linux_binprm *bprm);
@@ -575,9 +575,10 @@ static inline int security_bprm_creds_for_exec(struct linux_binprm *bprm)
return 0;
}
-static inline int security_bprm_repopulate_creds(struct linux_binprm *bprm)
+static inline int security_bprm_creds_from_file(struct linux_binprm *bprm,
+ struct file *file)
{
- return cap_bprm_repopulate_creds(bprm);
+ return cap_bprm_creds_from_file(bprm, file);
}
static inline int security_bprm_check(struct linux_binprm *bprm)