1*4e5070b6SJoanne Koong // SPDX-License-Identifier: GPL-2.0 2*4e5070b6SJoanne Koong /* Copyright (c) 2021 Facebook */ 3*4e5070b6SJoanne Koong 4*4e5070b6SJoanne Koong #include "vmlinux.h" 5*4e5070b6SJoanne Koong #include <bpf/bpf_helpers.h> 6*4e5070b6SJoanne Koong 7*4e5070b6SJoanne Koong char _license[] SEC("license") = "GPL"; 8*4e5070b6SJoanne Koong 9*4e5070b6SJoanne Koong struct callback_ctx { 10*4e5070b6SJoanne Koong int output; 11*4e5070b6SJoanne Koong }; 12*4e5070b6SJoanne Koong 13*4e5070b6SJoanne Koong /* These should be set by the user program */ 14*4e5070b6SJoanne Koong u32 nested_callback_nr_loops; 15*4e5070b6SJoanne Koong u32 stop_index = -1; 16*4e5070b6SJoanne Koong u32 nr_loops; 17*4e5070b6SJoanne Koong int pid; 18*4e5070b6SJoanne Koong 19*4e5070b6SJoanne Koong /* Making these global variables so that the userspace program 20*4e5070b6SJoanne Koong * can verify the output through the skeleton 21*4e5070b6SJoanne Koong */ 22*4e5070b6SJoanne Koong int nr_loops_returned; 23*4e5070b6SJoanne Koong int g_output; 24*4e5070b6SJoanne Koong int err; 25*4e5070b6SJoanne Koong 26*4e5070b6SJoanne Koong static int callback(__u32 index, void *data) 27*4e5070b6SJoanne Koong { 28*4e5070b6SJoanne Koong struct callback_ctx *ctx = data; 29*4e5070b6SJoanne Koong 30*4e5070b6SJoanne Koong if (index >= stop_index) 31*4e5070b6SJoanne Koong return 1; 32*4e5070b6SJoanne Koong 33*4e5070b6SJoanne Koong ctx->output += index; 34*4e5070b6SJoanne Koong 35*4e5070b6SJoanne Koong return 0; 36*4e5070b6SJoanne Koong } 37*4e5070b6SJoanne Koong 38*4e5070b6SJoanne Koong static int empty_callback(__u32 index, void *data) 39*4e5070b6SJoanne Koong { 40*4e5070b6SJoanne Koong return 0; 41*4e5070b6SJoanne Koong } 42*4e5070b6SJoanne Koong 43*4e5070b6SJoanne Koong static int nested_callback2(__u32 index, void *data) 44*4e5070b6SJoanne Koong { 45*4e5070b6SJoanne Koong nr_loops_returned += bpf_loop(nested_callback_nr_loops, callback, data, 0); 46*4e5070b6SJoanne Koong 47*4e5070b6SJoanne Koong return 0; 48*4e5070b6SJoanne Koong } 49*4e5070b6SJoanne Koong 50*4e5070b6SJoanne Koong static int nested_callback1(__u32 index, void *data) 51*4e5070b6SJoanne Koong { 52*4e5070b6SJoanne Koong bpf_loop(nested_callback_nr_loops, nested_callback2, data, 0); 53*4e5070b6SJoanne Koong return 0; 54*4e5070b6SJoanne Koong } 55*4e5070b6SJoanne Koong 56*4e5070b6SJoanne Koong SEC("fentry/__x64_sys_nanosleep") 57*4e5070b6SJoanne Koong int test_prog(void *ctx) 58*4e5070b6SJoanne Koong { 59*4e5070b6SJoanne Koong struct callback_ctx data = {}; 60*4e5070b6SJoanne Koong 61*4e5070b6SJoanne Koong if (bpf_get_current_pid_tgid() >> 32 != pid) 62*4e5070b6SJoanne Koong return 0; 63*4e5070b6SJoanne Koong 64*4e5070b6SJoanne Koong nr_loops_returned = bpf_loop(nr_loops, callback, &data, 0); 65*4e5070b6SJoanne Koong 66*4e5070b6SJoanne Koong if (nr_loops_returned < 0) 67*4e5070b6SJoanne Koong err = nr_loops_returned; 68*4e5070b6SJoanne Koong else 69*4e5070b6SJoanne Koong g_output = data.output; 70*4e5070b6SJoanne Koong 71*4e5070b6SJoanne Koong return 0; 72*4e5070b6SJoanne Koong } 73*4e5070b6SJoanne Koong 74*4e5070b6SJoanne Koong SEC("fentry/__x64_sys_nanosleep") 75*4e5070b6SJoanne Koong int prog_null_ctx(void *ctx) 76*4e5070b6SJoanne Koong { 77*4e5070b6SJoanne Koong if (bpf_get_current_pid_tgid() >> 32 != pid) 78*4e5070b6SJoanne Koong return 0; 79*4e5070b6SJoanne Koong 80*4e5070b6SJoanne Koong nr_loops_returned = bpf_loop(nr_loops, empty_callback, NULL, 0); 81*4e5070b6SJoanne Koong 82*4e5070b6SJoanne Koong return 0; 83*4e5070b6SJoanne Koong } 84*4e5070b6SJoanne Koong 85*4e5070b6SJoanne Koong SEC("fentry/__x64_sys_nanosleep") 86*4e5070b6SJoanne Koong int prog_invalid_flags(void *ctx) 87*4e5070b6SJoanne Koong { 88*4e5070b6SJoanne Koong struct callback_ctx data = {}; 89*4e5070b6SJoanne Koong 90*4e5070b6SJoanne Koong if (bpf_get_current_pid_tgid() >> 32 != pid) 91*4e5070b6SJoanne Koong return 0; 92*4e5070b6SJoanne Koong 93*4e5070b6SJoanne Koong err = bpf_loop(nr_loops, callback, &data, 1); 94*4e5070b6SJoanne Koong 95*4e5070b6SJoanne Koong return 0; 96*4e5070b6SJoanne Koong } 97*4e5070b6SJoanne Koong 98*4e5070b6SJoanne Koong SEC("fentry/__x64_sys_nanosleep") 99*4e5070b6SJoanne Koong int prog_nested_calls(void *ctx) 100*4e5070b6SJoanne Koong { 101*4e5070b6SJoanne Koong struct callback_ctx data = {}; 102*4e5070b6SJoanne Koong 103*4e5070b6SJoanne Koong if (bpf_get_current_pid_tgid() >> 32 != pid) 104*4e5070b6SJoanne Koong return 0; 105*4e5070b6SJoanne Koong 106*4e5070b6SJoanne Koong nr_loops_returned = 0; 107*4e5070b6SJoanne Koong bpf_loop(nr_loops, nested_callback1, &data, 0); 108*4e5070b6SJoanne Koong 109*4e5070b6SJoanne Koong g_output = data.output; 110*4e5070b6SJoanne Koong 111*4e5070b6SJoanne Koong return 0; 112*4e5070b6SJoanne Koong } 113