Re: [PATCH v5 bpf-next 2/5] selftests/bpf: Test CGROUP_STORAGE map can't be used by multiple progs

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, Jul 23, 2020 at 02:40:55AM -0500, YiFei Zhu wrote:
> From: YiFei Zhu <zhuyifei@xxxxxxxxxx>
> 
> The current assumption is that the lifetime of a cgroup storage
> is tied to the program's attachment. The storage is created in
> cgroup_bpf_attach, and released upon cgroup_bpf_detach and
> cgroup_bpf_release.
> 
> Because the current semantics is that each attachment gets a
> completely independent cgroup storage, and you can have multiple
> programs attached to the same (cgroup, attach type) pair, the key
> of the CGROUP_STORAGE map, looking up the map with this pair could
> yield multiple storages, and that is not permitted. Therefore,
> the kernel verifier checks that two programs cannot share the same
> CGROUP_STORAGE map, even if they have different expected attach
> types, considering that the actual attach type does not always
> have to be equal to the expected attach type.
> 
> The test creates a CGROUP_STORAGE map and make it shared across
> two different programs, one cgroup_skb/egress and one /ingress.
> It asserts that the two programs cannot be both loaded, due to
> verifier failure from the above reason.
> 
> Signed-off-by: YiFei Zhu <zhuyifei@xxxxxxxxxx>
> ---
>  .../bpf/prog_tests/cg_storage_multi.c         | 42 +++++++++++++----
>  .../selftests/bpf/progs/cg_storage_multi.h    | 13 ++++++
>  .../progs/cg_storage_multi_egress_ingress.c   | 45 +++++++++++++++++++
>  .../bpf/progs/cg_storage_multi_egress_only.c  |  9 ++--
>  4 files changed, 98 insertions(+), 11 deletions(-)
>  create mode 100644 tools/testing/selftests/bpf/progs/cg_storage_multi.h
>  create mode 100644 tools/testing/selftests/bpf/progs/cg_storage_multi_egress_ingress.c
> 
> diff --git a/tools/testing/selftests/bpf/prog_tests/cg_storage_multi.c b/tools/testing/selftests/bpf/prog_tests/cg_storage_multi.c
> index 6d5a2194e036..1f4ab437ddb9 100644
> --- a/tools/testing/selftests/bpf/prog_tests/cg_storage_multi.c
> +++ b/tools/testing/selftests/bpf/prog_tests/cg_storage_multi.c
> @@ -8,7 +8,10 @@
>  #include <cgroup_helpers.h>
>  #include <network_helpers.h>
>  
> +#include "progs/cg_storage_multi.h"
> +
>  #include "cg_storage_multi_egress_only.skel.h"
> +#include "cg_storage_multi_egress_ingress.skel.h"
>  
>  #define PARENT_CGROUP "/cgroup_storage"
>  #define CHILD_CGROUP "/cgroup_storage/child"
> @@ -16,10 +19,10 @@
>  static int duration;
>  
>  static bool assert_storage(struct bpf_map *map, const char *cgroup_path,
> -			   __u32 expected)
> +			   struct cgroup_value *expected)
>  {
>  	struct bpf_cgroup_storage_key key = {0};
> -	__u32 value;
> +	struct cgroup_value value;
>  	int map_fd;
>  
>  	map_fd = bpf_map__fd(map);
> @@ -29,8 +32,8 @@ static bool assert_storage(struct bpf_map *map, const char *cgroup_path,
>  	if (CHECK(bpf_map_lookup_elem(map_fd, &key, &value) < 0,
>  		  "map-lookup", "errno %d", errno))
>  		return true;
> -	if (CHECK(value != expected,
> -		  "assert-storage", "got %u expected %u", value, expected))
> +	if (CHECK(memcmp(&value, expected, sizeof(struct cgroup_value)),
> +		  "assert-storage", "storages differ"))
>  		return true;
>  
>  	return false;
> @@ -39,7 +42,7 @@ static bool assert_storage(struct bpf_map *map, const char *cgroup_path,
>  static bool assert_storage_noexist(struct bpf_map *map, const char *cgroup_path)
>  {
>  	struct bpf_cgroup_storage_key key = {0};
> -	__u32 value;
> +	struct cgroup_value value;
>  	int map_fd;
>  
>  	map_fd = bpf_map__fd(map);
> @@ -86,6 +89,7 @@ static bool connect_send(const char *cgroup_path)
>  static void test_egress_only(int parent_cgroup_fd, int child_cgroup_fd)
>  {
>  	struct cg_storage_multi_egress_only *obj;
> +	struct cgroup_value expected_cgroup_value;
>  	struct bpf_link *parent_link = NULL, *child_link = NULL;
>  	bool err;
>  
> @@ -109,7 +113,9 @@ static void test_egress_only(int parent_cgroup_fd, int child_cgroup_fd)
>  	if (CHECK(obj->bss->invocations != 1,
>  		  "first-invoke", "invocations=%d", obj->bss->invocations))
>  		goto close_bpf_object;
> -	if (assert_storage(obj->maps.cgroup_storage, PARENT_CGROUP, 1))
> +	expected_cgroup_value = (struct cgroup_value) { .egress_pkts = 1 };
> +	if (assert_storage(obj->maps.cgroup_storage,
> +			   PARENT_CGROUP, &expected_cgroup_value))
>  		goto close_bpf_object;
>  	if (assert_storage_noexist(obj->maps.cgroup_storage, CHILD_CGROUP))
>  		goto close_bpf_object;
> @@ -129,9 +135,13 @@ static void test_egress_only(int parent_cgroup_fd, int child_cgroup_fd)
>  	if (CHECK(obj->bss->invocations != 3,
>  		  "second-invoke", "invocations=%d", obj->bss->invocations))
>  		goto close_bpf_object;
> -	if (assert_storage(obj->maps.cgroup_storage, PARENT_CGROUP, 2))
> +	expected_cgroup_value = (struct cgroup_value) { .egress_pkts = 2 };
> +	if (assert_storage(obj->maps.cgroup_storage,
> +			   PARENT_CGROUP, &expected_cgroup_value))
>  		goto close_bpf_object;
> -	if (assert_storage(obj->maps.cgroup_storage, CHILD_CGROUP, 1))
> +	expected_cgroup_value = (struct cgroup_value) { .egress_pkts = 1 };
> +	if (assert_storage(obj->maps.cgroup_storage,
> +			   CHILD_CGROUP, &expected_cgroup_value))
>  		goto close_bpf_object;
>  
>  close_bpf_object:
> @@ -143,6 +153,19 @@ static void test_egress_only(int parent_cgroup_fd, int child_cgroup_fd)
>  	cg_storage_multi_egress_only__destroy(obj);
>  }
>  
> +static void test_egress_ingress(int parent_cgroup_fd, int child_cgroup_fd)
> +{
> +	struct cg_storage_multi_egress_ingress *obj;
> +
> +	/* Cannot load both programs due to verifier failure:
> +	 * "only one cgroup storage of each type is allowed"
> +	 */
> +	obj = cg_storage_multi_egress_ingress__open_and_load();
> +	if (CHECK(obj || errno != EBUSY,
> +		  "skel-load", "errno %d, expected EBUSY", errno))
obj may theoretically need to be freed.
Probably not big deal since this case will be gone in
the latter test.

> +		return;
> +}
> +



[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux