Among iterators, allow only iter/sockmap to update sockmaps and sockhashes.
Previously, any BPF_TRACE_ITER program could perform these updates, which
caused locking issues in specific scenarios [1][2][3]. This tightening is
part of the broader effort to lock down the BPF API [4].
env->prog->type check covers the BPF_PROG_TYPE_EXT case. Without it, a
non-sockmap iterator, e.g. iter/unix, could call a function named
bpf_iter_sockmap() that has been freplace'd with sockmap-update logic, and
still pass the check.
[1]: commit 4d328dd69538 ("bpf, sockmap: Fix af_unix iter deadlock")
[2]: commit 64c2f93fc325 ("bpf, sockmap: Take state lock for af_unix iter")
[3]: https://msgid.link/[email protected]
[4]: https://msgid.link/akRZ_e7DJh2aP-2i@john-p8
Reported-by: Sashiko <[email protected]>
Closes: https://msgid.link/[email protected]
Suggested-by: Jakub Sitnicki <[email protected]>
Signed-off-by: Michal Luczaj <[email protected]>
---
kernel/bpf/verifier.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index ddfa0c6d2755..c63abb13ec6d 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -10331,6 +10331,7 @@ static bool may_update_sockmap(struct bpf_verifier_env
*env, int func_id)
{
enum bpf_attach_type eatype = env->prog->expected_attach_type;
enum bpf_prog_type type = resolve_prog_type(env->prog);
+ const char *afname = env->prog->aux->attach_func_name;
if (func_id != BPF_FUNC_map_update_elem &&
func_id != BPF_FUNC_map_delete_elem)
@@ -10341,7 +10342,12 @@ static bool may_update_sockmap(struct bpf_verifier_env
*env, int func_id)
*/
switch (type) {
case BPF_PROG_TYPE_TRACING:
- if (eatype == BPF_TRACE_ITER)
+ /* iter/sockmap only; type check rejects a freplace of any
+ * iterator's bpf_iter_sockmap() subprog.
+ */
+ if (eatype == BPF_TRACE_ITER &&
+ env->prog->type == BPF_PROG_TYPE_TRACING &&
+ !strcmp(afname + strlen(BPF_ITER_FUNC_PREFIX), "sockmap"))
return true;
break;
case BPF_PROG_TYPE_SOCK_OPS:
--
2.56.0