Merge patch series "binfmt: fixes for kres reports"

Christian Brauner <brauner@kernel.org> says:

I asked Chris to run his kres tooling on the binfmt with bpf changes
merged for this cycle. It found two issues that are fixed in this
series. I reproduced both of them.

* patches from https://patch.msgid.link/20260918-work-binfmt_misc-fixes-v1-0-647b24bc1c46@kernel.org:
  binfmt_misc: fix racy checks in bpf set_interp kfuncs
  binfmt_misc: fix OOB read in bpf_binprm_select_interp()

Link: https://patch.msgid.link/20260918-work-binfmt_misc-fixes-v1-0-647b24bc1c46@kernel.org
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
This commit is contained in:
Christian Brauner 2026-09-18 11:20:59 +02:00
commit f615c80a5d
No known key found for this signature in database
GPG Key ID: 91C61BC06578DCA2

View File

@ -141,8 +141,6 @@ __bpf_kfunc int bpf_binprm_set_interp(struct linux_binprm *bprm,
len = strnlen(path, path__sz);
if (len == path__sz)
return -EINVAL;
if (path[0] != '/')
return -EINVAL;
if (len >= PATH_MAX)
return -ENAMETOOLONG;
@ -150,6 +148,15 @@ __bpf_kfunc int bpf_binprm_set_interp(struct linux_binprm *bprm,
if (!interp)
return -ENOMEM;
/*
* The program may pass memory that is written to while this runs,
* so check the private copy and not the buffer it was made from.
*/
if (interp[0] != '/') {
kfree(interp);
return -EINVAL;
}
bm_bpf_stage_selection(bprm, interp, NULL);
return 0;
}
@ -176,6 +183,7 @@ __bpf_kfunc int bpf_binprm_select_interp(struct linux_binprm *bprm,
const char *name, size_t name__sz)
{
const struct binfmt_misc_interp *interp;
char buf[BINFMT_MISC_INTERP_NAME_MAX + 1];
size_t len;
char *path;
@ -184,8 +192,20 @@ __bpf_kfunc int bpf_binprm_select_interp(struct linux_binprm *bprm,
len = strnlen(name, name__sz);
if (len == name__sz || !len)
return -EINVAL;
/* No entry binds a longer name, so it cannot be found. */
if (len > BINFMT_MISC_INTERP_NAME_MAX)
return -ENOENT;
interp = binfmt_misc_find_interp(bprm->bpf_interps, name);
/*
* The program may pass memory that is written to while this runs,
* so look the name up in a private copy and check that instead.
*/
memcpy(buf, name, len);
buf[len] = '\0';
if (!buf[0])
return -EINVAL;
interp = binfmt_misc_find_interp(bprm->bpf_interps, buf);
if (!interp)
return -ENOENT;
@ -228,6 +248,15 @@ __bpf_kfunc int bpf_binprm_set_interp_arg(struct linux_binprm *bprm,
if (!val)
return -ENOMEM;
/*
* The program may pass memory that is written to while this runs,
* so check the private copy and not the buffer it was made from.
*/
if (!val[0]) {
kfree(val);
return -EINVAL;
}
kfree(bprm->bpf_interp_arg);
bprm->bpf_interp_arg = val;
return 0;