at v4.14-rc3 196 lines 4.7 kB view raw
1/* eBPF example program: 2 * 3 * - Creates arraymap in kernel with 4 bytes keys and 8 byte values 4 * 5 * - Loads eBPF program 6 * 7 * The eBPF program accesses the map passed in to store two pieces of 8 * information. The number of invocations of the program, which maps 9 * to the number of packets received, is stored to key 0. Key 1 is 10 * incremented on each iteration by the number of bytes stored in 11 * the skb. 12 * 13 * - Attaches the new program to a cgroup using BPF_PROG_ATTACH 14 * 15 * - Every second, reads map[0] and map[1] to see how many bytes and 16 * packets were seen on any socket of tasks in the given cgroup. 17 */ 18 19#define _GNU_SOURCE 20 21#include <stdio.h> 22#include <stdlib.h> 23#include <assert.h> 24#include <unistd.h> 25 26#include <linux/bpf.h> 27 28#include "libbpf.h" 29#include "cgroup_helpers.h" 30 31#define FOO "/foo" 32#define BAR "/foo/bar/" 33#define PING_CMD "ping -c1 -w1 127.0.0.1" 34 35char bpf_log_buf[BPF_LOG_BUF_SIZE]; 36 37static int prog_load(int verdict) 38{ 39 int ret; 40 struct bpf_insn prog[] = { 41 BPF_MOV64_IMM(BPF_REG_0, verdict), /* r0 = verdict */ 42 BPF_EXIT_INSN(), 43 }; 44 size_t insns_cnt = sizeof(prog) / sizeof(struct bpf_insn); 45 46 ret = bpf_load_program(BPF_PROG_TYPE_CGROUP_SKB, 47 prog, insns_cnt, "GPL", 0, 48 bpf_log_buf, BPF_LOG_BUF_SIZE); 49 50 if (ret < 0) { 51 log_err("Loading program"); 52 printf("Output from verifier:\n%s\n-------\n", bpf_log_buf); 53 return 0; 54 } 55 return ret; 56} 57 58 59int main(int argc, char **argv) 60{ 61 int drop_prog, allow_prog, foo = 0, bar = 0, rc = 0; 62 63 allow_prog = prog_load(1); 64 if (!allow_prog) 65 goto err; 66 67 drop_prog = prog_load(0); 68 if (!drop_prog) 69 goto err; 70 71 if (setup_cgroup_environment()) 72 goto err; 73 74 /* Create cgroup /foo, get fd, and join it */ 75 foo = create_and_get_cgroup(FOO); 76 if (!foo) 77 goto err; 78 79 if (join_cgroup(FOO)) 80 goto err; 81 82 if (bpf_prog_attach(drop_prog, foo, BPF_CGROUP_INET_EGRESS, 1)) { 83 log_err("Attaching prog to /foo"); 84 goto err; 85 } 86 87 printf("Attached DROP prog. This ping in cgroup /foo should fail...\n"); 88 assert(system(PING_CMD) != 0); 89 90 /* Create cgroup /foo/bar, get fd, and join it */ 91 bar = create_and_get_cgroup(BAR); 92 if (!bar) 93 goto err; 94 95 if (join_cgroup(BAR)) 96 goto err; 97 98 printf("Attached DROP prog. This ping in cgroup /foo/bar should fail...\n"); 99 assert(system(PING_CMD) != 0); 100 101 if (bpf_prog_attach(allow_prog, bar, BPF_CGROUP_INET_EGRESS, 1)) { 102 log_err("Attaching prog to /foo/bar"); 103 goto err; 104 } 105 106 printf("Attached PASS prog. This ping in cgroup /foo/bar should pass...\n"); 107 assert(system(PING_CMD) == 0); 108 109 if (bpf_prog_detach(bar, BPF_CGROUP_INET_EGRESS)) { 110 log_err("Detaching program from /foo/bar"); 111 goto err; 112 } 113 114 printf("Detached PASS from /foo/bar while DROP is attached to /foo.\n" 115 "This ping in cgroup /foo/bar should fail...\n"); 116 assert(system(PING_CMD) != 0); 117 118 if (bpf_prog_attach(allow_prog, bar, BPF_CGROUP_INET_EGRESS, 1)) { 119 log_err("Attaching prog to /foo/bar"); 120 goto err; 121 } 122 123 if (bpf_prog_detach(foo, BPF_CGROUP_INET_EGRESS)) { 124 log_err("Detaching program from /foo"); 125 goto err; 126 } 127 128 printf("Attached PASS from /foo/bar and detached DROP from /foo.\n" 129 "This ping in cgroup /foo/bar should pass...\n"); 130 assert(system(PING_CMD) == 0); 131 132 if (bpf_prog_attach(allow_prog, bar, BPF_CGROUP_INET_EGRESS, 1)) { 133 log_err("Attaching prog to /foo/bar"); 134 goto err; 135 } 136 137 if (!bpf_prog_attach(allow_prog, bar, BPF_CGROUP_INET_EGRESS, 0)) { 138 errno = 0; 139 log_err("Unexpected success attaching prog to /foo/bar"); 140 goto err; 141 } 142 143 if (bpf_prog_detach(bar, BPF_CGROUP_INET_EGRESS)) { 144 log_err("Detaching program from /foo/bar"); 145 goto err; 146 } 147 148 if (!bpf_prog_detach(foo, BPF_CGROUP_INET_EGRESS)) { 149 errno = 0; 150 log_err("Unexpected success in double detach from /foo"); 151 goto err; 152 } 153 154 if (bpf_prog_attach(allow_prog, foo, BPF_CGROUP_INET_EGRESS, 0)) { 155 log_err("Attaching non-overridable prog to /foo"); 156 goto err; 157 } 158 159 if (!bpf_prog_attach(allow_prog, bar, BPF_CGROUP_INET_EGRESS, 0)) { 160 errno = 0; 161 log_err("Unexpected success attaching non-overridable prog to /foo/bar"); 162 goto err; 163 } 164 165 if (!bpf_prog_attach(allow_prog, bar, BPF_CGROUP_INET_EGRESS, 1)) { 166 errno = 0; 167 log_err("Unexpected success attaching overridable prog to /foo/bar"); 168 goto err; 169 } 170 171 if (!bpf_prog_attach(allow_prog, foo, BPF_CGROUP_INET_EGRESS, 1)) { 172 errno = 0; 173 log_err("Unexpected success attaching overridable prog to /foo"); 174 goto err; 175 } 176 177 if (bpf_prog_attach(drop_prog, foo, BPF_CGROUP_INET_EGRESS, 0)) { 178 log_err("Attaching different non-overridable prog to /foo"); 179 goto err; 180 } 181 182 goto out; 183 184err: 185 rc = 1; 186 187out: 188 close(foo); 189 close(bar); 190 cleanup_cgroup_environment(); 191 if (!rc) 192 printf("PASS\n"); 193 else 194 printf("FAIL\n"); 195 return rc; 196}