Skip to content

Program type BPF_PROG_TYPE_CGROUP_DEVICE

v4.15

cGroup device programs are executed when a process in the cGroup to which the program is attached wishes to utilize a device. The program can then decide whether or not to allow the process to allow that operation.

Usage

This program type is the cGroup v2 variant of the device whitelist controller. This program type is typically located in a cgroup/dev ELF section. It is called with a context describing the access attempt, if the program returns 0, the attempt fails with -EPERM, otherwise it succeeds.

Context

The program takes a pointer to the bpf_cgroup_dev_ctx structure, which describes the device access attempt: access type (mknod/read/write) and device (type, major and minor numbers). If the program returns 0, the attempt fails with -EPERM, otherwise it succeeds.

struct bpf_cgroup_dev_ctx {
    /* access_type encoded as (BPF_DEVCG_ACC_* << 16) | BPF_DEVCG_DEV_* */
    __u32 access_type;
    __u32 major;
    __u32 minor;
};

enum {
    BPF_DEVCG_ACC_MKNOD = (1ULL << 0),
    BPF_DEVCG_ACC_READ  = (1ULL << 1),
    BPF_DEVCG_ACC_WRITE = (1ULL << 2),
};

enum {
    BPF_DEVCG_DEV_BLOCK = (1ULL << 0),
    BPF_DEVCG_DEV_CHAR  = (1ULL << 1),
};

Attachment

cGroup socket buffer programs are attached to cgroups via the BPF_PROG_ATTACH syscall or via BPF link.

Example

Example BPF program:

/* Copyright (c) 2017 Facebook
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of version 2 of the GNU General Public
 * License as published by the Free Software Foundation.
 */

#include <linux/bpf.h>
#include <linux/version.h>
#include <bpf/bpf_helpers.h>

SEC("cgroup/dev")
int bpf_prog1(struct bpf_cgroup_dev_ctx *ctx)
{
    short type = ctx->access_type & 0xFFFF;
#ifdef DEBUG
    short access = ctx->access_type >> 16;
    char fmt[] = "  %d:%d    \n";

    switch (type) {
    case BPF_DEVCG_DEV_BLOCK:
        fmt[0] = 'b';
        break;
    case BPF_DEVCG_DEV_CHAR:
        fmt[0] = 'c';
        break;
    default:
        fmt[0] = '?';
        break;
    }

    if (access & BPF_DEVCG_ACC_READ)
        fmt[8] = 'r';

    if (access & BPF_DEVCG_ACC_WRITE)
        fmt[9] = 'w';

    if (access & BPF_DEVCG_ACC_MKNOD)
        fmt[10] = 'm';

    bpf_trace_printk(fmt, sizeof(fmt), ctx->major, ctx->minor);
#endif

    /* Allow access to /dev/zero and /dev/random.
     * Forbid everything else.
     */
    if (ctx->major != 1 || type != BPF_DEVCG_DEV_CHAR)
        return 0;

    switch (ctx->minor) {
    case 5: /* 1:5 /dev/zero */
    case 9: /* 1:9 /dev/urandom */
        return 1;
    }

    return 0;
}

char _license[] SEC("license") = "GPL";

Helper functions

Supported helper functions

KFuncs

There are currently no kfuncs supported for this program type