Commit 248e00ac authored by Lorenz Bauer's avatar Lorenz Bauer Committed by Alexei Starovoitov
Browse files

bpf: cgroup: Allow multi-attach program to replace itself



When using BPF_PROG_ATTACH to attach a program to a cgroup in
BPF_F_ALLOW_MULTI mode, it is not possible to replace a program
with itself. This is because the check for duplicate programs
doesn't take the replacement program into account.

Replacing a program with itself might seem weird, but it has
some uses: first, it allows resetting the associated cgroup storage.
Second, it makes the API consistent with the non-ALLOW_MULTI usage,
where it is possible to replace a program with itself. Third, it
aligns BPF_PROG_ATTACH with bpf_link, where replacing itself is
also supported.

Sice this code has been refactored a few times this change will
only apply to v5.7 and later. Adjustments could be made to
commit 1020c1f2 ("bpf: Simplify __cgroup_bpf_attach") and
commit d7bf2c10 ("bpf: allocate cgroup storage entries on attaching bpf programs")
as well as commit 324bda9e ("bpf: multi program support for cgroup+bpf")

Fixes: af6eea57 ("bpf: Implement bpf_link-based cgroup BPF program attachment")
Signed-off-by: default avatarLorenz Bauer <lmb@cloudflare.com>
Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
Link: https://lore.kernel.org/bpf/20200608162202.94002-1-lmb@cloudflare.com
parent 26afa0a4
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -378,7 +378,7 @@ static struct bpf_prog_list *find_attach_entry(struct list_head *progs,
	}

	list_for_each_entry(pl, progs, node) {
		if (prog && pl->prog == prog)
		if (prog && pl->prog == prog && prog != replace_prog)
			/* disallow attaching the same prog twice */
			return ERR_PTR(-EINVAL);
		if (link && pl->link == link)
+7 −0
Original line number Diff line number Diff line
@@ -230,6 +230,13 @@ void test_cgroup_attach_multi(void)
		  "prog_replace", "errno=%d\n", errno))
		goto err;

	/* replace program with itself */
	attach_opts.replace_prog_fd = allow_prog[6];
	if (CHECK(bpf_prog_attach_xattr(allow_prog[6], cg1,
					BPF_CGROUP_INET_EGRESS, &attach_opts),
		  "prog_replace", "errno=%d\n", errno))
		goto err;

	value = 0;
	CHECK_FAIL(bpf_map_update_elem(map_fd, &key, &value, 0));
	CHECK_FAIL(system(PING_CMD));