xref: /linux/tools/testing/selftests/bpf/prog_tests/summarization.c (revision 4f9786035f9e519db41375818e1d0b5f20da2f10)
1*72ed076aSKumar Kartikeya Dwivedi // SPDX-License-Identifier: GPL-2.0
2*72ed076aSKumar Kartikeya Dwivedi #include "bpf/libbpf.h"
3*72ed076aSKumar Kartikeya Dwivedi #include "summarization_freplace.skel.h"
4*72ed076aSKumar Kartikeya Dwivedi #include "summarization.skel.h"
5*72ed076aSKumar Kartikeya Dwivedi #include <test_progs.h>
6*72ed076aSKumar Kartikeya Dwivedi 
7*72ed076aSKumar Kartikeya Dwivedi static void print_verifier_log(const char *log)
8*72ed076aSKumar Kartikeya Dwivedi {
9*72ed076aSKumar Kartikeya Dwivedi 	if (env.verbosity >= VERBOSE_VERY)
10*72ed076aSKumar Kartikeya Dwivedi 		fprintf(stdout, "VERIFIER LOG:\n=============\n%s=============\n", log);
11*72ed076aSKumar Kartikeya Dwivedi }
12*72ed076aSKumar Kartikeya Dwivedi 
13*72ed076aSKumar Kartikeya Dwivedi static void test_aux(const char *main_prog_name,
14*72ed076aSKumar Kartikeya Dwivedi 		     const char *to_be_replaced,
15*72ed076aSKumar Kartikeya Dwivedi 		     const char *replacement,
16*72ed076aSKumar Kartikeya Dwivedi 		     bool expect_load,
17*72ed076aSKumar Kartikeya Dwivedi 		     const char *err_msg)
18*72ed076aSKumar Kartikeya Dwivedi {
19*72ed076aSKumar Kartikeya Dwivedi 	struct summarization_freplace *freplace = NULL;
20*72ed076aSKumar Kartikeya Dwivedi 	struct bpf_program *freplace_prog = NULL;
21*72ed076aSKumar Kartikeya Dwivedi 	struct bpf_program *main_prog = NULL;
22*72ed076aSKumar Kartikeya Dwivedi 	LIBBPF_OPTS(bpf_object_open_opts, opts);
23*72ed076aSKumar Kartikeya Dwivedi 	struct summarization *main = NULL;
24*72ed076aSKumar Kartikeya Dwivedi 	char log[16*1024];
25*72ed076aSKumar Kartikeya Dwivedi 	int err;
26*72ed076aSKumar Kartikeya Dwivedi 
27*72ed076aSKumar Kartikeya Dwivedi 	opts.kernel_log_buf = log;
28*72ed076aSKumar Kartikeya Dwivedi 	opts.kernel_log_size = sizeof(log);
29*72ed076aSKumar Kartikeya Dwivedi 	if (env.verbosity >= VERBOSE_SUPER)
30*72ed076aSKumar Kartikeya Dwivedi 		opts.kernel_log_level = 1 | 2 | 4;
31*72ed076aSKumar Kartikeya Dwivedi 	main = summarization__open_opts(&opts);
32*72ed076aSKumar Kartikeya Dwivedi 	if (!ASSERT_OK_PTR(main, "summarization__open"))
33*72ed076aSKumar Kartikeya Dwivedi 		goto out;
34*72ed076aSKumar Kartikeya Dwivedi 	main_prog = bpf_object__find_program_by_name(main->obj, main_prog_name);
35*72ed076aSKumar Kartikeya Dwivedi 	if (!ASSERT_OK_PTR(main_prog, "main_prog"))
36*72ed076aSKumar Kartikeya Dwivedi 		goto out;
37*72ed076aSKumar Kartikeya Dwivedi 	bpf_program__set_autoload(main_prog, true);
38*72ed076aSKumar Kartikeya Dwivedi 	err = summarization__load(main);
39*72ed076aSKumar Kartikeya Dwivedi 	print_verifier_log(log);
40*72ed076aSKumar Kartikeya Dwivedi 	if (!ASSERT_OK(err, "summarization__load"))
41*72ed076aSKumar Kartikeya Dwivedi 		goto out;
42*72ed076aSKumar Kartikeya Dwivedi 	freplace = summarization_freplace__open_opts(&opts);
43*72ed076aSKumar Kartikeya Dwivedi 	if (!ASSERT_OK_PTR(freplace, "summarization_freplace__open"))
44*72ed076aSKumar Kartikeya Dwivedi 		goto out;
45*72ed076aSKumar Kartikeya Dwivedi 	freplace_prog = bpf_object__find_program_by_name(freplace->obj, replacement);
46*72ed076aSKumar Kartikeya Dwivedi 	if (!ASSERT_OK_PTR(freplace_prog, "freplace_prog"))
47*72ed076aSKumar Kartikeya Dwivedi 		goto out;
48*72ed076aSKumar Kartikeya Dwivedi 	bpf_program__set_autoload(freplace_prog, true);
49*72ed076aSKumar Kartikeya Dwivedi 	bpf_program__set_autoattach(freplace_prog, true);
50*72ed076aSKumar Kartikeya Dwivedi 	bpf_program__set_attach_target(freplace_prog,
51*72ed076aSKumar Kartikeya Dwivedi 				       bpf_program__fd(main_prog),
52*72ed076aSKumar Kartikeya Dwivedi 				       to_be_replaced);
53*72ed076aSKumar Kartikeya Dwivedi 	err = summarization_freplace__load(freplace);
54*72ed076aSKumar Kartikeya Dwivedi 	print_verifier_log(log);
55*72ed076aSKumar Kartikeya Dwivedi 
56*72ed076aSKumar Kartikeya Dwivedi 	/* The might_sleep extension doesn't work yet as sleepable calls are not
57*72ed076aSKumar Kartikeya Dwivedi 	 * allowed, but preserve the check in case it's supported later and then
58*72ed076aSKumar Kartikeya Dwivedi 	 * this particular combination can be enabled.
59*72ed076aSKumar Kartikeya Dwivedi 	 */
60*72ed076aSKumar Kartikeya Dwivedi 	if (!strcmp("might_sleep", replacement) && err) {
61*72ed076aSKumar Kartikeya Dwivedi 		ASSERT_HAS_SUBSTR(log, "helper call might sleep in a non-sleepable prog", "error log");
62*72ed076aSKumar Kartikeya Dwivedi 		ASSERT_EQ(err, -EINVAL, "err");
63*72ed076aSKumar Kartikeya Dwivedi 		test__skip();
64*72ed076aSKumar Kartikeya Dwivedi 		goto out;
65*72ed076aSKumar Kartikeya Dwivedi 	}
66*72ed076aSKumar Kartikeya Dwivedi 
67*72ed076aSKumar Kartikeya Dwivedi 	if (expect_load) {
68*72ed076aSKumar Kartikeya Dwivedi 		ASSERT_OK(err, "summarization_freplace__load");
69*72ed076aSKumar Kartikeya Dwivedi 	} else {
70*72ed076aSKumar Kartikeya Dwivedi 		ASSERT_ERR(err, "summarization_freplace__load");
71*72ed076aSKumar Kartikeya Dwivedi 		ASSERT_HAS_SUBSTR(log, err_msg, "error log");
72*72ed076aSKumar Kartikeya Dwivedi 	}
73*72ed076aSKumar Kartikeya Dwivedi 
74*72ed076aSKumar Kartikeya Dwivedi out:
75*72ed076aSKumar Kartikeya Dwivedi 	summarization_freplace__destroy(freplace);
76*72ed076aSKumar Kartikeya Dwivedi 	summarization__destroy(main);
77*72ed076aSKumar Kartikeya Dwivedi }
78*72ed076aSKumar Kartikeya Dwivedi 
79*72ed076aSKumar Kartikeya Dwivedi /* There are two global subprograms in both summarization.skel.h:
80*72ed076aSKumar Kartikeya Dwivedi  * - one changes packet data;
81*72ed076aSKumar Kartikeya Dwivedi  * - another does not.
82*72ed076aSKumar Kartikeya Dwivedi  * It is ok to freplace subprograms that change packet data with those
83*72ed076aSKumar Kartikeya Dwivedi  * that either do or do not. It is only ok to freplace subprograms
84*72ed076aSKumar Kartikeya Dwivedi  * that do not change packet data with those that do not as well.
85*72ed076aSKumar Kartikeya Dwivedi  * The below tests check outcomes for each combination of such freplace.
86*72ed076aSKumar Kartikeya Dwivedi  * Also test a case when main subprogram itself is replaced and is a single
87*72ed076aSKumar Kartikeya Dwivedi  * subprogram in a program.
88*72ed076aSKumar Kartikeya Dwivedi  *
89*72ed076aSKumar Kartikeya Dwivedi  * This holds for might_sleep programs. It is ok to replace might_sleep with
90*72ed076aSKumar Kartikeya Dwivedi  * might_sleep and with does_not_sleep, but does_not_sleep cannot be replaced
91*72ed076aSKumar Kartikeya Dwivedi  * with might_sleep.
92*72ed076aSKumar Kartikeya Dwivedi  */
93*72ed076aSKumar Kartikeya Dwivedi void test_summarization_freplace(void)
94*72ed076aSKumar Kartikeya Dwivedi {
95*72ed076aSKumar Kartikeya Dwivedi 	struct {
96*72ed076aSKumar Kartikeya Dwivedi 		const char *main;
97*72ed076aSKumar Kartikeya Dwivedi 		const char *to_be_replaced;
98*72ed076aSKumar Kartikeya Dwivedi 		bool has_side_effect;
99*72ed076aSKumar Kartikeya Dwivedi 	} mains[2][4] = {
100*72ed076aSKumar Kartikeya Dwivedi 		{
101*72ed076aSKumar Kartikeya Dwivedi 			{ "main_changes_with_subprogs",		"changes_pkt_data",	    true },
102*72ed076aSKumar Kartikeya Dwivedi 			{ "main_changes_with_subprogs",		"does_not_change_pkt_data", false },
103*72ed076aSKumar Kartikeya Dwivedi 			{ "main_changes",			"main_changes",             true },
104*72ed076aSKumar Kartikeya Dwivedi 			{ "main_does_not_change",		"main_does_not_change",     false },
105*72ed076aSKumar Kartikeya Dwivedi 		},
106*72ed076aSKumar Kartikeya Dwivedi 		{
107*72ed076aSKumar Kartikeya Dwivedi 			{ "main_might_sleep_with_subprogs",	"might_sleep",		    true },
108*72ed076aSKumar Kartikeya Dwivedi 			{ "main_might_sleep_with_subprogs",	"does_not_sleep",	    false },
109*72ed076aSKumar Kartikeya Dwivedi 			{ "main_might_sleep",			"main_might_sleep",	    true },
110*72ed076aSKumar Kartikeya Dwivedi 			{ "main_does_not_sleep",		"main_does_not_sleep",	    false },
111*72ed076aSKumar Kartikeya Dwivedi 		},
112*72ed076aSKumar Kartikeya Dwivedi 	};
113*72ed076aSKumar Kartikeya Dwivedi 	const char *pkt_err = "Extension program changes packet data";
114*72ed076aSKumar Kartikeya Dwivedi 	const char *slp_err = "Extension program may sleep";
115*72ed076aSKumar Kartikeya Dwivedi 	struct {
116*72ed076aSKumar Kartikeya Dwivedi 		const char *func;
117*72ed076aSKumar Kartikeya Dwivedi 		bool has_side_effect;
118*72ed076aSKumar Kartikeya Dwivedi 		const char *err_msg;
119*72ed076aSKumar Kartikeya Dwivedi 	} replacements[2][2] = {
120*72ed076aSKumar Kartikeya Dwivedi 		{
121*72ed076aSKumar Kartikeya Dwivedi 			{ "changes_pkt_data",	      true,	pkt_err },
122*72ed076aSKumar Kartikeya Dwivedi 			{ "does_not_change_pkt_data", false,	pkt_err },
123*72ed076aSKumar Kartikeya Dwivedi 		},
124*72ed076aSKumar Kartikeya Dwivedi 		{
125*72ed076aSKumar Kartikeya Dwivedi 			{ "might_sleep",	      true,	slp_err },
126*72ed076aSKumar Kartikeya Dwivedi 			{ "does_not_sleep",	      false,	slp_err },
127*72ed076aSKumar Kartikeya Dwivedi 		},
128*72ed076aSKumar Kartikeya Dwivedi 	};
129*72ed076aSKumar Kartikeya Dwivedi 	char buf[64];
130*72ed076aSKumar Kartikeya Dwivedi 
131*72ed076aSKumar Kartikeya Dwivedi 	for (int t = 0; t < 2; t++) {
132*72ed076aSKumar Kartikeya Dwivedi 		for (int i = 0; i < ARRAY_SIZE(mains); ++i) {
133*72ed076aSKumar Kartikeya Dwivedi 			for (int j = 0; j < ARRAY_SIZE(replacements); ++j) {
134*72ed076aSKumar Kartikeya Dwivedi 				snprintf(buf, sizeof(buf), "%s_with_%s",
135*72ed076aSKumar Kartikeya Dwivedi 					 mains[t][i].to_be_replaced, replacements[t][j].func);
136*72ed076aSKumar Kartikeya Dwivedi 				if (!test__start_subtest(buf))
137*72ed076aSKumar Kartikeya Dwivedi 					continue;
138*72ed076aSKumar Kartikeya Dwivedi 				test_aux(mains[t][i].main, mains[t][i].to_be_replaced, replacements[t][j].func,
139*72ed076aSKumar Kartikeya Dwivedi 					 mains[t][i].has_side_effect || !replacements[t][j].has_side_effect,
140*72ed076aSKumar Kartikeya Dwivedi 					 replacements[t][j].err_msg);
141*72ed076aSKumar Kartikeya Dwivedi 			}
142*72ed076aSKumar Kartikeya Dwivedi 		}
143*72ed076aSKumar Kartikeya Dwivedi 	}
144*72ed076aSKumar Kartikeya Dwivedi }
145