1bd4aed0eSJiong Wang /* Copyright (c) 2017 Facebook
2bd4aed0eSJiong Wang  *
3bd4aed0eSJiong Wang  * This program is free software; you can redistribute it and/or
4bd4aed0eSJiong Wang  * modify it under the terms of version 2 of the GNU General Public
5bd4aed0eSJiong Wang  * License as published by the Free Software Foundation.
6bd4aed0eSJiong Wang  */
7bd4aed0eSJiong Wang 
8bd4aed0eSJiong Wang #include <linux/bpf.h>
9bd4aed0eSJiong Wang #include <linux/version.h>
103e689141SToke Høiland-Jørgensen #include <bpf/bpf_helpers.h>
11bd4aed0eSJiong Wang 
12bd4aed0eSJiong Wang SEC("cgroup/dev")
bpf_prog1(struct bpf_cgroup_dev_ctx * ctx)13bd4aed0eSJiong Wang int bpf_prog1(struct bpf_cgroup_dev_ctx *ctx)
14bd4aed0eSJiong Wang {
15bd4aed0eSJiong Wang 	short type = ctx->access_type & 0xFFFF;
16bd4aed0eSJiong Wang #ifdef DEBUG
17bd4aed0eSJiong Wang 	short access = ctx->access_type >> 16;
18bd4aed0eSJiong Wang 	char fmt[] = "  %d:%d    \n";
19bd4aed0eSJiong Wang 
20bd4aed0eSJiong Wang 	switch (type) {
21bd4aed0eSJiong Wang 	case BPF_DEVCG_DEV_BLOCK:
22bd4aed0eSJiong Wang 		fmt[0] = 'b';
23bd4aed0eSJiong Wang 		break;
24bd4aed0eSJiong Wang 	case BPF_DEVCG_DEV_CHAR:
25bd4aed0eSJiong Wang 		fmt[0] = 'c';
26bd4aed0eSJiong Wang 		break;
27bd4aed0eSJiong Wang 	default:
28bd4aed0eSJiong Wang 		fmt[0] = '?';
29bd4aed0eSJiong Wang 		break;
30bd4aed0eSJiong Wang 	}
31bd4aed0eSJiong Wang 
32bd4aed0eSJiong Wang 	if (access & BPF_DEVCG_ACC_READ)
33bd4aed0eSJiong Wang 		fmt[8] = 'r';
34bd4aed0eSJiong Wang 
35bd4aed0eSJiong Wang 	if (access & BPF_DEVCG_ACC_WRITE)
36bd4aed0eSJiong Wang 		fmt[9] = 'w';
37bd4aed0eSJiong Wang 
38bd4aed0eSJiong Wang 	if (access & BPF_DEVCG_ACC_MKNOD)
39bd4aed0eSJiong Wang 		fmt[10] = 'm';
40bd4aed0eSJiong Wang 
41bd4aed0eSJiong Wang 	bpf_trace_printk(fmt, sizeof(fmt), ctx->major, ctx->minor);
42bd4aed0eSJiong Wang #endif
43bd4aed0eSJiong Wang 
44bd4aed0eSJiong Wang 	/* Allow access to /dev/zero and /dev/random.
45bd4aed0eSJiong Wang 	 * Forbid everything else.
46bd4aed0eSJiong Wang 	 */
47bd4aed0eSJiong Wang 	if (ctx->major != 1 || type != BPF_DEVCG_DEV_CHAR)
48bd4aed0eSJiong Wang 		return 0;
49bd4aed0eSJiong Wang 
50bd4aed0eSJiong Wang 	switch (ctx->minor) {
51bd4aed0eSJiong Wang 	case 5: /* 1:5 /dev/zero */
52bd4aed0eSJiong Wang 	case 9: /* 1:9 /dev/urandom */
53bd4aed0eSJiong Wang 		return 1;
54bd4aed0eSJiong Wang 	}
55bd4aed0eSJiong Wang 
56bd4aed0eSJiong Wang 	return 0;
57bd4aed0eSJiong Wang }
58bd4aed0eSJiong Wang 
59bd4aed0eSJiong Wang char _license[] SEC("license") = "GPL";
60