From: Christian Brauner <[email protected]> The upcoming bpf-backed binfmt_misc handlers select the interpreter for a binary programmatically at exec time. The selection runs before load_misc_binary() has copied the binary path from bprm->interp into the argument vector, so the selecting program cannot go through bprm_change_interp() directly without clobbering argv[1].
Stage the selected path in the bprm instead. The bprm is exclusively owned by the task doing the exec so no synchronization is needed. The consumer frees and clears the field once the exec attempt that set it is finished; free_bprm() covers all error paths. Signed-off-by: Christian Brauner (Amutable) <[email protected]> --- fs/exec.c | 1 + include/linux/binfmts.h | 1 + 2 files changed, 2 insertions(+) diff --git a/fs/exec.c b/fs/exec.c index b92fe7db1..7c9e28f54 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -1418,6 +1418,7 @@ static void free_bprm(struct linux_binprm *bprm) /* If a binfmt changed the interp, free it. */ if (bprm->interp != bprm->filename) kfree(bprm->interp); + kfree(bprm->bpf_interp); kfree(bprm->fdpath); kfree(bprm); } diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h index 7e7333b7b..1dbec6905 100644 --- a/include/linux/binfmts.h +++ b/include/linux/binfmts.h @@ -65,6 +65,7 @@ struct linux_binprm { of the time same as filename, but could be different for binfmt_{misc,script} */ const char *fdpath; /* generated filename for execveat */ + const char *bpf_interp; /* interpreter selected by a bpf handler */ unsigned interp_flags; int execfd; /* File descriptor of the executable */ unsigned long exec; -- 2.51.2

