162306a36Sopenharmony_ci/* Copyright (c) 2017 Facebook
262306a36Sopenharmony_ci *
362306a36Sopenharmony_ci * This program is free software; you can redistribute it and/or
462306a36Sopenharmony_ci * modify it under the terms of version 2 of the GNU General Public
562306a36Sopenharmony_ci * License as published by the Free Software Foundation.
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include <linux/bpf.h>
962306a36Sopenharmony_ci#include <linux/version.h>
1062306a36Sopenharmony_ci#include <bpf/bpf_helpers.h>
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ciSEC("cgroup/dev")
1362306a36Sopenharmony_ciint bpf_prog1(struct bpf_cgroup_dev_ctx *ctx)
1462306a36Sopenharmony_ci{
1562306a36Sopenharmony_ci	short type = ctx->access_type & 0xFFFF;
1662306a36Sopenharmony_ci#ifdef DEBUG
1762306a36Sopenharmony_ci	short access = ctx->access_type >> 16;
1862306a36Sopenharmony_ci	char fmt[] = "  %d:%d    \n";
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci	switch (type) {
2162306a36Sopenharmony_ci	case BPF_DEVCG_DEV_BLOCK:
2262306a36Sopenharmony_ci		fmt[0] = 'b';
2362306a36Sopenharmony_ci		break;
2462306a36Sopenharmony_ci	case BPF_DEVCG_DEV_CHAR:
2562306a36Sopenharmony_ci		fmt[0] = 'c';
2662306a36Sopenharmony_ci		break;
2762306a36Sopenharmony_ci	default:
2862306a36Sopenharmony_ci		fmt[0] = '?';
2962306a36Sopenharmony_ci		break;
3062306a36Sopenharmony_ci	}
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci	if (access & BPF_DEVCG_ACC_READ)
3362306a36Sopenharmony_ci		fmt[8] = 'r';
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci	if (access & BPF_DEVCG_ACC_WRITE)
3662306a36Sopenharmony_ci		fmt[9] = 'w';
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci	if (access & BPF_DEVCG_ACC_MKNOD)
3962306a36Sopenharmony_ci		fmt[10] = 'm';
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci	bpf_trace_printk(fmt, sizeof(fmt), ctx->major, ctx->minor);
4262306a36Sopenharmony_ci#endif
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci	/* Allow access to /dev/zero and /dev/random.
4562306a36Sopenharmony_ci	 * Forbid everything else.
4662306a36Sopenharmony_ci	 */
4762306a36Sopenharmony_ci	if (ctx->major != 1 || type != BPF_DEVCG_DEV_CHAR)
4862306a36Sopenharmony_ci		return 0;
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci	switch (ctx->minor) {
5162306a36Sopenharmony_ci	case 5: /* 1:5 /dev/zero */
5262306a36Sopenharmony_ci	case 9: /* 1:9 /dev/urandom */
5362306a36Sopenharmony_ci		return 1;
5462306a36Sopenharmony_ci	}
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci	return 0;
5762306a36Sopenharmony_ci}
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_cichar _license[] SEC("license") = "GPL";
60