410 lines · c
1// SPDX-License-Identifier: GPL-2.02#include <test_progs.h>3#include <network_helpers.h>4 5#include "exceptions.skel.h"6#include "exceptions_ext.skel.h"7#include "exceptions_fail.skel.h"8#include "exceptions_assert.skel.h"9 10static char log_buf[1024 * 1024];11 12static void test_exceptions_failure(void)13{14 RUN_TESTS(exceptions_fail);15}16 17static void test_exceptions_success(void)18{19 LIBBPF_OPTS(bpf_test_run_opts, ropts,20 .data_in = &pkt_v4,21 .data_size_in = sizeof(pkt_v4),22 .repeat = 1,23 );24 struct exceptions_ext *eskel = NULL;25 struct exceptions *skel;26 int ret;27 28 skel = exceptions__open();29 if (!ASSERT_OK_PTR(skel, "exceptions__open"))30 return;31 32 ret = exceptions__load(skel);33 if (!ASSERT_OK(ret, "exceptions__load"))34 goto done;35 36 if (!ASSERT_OK(bpf_map_update_elem(bpf_map__fd(skel->maps.jmp_table), &(int){0},37 &(int){bpf_program__fd(skel->progs.exception_tail_call_target)}, BPF_ANY),38 "bpf_map_update_elem jmp_table"))39 goto done;40 41#define RUN_SUCCESS(_prog, return_val) \42 if (!test__start_subtest(#_prog)) goto _prog##_##return_val; \43 ret = bpf_prog_test_run_opts(bpf_program__fd(skel->progs._prog), &ropts); \44 ASSERT_OK(ret, #_prog " prog run ret"); \45 ASSERT_EQ(ropts.retval, return_val, #_prog " prog run retval"); \46 _prog##_##return_val:47 48 RUN_SUCCESS(exception_throw_always_1, 64);49 RUN_SUCCESS(exception_throw_always_2, 32);50 RUN_SUCCESS(exception_throw_unwind_1, 16);51 RUN_SUCCESS(exception_throw_unwind_2, 32);52 RUN_SUCCESS(exception_throw_default, 0);53 RUN_SUCCESS(exception_throw_default_value, 5);54 RUN_SUCCESS(exception_tail_call, 24);55 RUN_SUCCESS(exception_ext, 0);56 RUN_SUCCESS(exception_ext_mod_cb_runtime, 35);57 RUN_SUCCESS(exception_throw_subprog, 1);58 RUN_SUCCESS(exception_assert_nz_gfunc, 1);59 RUN_SUCCESS(exception_assert_zero_gfunc, 1);60 RUN_SUCCESS(exception_assert_neg_gfunc, 1);61 RUN_SUCCESS(exception_assert_pos_gfunc, 1);62 RUN_SUCCESS(exception_assert_negeq_gfunc, 1);63 RUN_SUCCESS(exception_assert_poseq_gfunc, 1);64 RUN_SUCCESS(exception_assert_nz_gfunc_with, 1);65 RUN_SUCCESS(exception_assert_zero_gfunc_with, 1);66 RUN_SUCCESS(exception_assert_neg_gfunc_with, 1);67 RUN_SUCCESS(exception_assert_pos_gfunc_with, 1);68 RUN_SUCCESS(exception_assert_negeq_gfunc_with, 1);69 RUN_SUCCESS(exception_assert_poseq_gfunc_with, 1);70 RUN_SUCCESS(exception_bad_assert_nz_gfunc, 0);71 RUN_SUCCESS(exception_bad_assert_zero_gfunc, 0);72 RUN_SUCCESS(exception_bad_assert_neg_gfunc, 0);73 RUN_SUCCESS(exception_bad_assert_pos_gfunc, 0);74 RUN_SUCCESS(exception_bad_assert_negeq_gfunc, 0);75 RUN_SUCCESS(exception_bad_assert_poseq_gfunc, 0);76 RUN_SUCCESS(exception_bad_assert_nz_gfunc_with, 100);77 RUN_SUCCESS(exception_bad_assert_zero_gfunc_with, 105);78 RUN_SUCCESS(exception_bad_assert_neg_gfunc_with, 200);79 RUN_SUCCESS(exception_bad_assert_pos_gfunc_with, 0);80 RUN_SUCCESS(exception_bad_assert_negeq_gfunc_with, 101);81 RUN_SUCCESS(exception_bad_assert_poseq_gfunc_with, 99);82 RUN_SUCCESS(exception_assert_range, 1);83 RUN_SUCCESS(exception_assert_range_with, 1);84 RUN_SUCCESS(exception_bad_assert_range, 0);85 RUN_SUCCESS(exception_bad_assert_range_with, 10);86 87#define RUN_EXT(load_ret, attach_err, expr, msg, after_link) \88 { \89 LIBBPF_OPTS(bpf_object_open_opts, o, .kernel_log_buf = log_buf, \90 .kernel_log_size = sizeof(log_buf), \91 .kernel_log_level = 2); \92 exceptions_ext__destroy(eskel); \93 eskel = exceptions_ext__open_opts(&o); \94 struct bpf_program *prog = NULL; \95 struct bpf_link *link = NULL; \96 if (!ASSERT_OK_PTR(eskel, "exceptions_ext__open")) \97 goto done; \98 (expr); \99 ASSERT_OK_PTR(bpf_program__name(prog), bpf_program__name(prog)); \100 if (!ASSERT_EQ(exceptions_ext__load(eskel), load_ret, \101 "exceptions_ext__load")) { \102 printf("%s\n", log_buf); \103 goto done; \104 } \105 if (load_ret != 0) { \106 if (!ASSERT_OK_PTR(strstr(log_buf, msg), "strstr")) { \107 printf("%s\n", log_buf); \108 goto done; \109 } \110 } \111 if (!load_ret && attach_err) { \112 if (!ASSERT_ERR_PTR(link = bpf_program__attach(prog), "attach err")) \113 goto done; \114 } else if (!load_ret) { \115 if (!ASSERT_OK_PTR(link = bpf_program__attach(prog), "attach ok")) \116 goto done; \117 (void)(after_link); \118 bpf_link__destroy(link); \119 } \120 }121 122 if (test__start_subtest("non-throwing fentry -> exception_cb"))123 RUN_EXT(-EINVAL, true, ({124 prog = eskel->progs.pfentry;125 bpf_program__set_autoload(prog, true);126 if (!ASSERT_OK(bpf_program__set_attach_target(prog,127 bpf_program__fd(skel->progs.exception_ext_mod_cb_runtime),128 "exception_cb_mod"), "set_attach_target"))129 goto done;130 }), "FENTRY/FEXIT programs cannot attach to exception callback", 0);131 132 if (test__start_subtest("throwing fentry -> exception_cb"))133 RUN_EXT(-EINVAL, true, ({134 prog = eskel->progs.throwing_fentry;135 bpf_program__set_autoload(prog, true);136 if (!ASSERT_OK(bpf_program__set_attach_target(prog,137 bpf_program__fd(skel->progs.exception_ext_mod_cb_runtime),138 "exception_cb_mod"), "set_attach_target"))139 goto done;140 }), "FENTRY/FEXIT programs cannot attach to exception callback", 0);141 142 if (test__start_subtest("non-throwing fexit -> exception_cb"))143 RUN_EXT(-EINVAL, true, ({144 prog = eskel->progs.pfexit;145 bpf_program__set_autoload(prog, true);146 if (!ASSERT_OK(bpf_program__set_attach_target(prog,147 bpf_program__fd(skel->progs.exception_ext_mod_cb_runtime),148 "exception_cb_mod"), "set_attach_target"))149 goto done;150 }), "FENTRY/FEXIT programs cannot attach to exception callback", 0);151 152 if (test__start_subtest("throwing fexit -> exception_cb"))153 RUN_EXT(-EINVAL, true, ({154 prog = eskel->progs.throwing_fexit;155 bpf_program__set_autoload(prog, true);156 if (!ASSERT_OK(bpf_program__set_attach_target(prog,157 bpf_program__fd(skel->progs.exception_ext_mod_cb_runtime),158 "exception_cb_mod"), "set_attach_target"))159 goto done;160 }), "FENTRY/FEXIT programs cannot attach to exception callback", 0);161 162 if (test__start_subtest("throwing extension (with custom cb) -> exception_cb"))163 RUN_EXT(-EINVAL, true, ({164 prog = eskel->progs.throwing_exception_cb_extension;165 bpf_program__set_autoload(prog, true);166 if (!ASSERT_OK(bpf_program__set_attach_target(prog,167 bpf_program__fd(skel->progs.exception_ext_mod_cb_runtime),168 "exception_cb_mod"), "set_attach_target"))169 goto done;170 }), "Extension programs cannot attach to exception callback", 0);171 172 if (test__start_subtest("throwing extension -> global func in exception_cb"))173 RUN_EXT(0, false, ({174 prog = eskel->progs.throwing_exception_cb_extension;175 bpf_program__set_autoload(prog, true);176 if (!ASSERT_OK(bpf_program__set_attach_target(prog,177 bpf_program__fd(skel->progs.exception_ext_mod_cb_runtime),178 "exception_cb_mod_global"), "set_attach_target"))179 goto done;180 }), "", ({ RUN_SUCCESS(exception_ext_mod_cb_runtime, 131); }));181 182 if (test__start_subtest("throwing extension (with custom cb) -> global func in exception_cb"))183 RUN_EXT(0, false, ({184 prog = eskel->progs.throwing_extension;185 bpf_program__set_autoload(prog, true);186 if (!ASSERT_OK(bpf_program__set_attach_target(prog,187 bpf_program__fd(skel->progs.exception_ext),188 "exception_ext_global"), "set_attach_target"))189 goto done;190 }), "", ({ RUN_SUCCESS(exception_ext, 128); }));191 192 if (test__start_subtest("non-throwing fentry -> non-throwing subprog"))193 /* non-throwing fentry -> non-throwing subprog : OK */194 RUN_EXT(0, false, ({195 prog = eskel->progs.pfentry;196 bpf_program__set_autoload(prog, true);197 if (!ASSERT_OK(bpf_program__set_attach_target(prog,198 bpf_program__fd(skel->progs.exception_throw_subprog),199 "subprog"), "set_attach_target"))200 goto done;201 }), "", 0);202 203 if (test__start_subtest("throwing fentry -> non-throwing subprog"))204 /* throwing fentry -> non-throwing subprog : OK */205 RUN_EXT(0, false, ({206 prog = eskel->progs.throwing_fentry;207 bpf_program__set_autoload(prog, true);208 if (!ASSERT_OK(bpf_program__set_attach_target(prog,209 bpf_program__fd(skel->progs.exception_throw_subprog),210 "subprog"), "set_attach_target"))211 goto done;212 }), "", 0);213 214 if (test__start_subtest("non-throwing fentry -> throwing subprog"))215 /* non-throwing fentry -> throwing subprog : OK */216 RUN_EXT(0, false, ({217 prog = eskel->progs.pfentry;218 bpf_program__set_autoload(prog, true);219 if (!ASSERT_OK(bpf_program__set_attach_target(prog,220 bpf_program__fd(skel->progs.exception_throw_subprog),221 "throwing_subprog"), "set_attach_target"))222 goto done;223 }), "", 0);224 225 if (test__start_subtest("throwing fentry -> throwing subprog"))226 /* throwing fentry -> throwing subprog : OK */227 RUN_EXT(0, false, ({228 prog = eskel->progs.throwing_fentry;229 bpf_program__set_autoload(prog, true);230 if (!ASSERT_OK(bpf_program__set_attach_target(prog,231 bpf_program__fd(skel->progs.exception_throw_subprog),232 "throwing_subprog"), "set_attach_target"))233 goto done;234 }), "", 0);235 236 if (test__start_subtest("non-throwing fexit -> non-throwing subprog"))237 /* non-throwing fexit -> non-throwing subprog : OK */238 RUN_EXT(0, false, ({239 prog = eskel->progs.pfexit;240 bpf_program__set_autoload(prog, true);241 if (!ASSERT_OK(bpf_program__set_attach_target(prog,242 bpf_program__fd(skel->progs.exception_throw_subprog),243 "subprog"), "set_attach_target"))244 goto done;245 }), "", 0);246 247 if (test__start_subtest("throwing fexit -> non-throwing subprog"))248 /* throwing fexit -> non-throwing subprog : OK */249 RUN_EXT(0, false, ({250 prog = eskel->progs.throwing_fexit;251 bpf_program__set_autoload(prog, true);252 if (!ASSERT_OK(bpf_program__set_attach_target(prog,253 bpf_program__fd(skel->progs.exception_throw_subprog),254 "subprog"), "set_attach_target"))255 goto done;256 }), "", 0);257 258 if (test__start_subtest("non-throwing fexit -> throwing subprog"))259 /* non-throwing fexit -> throwing subprog : OK */260 RUN_EXT(0, false, ({261 prog = eskel->progs.pfexit;262 bpf_program__set_autoload(prog, true);263 if (!ASSERT_OK(bpf_program__set_attach_target(prog,264 bpf_program__fd(skel->progs.exception_throw_subprog),265 "throwing_subprog"), "set_attach_target"))266 goto done;267 }), "", 0);268 269 if (test__start_subtest("throwing fexit -> throwing subprog"))270 /* throwing fexit -> throwing subprog : OK */271 RUN_EXT(0, false, ({272 prog = eskel->progs.throwing_fexit;273 bpf_program__set_autoload(prog, true);274 if (!ASSERT_OK(bpf_program__set_attach_target(prog,275 bpf_program__fd(skel->progs.exception_throw_subprog),276 "throwing_subprog"), "set_attach_target"))277 goto done;278 }), "", 0);279 280 /* fmod_ret not allowed for subprog - Check so we remember to handle its281 * throwing specification compatibility with target when supported.282 */283 if (test__start_subtest("non-throwing fmod_ret -> non-throwing subprog"))284 RUN_EXT(-EINVAL, true, ({285 prog = eskel->progs.pfmod_ret;286 bpf_program__set_autoload(prog, true);287 if (!ASSERT_OK(bpf_program__set_attach_target(prog,288 bpf_program__fd(skel->progs.exception_throw_subprog),289 "subprog"), "set_attach_target"))290 goto done;291 }), "can't modify return codes of BPF program", 0);292 293 /* fmod_ret not allowed for subprog - Check so we remember to handle its294 * throwing specification compatibility with target when supported.295 */296 if (test__start_subtest("non-throwing fmod_ret -> non-throwing global subprog"))297 RUN_EXT(-EINVAL, true, ({298 prog = eskel->progs.pfmod_ret;299 bpf_program__set_autoload(prog, true);300 if (!ASSERT_OK(bpf_program__set_attach_target(prog,301 bpf_program__fd(skel->progs.exception_throw_subprog),302 "global_subprog"), "set_attach_target"))303 goto done;304 }), "can't modify return codes of BPF program", 0);305 306 if (test__start_subtest("non-throwing extension -> non-throwing subprog"))307 /* non-throwing extension -> non-throwing subprog : BAD (!global) */308 RUN_EXT(-EINVAL, true, ({309 prog = eskel->progs.extension;310 bpf_program__set_autoload(prog, true);311 if (!ASSERT_OK(bpf_program__set_attach_target(prog,312 bpf_program__fd(skel->progs.exception_throw_subprog),313 "subprog"), "set_attach_target"))314 goto done;315 }), "subprog() is not a global function", 0);316 317 if (test__start_subtest("non-throwing extension -> throwing subprog"))318 /* non-throwing extension -> throwing subprog : BAD (!global) */319 RUN_EXT(-EINVAL, true, ({320 prog = eskel->progs.extension;321 bpf_program__set_autoload(prog, true);322 if (!ASSERT_OK(bpf_program__set_attach_target(prog,323 bpf_program__fd(skel->progs.exception_throw_subprog),324 "throwing_subprog"), "set_attach_target"))325 goto done;326 }), "throwing_subprog() is not a global function", 0);327 328 if (test__start_subtest("non-throwing extension -> non-throwing subprog"))329 /* non-throwing extension -> non-throwing global subprog : OK */330 RUN_EXT(0, false, ({331 prog = eskel->progs.extension;332 bpf_program__set_autoload(prog, true);333 if (!ASSERT_OK(bpf_program__set_attach_target(prog,334 bpf_program__fd(skel->progs.exception_throw_subprog),335 "global_subprog"), "set_attach_target"))336 goto done;337 }), "", 0);338 339 if (test__start_subtest("non-throwing extension -> throwing global subprog"))340 /* non-throwing extension -> throwing global subprog : OK */341 RUN_EXT(0, false, ({342 prog = eskel->progs.extension;343 bpf_program__set_autoload(prog, true);344 if (!ASSERT_OK(bpf_program__set_attach_target(prog,345 bpf_program__fd(skel->progs.exception_throw_subprog),346 "throwing_global_subprog"), "set_attach_target"))347 goto done;348 }), "", 0);349 350 if (test__start_subtest("throwing extension -> throwing global subprog"))351 /* throwing extension -> throwing global subprog : OK */352 RUN_EXT(0, false, ({353 prog = eskel->progs.throwing_extension;354 bpf_program__set_autoload(prog, true);355 if (!ASSERT_OK(bpf_program__set_attach_target(prog,356 bpf_program__fd(skel->progs.exception_throw_subprog),357 "throwing_global_subprog"), "set_attach_target"))358 goto done;359 }), "", 0);360 361 if (test__start_subtest("throwing extension -> non-throwing global subprog"))362 /* throwing extension -> non-throwing global subprog : OK */363 RUN_EXT(0, false, ({364 prog = eskel->progs.throwing_extension;365 bpf_program__set_autoload(prog, true);366 if (!ASSERT_OK(bpf_program__set_attach_target(prog,367 bpf_program__fd(skel->progs.exception_throw_subprog),368 "global_subprog"), "set_attach_target"))369 goto done;370 }), "", 0);371 372 if (test__start_subtest("non-throwing extension -> main subprog"))373 /* non-throwing extension -> main subprog : OK */374 RUN_EXT(0, false, ({375 prog = eskel->progs.extension;376 bpf_program__set_autoload(prog, true);377 if (!ASSERT_OK(bpf_program__set_attach_target(prog,378 bpf_program__fd(skel->progs.exception_throw_subprog),379 "exception_throw_subprog"), "set_attach_target"))380 goto done;381 }), "", 0);382 383 if (test__start_subtest("throwing extension -> main subprog"))384 /* throwing extension -> main subprog : OK */385 RUN_EXT(0, false, ({386 prog = eskel->progs.throwing_extension;387 bpf_program__set_autoload(prog, true);388 if (!ASSERT_OK(bpf_program__set_attach_target(prog,389 bpf_program__fd(skel->progs.exception_throw_subprog),390 "exception_throw_subprog"), "set_attach_target"))391 goto done;392 }), "", 0);393 394done:395 exceptions_ext__destroy(eskel);396 exceptions__destroy(skel);397}398 399static void test_exceptions_assertions(void)400{401 RUN_TESTS(exceptions_assert);402}403 404void test_exceptions(void)405{406 test_exceptions_success();407 test_exceptions_failure();408 test_exceptions_assertions();409}410