Skip to content

Commit

Permalink
bpf: add BPF_PROG_ATTACH and BPF_PROG_DETACH commands
Browse files Browse the repository at this point in the history
Extend the bpf(2) syscall by two new commands, BPF_PROG_ATTACH and
BPF_PROG_DETACH which allow attaching and detaching eBPF programs
to a target.

On the API level, the target could be anything that has an fd in
userspace, hence the name of the field in union bpf_attr is called
'target_fd'.

When called with BPF_ATTACH_TYPE_CGROUP_INET_{E,IN}GRESS, the target is
expected to be a valid file descriptor of a cgroup v2 directory which
has the bpf controller enabled. These are the only use-cases
implemented by this patch at this point, but more can be added.

If a program of the given type already exists in the given cgroup,
the program is swapped automically, so userspace does not have to drop
an existing program first before installing a new one, which would
otherwise leave a gap in which no program is attached.

For more information on the propagation logic to subcgroups, please
refer to the bpf cgroup controller implementation.

The API is guarded by CAP_NET_ADMIN.

Signed-off-by: Daniel Mack <daniel@zonque.org>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
zonque authored and davem330 committed Nov 25, 2016
1 parent 3007098 commit f432455
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 0 deletions.
8 changes: 8 additions & 0 deletions include/uapi/linux/bpf.h
Expand Up @@ -73,6 +73,8 @@ enum bpf_cmd {
BPF_PROG_LOAD,
BPF_OBJ_PIN,
BPF_OBJ_GET,
BPF_PROG_ATTACH,
BPF_PROG_DETACH,
};

enum bpf_map_type {
Expand Down Expand Up @@ -159,6 +161,12 @@ union bpf_attr {
__aligned_u64 pathname;
__u32 bpf_fd;
};

struct { /* anonymous struct used by BPF_PROG_ATTACH/DETACH commands */
__u32 target_fd; /* container object to attach to */
__u32 attach_bpf_fd; /* eBPF program to attach */
__u32 attach_type;
};
} __attribute__((aligned(8)));

/* BPF helper function descriptions:
Expand Down
81 changes: 81 additions & 0 deletions kernel/bpf/syscall.c
Expand Up @@ -835,6 +835,77 @@ static int bpf_obj_get(const union bpf_attr *attr)
return bpf_obj_get_user(u64_to_user_ptr(attr->pathname));
}

#ifdef CONFIG_CGROUP_BPF

#define BPF_PROG_ATTACH_LAST_FIELD attach_type

static int bpf_prog_attach(const union bpf_attr *attr)
{
struct bpf_prog *prog;
struct cgroup *cgrp;

if (!capable(CAP_NET_ADMIN))
return -EPERM;

if (CHECK_ATTR(BPF_PROG_ATTACH))
return -EINVAL;

switch (attr->attach_type) {
case BPF_CGROUP_INET_INGRESS:
case BPF_CGROUP_INET_EGRESS:
prog = bpf_prog_get_type(attr->attach_bpf_fd,
BPF_PROG_TYPE_CGROUP_SKB);
if (IS_ERR(prog))
return PTR_ERR(prog);

cgrp = cgroup_get_from_fd(attr->target_fd);
if (IS_ERR(cgrp)) {
bpf_prog_put(prog);
return PTR_ERR(cgrp);
}

cgroup_bpf_update(cgrp, prog, attr->attach_type);
cgroup_put(cgrp);
break;

default:
return -EINVAL;
}

return 0;
}

#define BPF_PROG_DETACH_LAST_FIELD attach_type

static int bpf_prog_detach(const union bpf_attr *attr)
{
struct cgroup *cgrp;

if (!capable(CAP_NET_ADMIN))
return -EPERM;

if (CHECK_ATTR(BPF_PROG_DETACH))
return -EINVAL;

switch (attr->attach_type) {
case BPF_CGROUP_INET_INGRESS:
case BPF_CGROUP_INET_EGRESS:
cgrp = cgroup_get_from_fd(attr->target_fd);
if (IS_ERR(cgrp))
return PTR_ERR(cgrp);

cgroup_bpf_update(cgrp, NULL, attr->attach_type);
cgroup_put(cgrp);
break;

default:
return -EINVAL;
}

return 0;
}
#endif /* CONFIG_CGROUP_BPF */

SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, size)
{
union bpf_attr attr = {};
Expand Down Expand Up @@ -901,6 +972,16 @@ SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, siz
case BPF_OBJ_GET:
err = bpf_obj_get(&attr);
break;

#ifdef CONFIG_CGROUP_BPF
case BPF_PROG_ATTACH:
err = bpf_prog_attach(&attr);
break;
case BPF_PROG_DETACH:
err = bpf_prog_detach(&attr);
break;
#endif

default:
err = -EINVAL;
break;
Expand Down

0 comments on commit f432455

Please sign in to comment.