When the format search stages an interpreter exec_binprm() swaps it in and releases the file it replaces. Dropping the write denial the open took is done manually ahead of both release paths. The one path that keeps the file silently relies on it not being called. Let's just use do_close_execat() on the two paths that release the file and drop the denial explicitly on the one that does not. No functional change. Signed-off-by: Christian Brauner (Amutable) --- fs/exec.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/fs/exec.c b/fs/exec.c index 2f50aa039827..6e540f4b43d8 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -1741,15 +1741,17 @@ static int exec_binprm(struct linux_binprm *bprm) bprm->file = bprm->interpreter; bprm->interpreter = NULL; - exe_file_allow_write_access(exec); if (unlikely(bprm->have_execfd)) { if (bprm->executable) { - fput(exec); + do_close_execat(exec); return -ENOEXEC; } + /* Only the reference is kept, for AT_EXECFD. */ + exe_file_allow_write_access(exec); bprm->executable = exec; - } else - fput(exec); + } else { + do_close_execat(exec); + } } audit_bprm(bprm); -- 2.53.0