1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2023 Meta Platforms, Inc. and affiliates.*/
3 
4 #include <test_progs.h>
5 #include <network_helpers.h>
6 #include "test_ldsx_insn.skel.h"
7 
8 static void test_map_val_and_probed_memory(void)
9 {
10 	struct test_ldsx_insn *skel;
11 	int err;
12 
13 	skel = test_ldsx_insn__open();
14 	if (!ASSERT_OK_PTR(skel, "test_ldsx_insn__open"))
15 		return;
16 
17 	if (skel->rodata->skip) {
18 		test__skip();
19 		goto out;
20 	}
21 
22 	bpf_program__set_autoload(skel->progs.rdonly_map_prog, true);
23 	bpf_program__set_autoload(skel->progs.map_val_prog, true);
24 	bpf_program__set_autoload(skel->progs.test_ptr_struct_arg, true);
25 
26 	err = test_ldsx_insn__load(skel);
27 	if (!ASSERT_OK(err, "test_ldsx_insn__load"))
28 		goto out;
29 
30 	err = test_ldsx_insn__attach(skel);
31 	if (!ASSERT_OK(err, "test_ldsx_insn__attach"))
32 		goto out;
33 
34 	ASSERT_OK(trigger_module_test_read(256), "trigger_read");
35 
36 	ASSERT_EQ(skel->bss->done1, 1, "done1");
37 	ASSERT_EQ(skel->bss->ret1, 1, "ret1");
38 	ASSERT_EQ(skel->bss->done2, 1, "done2");
39 	ASSERT_EQ(skel->bss->ret2, 1, "ret2");
40 	ASSERT_EQ(skel->bss->int_member, -1, "int_member");
41 
42 out:
43 	test_ldsx_insn__destroy(skel);
44 }
45 
46 static void test_ctx_member_sign_ext(void)
47 {
48 	struct test_ldsx_insn *skel;
49 	int err, fd, cgroup_fd;
50 	char buf[16] = {0};
51 	socklen_t optlen;
52 
53 	cgroup_fd = test__join_cgroup("/ldsx_test");
54 	if (!ASSERT_GE(cgroup_fd, 0, "join_cgroup /ldsx_test"))
55 		return;
56 
57 	skel = test_ldsx_insn__open();
58 	if (!ASSERT_OK_PTR(skel, "test_ldsx_insn__open"))
59 		goto close_cgroup_fd;
60 
61 	if (skel->rodata->skip) {
62 		test__skip();
63 		goto destroy_skel;
64 	}
65 
66 	bpf_program__set_autoload(skel->progs._getsockopt, true);
67 
68 	err = test_ldsx_insn__load(skel);
69 	if (!ASSERT_OK(err, "test_ldsx_insn__load"))
70 		goto destroy_skel;
71 
72 	skel->links._getsockopt =
73 		bpf_program__attach_cgroup(skel->progs._getsockopt, cgroup_fd);
74 	if (!ASSERT_OK_PTR(skel->links._getsockopt, "getsockopt_link"))
75 		goto destroy_skel;
76 
77 	fd = socket(AF_INET, SOCK_STREAM, 0);
78 	if (!ASSERT_GE(fd, 0, "socket"))
79 		goto destroy_skel;
80 
81 	optlen = sizeof(buf);
82 	(void)getsockopt(fd, SOL_IP, IP_TTL, buf, &optlen);
83 
84 	ASSERT_EQ(skel->bss->set_optlen, -1, "optlen");
85 	ASSERT_EQ(skel->bss->set_retval, -1, "retval");
86 
87 	close(fd);
88 destroy_skel:
89 	test_ldsx_insn__destroy(skel);
90 close_cgroup_fd:
91 	close(cgroup_fd);
92 }
93 
94 static void test_ctx_member_narrow_sign_ext(void)
95 {
96 	struct test_ldsx_insn *skel;
97 	struct __sk_buff skb = {};
98 	LIBBPF_OPTS(bpf_test_run_opts, topts,
99 		    .data_in = &pkt_v4,
100 		    .data_size_in = sizeof(pkt_v4),
101 		    .ctx_in = &skb,
102 		    .ctx_size_in = sizeof(skb),
103 	);
104 	int err, prog_fd;
105 
106 	skel = test_ldsx_insn__open();
107 	if (!ASSERT_OK_PTR(skel, "test_ldsx_insn__open"))
108 		return;
109 
110 	if (skel->rodata->skip) {
111 		test__skip();
112 		goto out;
113 	}
114 
115 	bpf_program__set_autoload(skel->progs._tc, true);
116 
117 	err = test_ldsx_insn__load(skel);
118 	if (!ASSERT_OK(err, "test_ldsx_insn__load"))
119 		goto out;
120 
121 	prog_fd = bpf_program__fd(skel->progs._tc);
122 	err = bpf_prog_test_run_opts(prog_fd, &topts);
123 	ASSERT_OK(err, "test_run");
124 
125 	ASSERT_EQ(skel->bss->set_mark, -2, "set_mark");
126 
127 out:
128 	test_ldsx_insn__destroy(skel);
129 }
130 
131 void test_ldsx_insn(void)
132 {
133 	if (test__start_subtest("map_val and probed_memory"))
134 		test_map_val_and_probed_memory();
135 	if (test__start_subtest("ctx_member_sign_ext"))
136 		test_ctx_member_sign_ext();
137 	if (test__start_subtest("ctx_member_narrow_sign_ext"))
138 		test_ctx_member_narrow_sign_ext();
139 }
140