Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.2.
  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}