Commit e01b4a72 authored by Stanislav Fomichev's avatar Stanislav Fomichev Committed by Martin KaFai Lau
Browse files

selftests/bpf: Correctly handle optlen > 4096



Even though it's not relevant in selftests, the people
might still copy-paste from them. So let's take care
of optlen > 4096 cases explicitly.

Signed-off-by: default avatarStanislav Fomichev <sdf@google.com>
Link: https://lore.kernel.org/r/20230511170456.1759459-4-sdf@google.com


Signed-off-by: default avatarMartin KaFai Lau <martin.lau@kernel.org>
parent 989a4a7d
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
@@ -25,6 +25,8 @@ static void test_setsockopt_set(int cgroup_fd, int sock_fd)
	if (!ASSERT_OK_PTR(obj, "skel-load"))
		return;

	obj->bss->page_size = sysconf(_SC_PAGESIZE);

	/* Attach setsockopt that sets EUNATCH, assert that
	 * we actually get that error when we run setsockopt()
	 */
@@ -59,6 +61,8 @@ static void test_setsockopt_set_and_get(int cgroup_fd, int sock_fd)
	if (!ASSERT_OK_PTR(obj, "skel-load"))
		return;

	obj->bss->page_size = sysconf(_SC_PAGESIZE);

	/* Attach setsockopt that sets EUNATCH, and one that gets the
	 * previously set errno. Assert that we get the same errno back.
	 */
@@ -100,6 +104,8 @@ static void test_setsockopt_default_zero(int cgroup_fd, int sock_fd)
	if (!ASSERT_OK_PTR(obj, "skel-load"))
		return;

	obj->bss->page_size = sysconf(_SC_PAGESIZE);

	/* Attach setsockopt that gets the previously set errno.
	 * Assert that, without anything setting one, we get 0.
	 */
@@ -134,6 +140,8 @@ static void test_setsockopt_default_zero_and_set(int cgroup_fd, int sock_fd)
	if (!ASSERT_OK_PTR(obj, "skel-load"))
		return;

	obj->bss->page_size = sysconf(_SC_PAGESIZE);

	/* Attach setsockopt that gets the previously set errno, and then
	 * one that sets the errno to EUNATCH. Assert that the get does not
	 * see EUNATCH set later, and does not prevent EUNATCH from being set.
@@ -177,6 +185,8 @@ static void test_setsockopt_override(int cgroup_fd, int sock_fd)
	if (!ASSERT_OK_PTR(obj, "skel-load"))
		return;

	obj->bss->page_size = sysconf(_SC_PAGESIZE);

	/* Attach setsockopt that sets EUNATCH, then one that sets EISCONN,
	 * and then one that gets the exported errno. Assert both the syscall
	 * and the helper sees the last set errno.
@@ -224,6 +234,8 @@ static void test_setsockopt_legacy_eperm(int cgroup_fd, int sock_fd)
	if (!ASSERT_OK_PTR(obj, "skel-load"))
		return;

	obj->bss->page_size = sysconf(_SC_PAGESIZE);

	/* Attach setsockopt that return a reject without setting errno
	 * (legacy reject), and one that gets the errno. Assert that for
	 * backward compatibility the syscall result in EPERM, and this
@@ -268,6 +280,8 @@ static void test_setsockopt_legacy_no_override(int cgroup_fd, int sock_fd)
	if (!ASSERT_OK_PTR(obj, "skel-load"))
		return;

	obj->bss->page_size = sysconf(_SC_PAGESIZE);

	/* Attach setsockopt that sets EUNATCH, then one that return a reject
	 * without setting errno, and then one that gets the exported errno.
	 * Assert both the syscall and the helper's errno are unaffected by
@@ -319,6 +333,8 @@ static void test_getsockopt_get(int cgroup_fd, int sock_fd)
	if (!ASSERT_OK_PTR(obj, "skel-load"))
		return;

	obj->bss->page_size = sysconf(_SC_PAGESIZE);

	/* Attach getsockopt that gets previously set errno. Assert that the
	 * error from kernel is in both ctx_retval_value and retval_value.
	 */
@@ -359,6 +375,8 @@ static void test_getsockopt_override(int cgroup_fd, int sock_fd)
	if (!ASSERT_OK_PTR(obj, "skel-load"))
		return;

	obj->bss->page_size = sysconf(_SC_PAGESIZE);

	/* Attach getsockopt that sets retval to -EISCONN. Assert that this
	 * overrides the value from kernel.
	 */
@@ -396,6 +414,8 @@ static void test_getsockopt_retval_sync(int cgroup_fd, int sock_fd)
	if (!ASSERT_OK_PTR(obj, "skel-load"))
		return;

	obj->bss->page_size = sysconf(_SC_PAGESIZE);

	/* Attach getsockopt that sets retval to -EISCONN, and one that clears
	 * ctx retval. Assert that the clearing ctx retval is synced to helper
	 * and clears any errors both from kernel and BPF..
+18 −41
Original line number Diff line number Diff line
@@ -2,6 +2,8 @@
#include <test_progs.h>
#include "cgroup_helpers.h"

#include "sockopt_inherit.skel.h"

#define SOL_CUSTOM			0xdeadbeef
#define CUSTOM_INHERIT1			0
#define CUSTOM_INHERIT2			1
@@ -132,58 +134,30 @@ static int start_server(void)
	return fd;
}

static int prog_attach(struct bpf_object *obj, int cgroup_fd, const char *title,
		       const char *prog_name)
{
	enum bpf_attach_type attach_type;
	enum bpf_prog_type prog_type;
	struct bpf_program *prog;
	int err;

	err = libbpf_prog_type_by_name(title, &prog_type, &attach_type);
	if (err) {
		log_err("Failed to deduct types for %s BPF program", prog_name);
		return -1;
	}

	prog = bpf_object__find_program_by_name(obj, prog_name);
	if (!prog) {
		log_err("Failed to find %s BPF program", prog_name);
		return -1;
	}

	err = bpf_prog_attach(bpf_program__fd(prog), cgroup_fd,
			      attach_type, 0);
	if (err) {
		log_err("Failed to attach %s BPF program", prog_name);
		return -1;
	}

	return 0;
}

static void run_test(int cgroup_fd)
{
	struct bpf_link *link_getsockopt = NULL;
	struct bpf_link *link_setsockopt = NULL;
	int server_fd = -1, client_fd;
	struct bpf_object *obj;
	struct sockopt_inherit *obj;
	void *server_err;
	pthread_t tid;
	int err;

	obj = bpf_object__open_file("sockopt_inherit.bpf.o", NULL);
	if (!ASSERT_OK_PTR(obj, "obj_open"))
	obj = sockopt_inherit__open_and_load();
	if (!ASSERT_OK_PTR(obj, "skel-load"))
		return;

	err = bpf_object__load(obj);
	if (!ASSERT_OK(err, "obj_load"))
		goto close_bpf_object;
	obj->bss->page_size = sysconf(_SC_PAGESIZE);

	err = prog_attach(obj, cgroup_fd, "cgroup/getsockopt", "_getsockopt");
	if (!ASSERT_OK(err, "prog_attach _getsockopt"))
	link_getsockopt = bpf_program__attach_cgroup(obj->progs._getsockopt,
						     cgroup_fd);
	if (!ASSERT_OK_PTR(link_getsockopt, "cg-attach-getsockopt"))
		goto close_bpf_object;

	err = prog_attach(obj, cgroup_fd, "cgroup/setsockopt", "_setsockopt");
	if (!ASSERT_OK(err, "prog_attach _setsockopt"))
	link_setsockopt = bpf_program__attach_cgroup(obj->progs._setsockopt,
						     cgroup_fd);
	if (!ASSERT_OK_PTR(link_setsockopt, "cg-attach-setsockopt"))
		goto close_bpf_object;

	server_fd = start_server();
@@ -217,7 +191,10 @@ static void run_test(int cgroup_fd)
close_server_fd:
	close(server_fd);
close_bpf_object:
	bpf_object__close(obj);
	bpf_link__destroy(link_getsockopt);
	bpf_link__destroy(link_setsockopt);

	sockopt_inherit__destroy(obj);
}

void test_sockopt_inherit(void)
+30 −78
Original line number Diff line number Diff line
@@ -2,61 +2,13 @@
#include <test_progs.h>
#include "cgroup_helpers.h"

static int prog_attach(struct bpf_object *obj, int cgroup_fd, const char *title, const char *name)
{
	enum bpf_attach_type attach_type;
	enum bpf_prog_type prog_type;
	struct bpf_program *prog;
	int err;

	err = libbpf_prog_type_by_name(title, &prog_type, &attach_type);
	if (err) {
		log_err("Failed to deduct types for %s BPF program", title);
		return -1;
	}

	prog = bpf_object__find_program_by_name(obj, name);
	if (!prog) {
		log_err("Failed to find %s BPF program", name);
		return -1;
	}

	err = bpf_prog_attach(bpf_program__fd(prog), cgroup_fd,
			      attach_type, BPF_F_ALLOW_MULTI);
	if (err) {
		log_err("Failed to attach %s BPF program", name);
		return -1;
	}

	return 0;
}
#include "sockopt_multi.skel.h"

static int prog_detach(struct bpf_object *obj, int cgroup_fd, const char *title, const char *name)
{
	enum bpf_attach_type attach_type;
	enum bpf_prog_type prog_type;
	struct bpf_program *prog;
	int err;

	err = libbpf_prog_type_by_name(title, &prog_type, &attach_type);
	if (err)
		return -1;

	prog = bpf_object__find_program_by_name(obj, name);
	if (!prog)
		return -1;

	err = bpf_prog_detach2(bpf_program__fd(prog), cgroup_fd,
			       attach_type);
	if (err)
		return -1;

	return 0;
}

static int run_getsockopt_test(struct bpf_object *obj, int cg_parent,
static int run_getsockopt_test(struct sockopt_multi *obj, int cg_parent,
			       int cg_child, int sock_fd)
{
	struct bpf_link *link_parent = NULL;
	struct bpf_link *link_child = NULL;
	socklen_t optlen;
	__u8 buf;
	int err;
@@ -89,8 +41,9 @@ static int run_getsockopt_test(struct bpf_object *obj, int cg_parent,
	 * - child:  0x80 -> 0x90
	 */

	err = prog_attach(obj, cg_child, "cgroup/getsockopt", "_getsockopt_child");
	if (err)
	link_child = bpf_program__attach_cgroup(obj->progs._getsockopt_child,
						cg_child);
	if (!ASSERT_OK_PTR(link_child, "cg-attach-getsockopt_child"))
		goto detach;

	buf = 0x00;
@@ -113,8 +66,9 @@ static int run_getsockopt_test(struct bpf_object *obj, int cg_parent,
	 * - parent: 0x90 -> 0xA0
	 */

	err = prog_attach(obj, cg_parent, "cgroup/getsockopt", "_getsockopt_parent");
	if (err)
	link_parent = bpf_program__attach_cgroup(obj->progs._getsockopt_parent,
						 cg_parent);
	if (!ASSERT_OK_PTR(link_parent, "cg-attach-getsockopt_parent"))
		goto detach;

	buf = 0x00;
@@ -157,11 +111,8 @@ static int run_getsockopt_test(struct bpf_object *obj, int cg_parent,
	 * - parent: unexpected 0x40, EPERM
	 */

	err = prog_detach(obj, cg_child, "cgroup/getsockopt", "_getsockopt_child");
	if (err) {
		log_err("Failed to detach child program");
		goto detach;
	}
	bpf_link__destroy(link_child);
	link_child = NULL;

	buf = 0x00;
	optlen = 1;
@@ -198,15 +149,17 @@ static int run_getsockopt_test(struct bpf_object *obj, int cg_parent,
	}

detach:
	prog_detach(obj, cg_child, "cgroup/getsockopt", "_getsockopt_child");
	prog_detach(obj, cg_parent, "cgroup/getsockopt", "_getsockopt_parent");
	bpf_link__destroy(link_child);
	bpf_link__destroy(link_parent);

	return err;
}

static int run_setsockopt_test(struct bpf_object *obj, int cg_parent,
static int run_setsockopt_test(struct sockopt_multi *obj, int cg_parent,
			       int cg_child, int sock_fd)
{
	struct bpf_link *link_parent = NULL;
	struct bpf_link *link_child = NULL;
	socklen_t optlen;
	__u8 buf;
	int err;
@@ -236,8 +189,9 @@ static int run_setsockopt_test(struct bpf_object *obj, int cg_parent,

	/* Attach child program and make sure it adds 0x10. */

	err = prog_attach(obj, cg_child, "cgroup/setsockopt", "_setsockopt");
	if (err)
	link_child = bpf_program__attach_cgroup(obj->progs._setsockopt,
						cg_child);
	if (!ASSERT_OK_PTR(link_child, "cg-attach-setsockopt_child"))
		goto detach;

	buf = 0x80;
@@ -263,8 +217,9 @@ static int run_setsockopt_test(struct bpf_object *obj, int cg_parent,

	/* Attach parent program and make sure it adds another 0x10. */

	err = prog_attach(obj, cg_parent, "cgroup/setsockopt", "_setsockopt");
	if (err)
	link_parent = bpf_program__attach_cgroup(obj->progs._setsockopt,
						 cg_parent);
	if (!ASSERT_OK_PTR(link_parent, "cg-attach-setsockopt_parent"))
		goto detach;

	buf = 0x80;
@@ -289,8 +244,8 @@ static int run_setsockopt_test(struct bpf_object *obj, int cg_parent,
	}

detach:
	prog_detach(obj, cg_child, "cgroup/setsockopt", "_setsockopt");
	prog_detach(obj, cg_parent, "cgroup/setsockopt", "_setsockopt");
	bpf_link__destroy(link_child);
	bpf_link__destroy(link_parent);

	return err;
}
@@ -298,9 +253,8 @@ static int run_setsockopt_test(struct bpf_object *obj, int cg_parent,
void test_sockopt_multi(void)
{
	int cg_parent = -1, cg_child = -1;
	struct bpf_object *obj = NULL;
	struct sockopt_multi *obj = NULL;
	int sock_fd = -1;
	int err = -1;

	cg_parent = test__join_cgroup("/parent");
	if (!ASSERT_GE(cg_parent, 0, "join_cgroup /parent"))
@@ -310,13 +264,11 @@ void test_sockopt_multi(void)
	if (!ASSERT_GE(cg_child, 0, "join_cgroup /parent/child"))
		goto out;

	obj = bpf_object__open_file("sockopt_multi.bpf.o", NULL);
	if (!ASSERT_OK_PTR(obj, "obj_load"))
	obj = sockopt_multi__open_and_load();
	if (!ASSERT_OK_PTR(obj, "skel-load"))
		goto out;

	err = bpf_object__load(obj);
	if (!ASSERT_OK(err, "obj_load"))
		goto out;
	obj->bss->page_size = sysconf(_SC_PAGESIZE);

	sock_fd = socket(AF_INET, SOCK_STREAM, 0);
	if (!ASSERT_GE(sock_fd, 0, "socket"))
@@ -327,7 +279,7 @@ void test_sockopt_multi(void)

out:
	close(sock_fd);
	bpf_object__close(obj);
	sockopt_multi__destroy(obj);
	close(cg_child);
	close(cg_parent);
}
+2 −0
Original line number Diff line number Diff line
@@ -42,6 +42,8 @@ void test_sockopt_qos_to_cc(void)
	if (!ASSERT_OK_PTR(skel, "skel"))
		goto done;

	skel->bss->page_size = sysconf(_SC_PAGESIZE);

	sock_fd = socket(AF_INET6, SOCK_STREAM, 0);
	if (!ASSERT_GE(sock_fd, 0, "v6 socket open"))
		goto done;
+13 −0
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@ __u32 invocations = 0;
__u32 assertion_error = 0;
__u32 retval_value = 0;
__u32 ctx_retval_value = 0;
__u32 page_size = 0;

SEC("cgroup/getsockopt")
int get_retval(struct bpf_sockopt *ctx)
@@ -20,6 +21,10 @@ int get_retval(struct bpf_sockopt *ctx)
	ctx_retval_value = ctx->retval;
	__sync_fetch_and_add(&invocations, 1);

	/* optval larger than PAGE_SIZE use kernel's buffer. */
	if (ctx->optlen > page_size)
		ctx->optlen = 0;

	return 1;
}

@@ -31,6 +36,10 @@ int set_eisconn(struct bpf_sockopt *ctx)
	if (bpf_set_retval(-EISCONN))
		assertion_error = 1;

	/* optval larger than PAGE_SIZE use kernel's buffer. */
	if (ctx->optlen > page_size)
		ctx->optlen = 0;

	return 1;
}

@@ -41,5 +50,9 @@ int clear_retval(struct bpf_sockopt *ctx)

	ctx->retval = 0;

	/* optval larger than PAGE_SIZE use kernel's buffer. */
	if (ctx->optlen > page_size)
		ctx->optlen = 0;

	return 1;
}
Loading