On Feb 6, 2024 Tetsuo Handa <penguin-kernel@xxxxxxxxxxxxxxxxxxx> wrote: > > A regression caused by commit 978ffcbf00d8 ("execve: open the executable > file before doing anything else") has been fixed by commit 4759ff71f23e > ("exec: Check __FMODE_EXEC instead of in_execve for LSMs") and commit > 3eab830189d9 ("uselib: remove use of __FMODE_EXEC"). While fixing this > regression, Linus commented that we want to remove current->in_execve flag. > > The current->in_execve flag was introduced by commit f9ce1f1cda8b ("Add > in_execve flag into task_struct.") when TOMOYO LSM was merged, and the > reason was explained in commit f7433243770c ("LSM adapter functions."). > > In short, TOMOYO's design is not compatible with COW credential model > introduced in Linux 2.6.29, and the current->in_execve flag was added for > emulating security_bprm_free() hook which has been removed by introduction > of COW credential model. If you wanted to mention the relevant commit where security_bprm_free() was removed, it was a6f76f23d297 ("CRED: Make execve() take advantage of copy-on-write credentials"). > security_task_alloc()/security_task_free() hooks have been removed by > commit f1752eec6145 ("CRED: Detach the credentials from task_struct"), > and these hooks have been revived by commit 1a2a4d06e1e9 ("security: > create task_free security callback") and commit e4e55b47ed9a ("LSM: Revive > security_task_alloc() hook and per "struct task_struct" security blob."). > > But security_bprm_free() hook did not revive until now. Now that Linus > wants TOMOYO to stop carrying state across two independent execve() calls, > and TOMOYO can stop carrying state if a hook for restoring previous state > upon failed execve() call were provided, this patch revives the hook. > > Since security_bprm_committing_creds() and security_bprm_committed_creds() > hooks are called when an execve() request succeeded, we don't need to call > security_bprm_free() hook when an execve() request succeeded. Therefore, > this patch adds security_execve_abort() hook which is called only when an > execve() request failed after successful prepare_bprm_creds() call. > > Signed-off-by: Tetsuo Handa <penguin-kernel@xxxxxxxxxxxxxxxxxxx> > Acked-by: Serge E. Hallyn <serge@xxxxxxxxxx> > --- > fs/exec.c | 1 + > include/linux/lsm_hook_defs.h | 1 + > include/linux/security.h | 5 +++++ > security/security.c | 11 +++++++++++ > 4 files changed, 18 insertions(+) > > diff --git a/fs/exec.c b/fs/exec.c > index af4fbb61cd53..d6d35a06fd08 100644 > --- a/fs/exec.c > +++ b/fs/exec.c > @@ -1521,6 +1521,7 @@ static void free_bprm(struct linux_binprm *bprm) > if (bprm->cred) { > mutex_unlock(¤t->signal->cred_guard_mutex); > abort_creds(bprm->cred); > + security_execve_abort(); > } > do_close_execat(bprm->file); > if (bprm->executable) > diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h > index 76458b6d53da..fd100ab71a33 100644 > --- a/include/linux/lsm_hook_defs.h > +++ b/include/linux/lsm_hook_defs.h > @@ -54,6 +54,7 @@ LSM_HOOK(int, 0, bprm_creds_from_file, struct linux_binprm *bprm, const struct f > LSM_HOOK(int, 0, bprm_check_security, struct linux_binprm *bprm) > LSM_HOOK(void, LSM_RET_VOID, bprm_committing_creds, const struct linux_binprm *bprm) > LSM_HOOK(void, LSM_RET_VOID, bprm_committed_creds, const struct linux_binprm *bprm) > +LSM_HOOK(void, LSM_RET_VOID, execve_abort, void) > LSM_HOOK(int, 0, fs_context_submount, struct fs_context *fc, struct super_block *reference) > LSM_HOOK(int, 0, fs_context_dup, struct fs_context *fc, > struct fs_context *src_sc) > diff --git a/include/linux/security.h b/include/linux/security.h > index d0eb20f90b26..31532b30c4f0 100644 > --- a/include/linux/security.h > +++ b/include/linux/security.h > @@ -299,6 +299,7 @@ int security_bprm_creds_from_file(struct linux_binprm *bprm, const struct file * > int security_bprm_check(struct linux_binprm *bprm); > void security_bprm_committing_creds(const struct linux_binprm *bprm); > void security_bprm_committed_creds(const struct linux_binprm *bprm); > +void security_execve_abort(void); > int security_fs_context_submount(struct fs_context *fc, struct super_block *reference); > int security_fs_context_dup(struct fs_context *fc, struct fs_context *src_fc); > int security_fs_context_parse_param(struct fs_context *fc, struct fs_parameter *param); > @@ -648,6 +649,10 @@ static inline void security_bprm_committed_creds(const struct linux_binprm *bprm > { > } > > +static inline void security_execve_abort(void) > +{ > +} > + > static inline int security_fs_context_submount(struct fs_context *fc, > struct super_block *reference) > { > diff --git a/security/security.c b/security/security.c > index 3aaad75c9ce8..10adc4d3c5e0 100644 > --- a/security/security.c > +++ b/security/security.c > @@ -1223,6 +1223,17 @@ void security_bprm_committed_creds(const struct linux_binprm *bprm) > call_void_hook(bprm_committed_creds, bprm); > } > > +/** > + * security_execve_abort() - Notify that exec() has failed > + * > + * This hook is for undoing changes which cannot be discarded by > + * abort_creds(). > + */ > +void security_execve_abort(void) > +{ > + call_void_hook(execve_abort); > +} I don't have a problem with reinstating something like security_bprm_free(), but I don't like the name security_execve_abort(), especially given that it is being called from alloc_bprm() as well as all of the execve code. At the risk of bikeshedding this, I'd be much happier if this hook were renamed to security_bprm_free() and the hook's description explained that this hook is called when a linux_bprm instance is being destroyed, after the bprm creds have been released, and is intended to cleanup any internal LSM state associated with the linux_bprm instance. Are you okay with that? -- paul-moore.com