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