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