bpf: fix attach type BPF_LIRC_MODE2 dependency wrt CONFIG_CGROUP_BPF
If the kernel is compiled with CONFIG_CGROUP_BPF not enabled, it is not
possible to attach, detach or query IR BPF programs to /dev/lircN devices,
making them impossible to use. For embedded devices, it should be possible
to use IR decoding without cgroups or CONFIG_CGROUP_BPF enabled.
This change requires some refactoring, since bpf_prog_{attach,detach,query}
functions are now always compiled, but their code paths for cgroups need
moving out. Rather than a #ifdef CONFIG_CGROUP_BPF in kernel/bpf/syscall.c,
moving them to kernel/bpf/cgroup.c and kernel/bpf/sockmap.c does not
require #ifdefs since that is already conditionally compiled.
Fixes: f4364dcfc8
("media: rc: introduce BPF_PROG_LIRC_MODE2")
Signed-off-by: Sean Young <sean@mess.org>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
This commit is contained in:

committed by
Daniel Borkmann

parent
68d676a089
commit
fdb5c4531c
@@ -428,6 +428,60 @@ int __cgroup_bpf_query(struct cgroup *cgrp, const union bpf_attr *attr,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cgroup_bpf_prog_attach(const union bpf_attr *attr,
|
||||
enum bpf_prog_type ptype, struct bpf_prog *prog)
|
||||
{
|
||||
struct cgroup *cgrp;
|
||||
int ret;
|
||||
|
||||
cgrp = cgroup_get_from_fd(attr->target_fd);
|
||||
if (IS_ERR(cgrp))
|
||||
return PTR_ERR(cgrp);
|
||||
|
||||
ret = cgroup_bpf_attach(cgrp, prog, attr->attach_type,
|
||||
attr->attach_flags);
|
||||
cgroup_put(cgrp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cgroup_bpf_prog_detach(const union bpf_attr *attr, enum bpf_prog_type ptype)
|
||||
{
|
||||
struct bpf_prog *prog;
|
||||
struct cgroup *cgrp;
|
||||
int ret;
|
||||
|
||||
cgrp = cgroup_get_from_fd(attr->target_fd);
|
||||
if (IS_ERR(cgrp))
|
||||
return PTR_ERR(cgrp);
|
||||
|
||||
prog = bpf_prog_get_type(attr->attach_bpf_fd, ptype);
|
||||
if (IS_ERR(prog))
|
||||
prog = NULL;
|
||||
|
||||
ret = cgroup_bpf_detach(cgrp, prog, attr->attach_type, 0);
|
||||
if (prog)
|
||||
bpf_prog_put(prog);
|
||||
|
||||
cgroup_put(cgrp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cgroup_bpf_prog_query(const union bpf_attr *attr,
|
||||
union bpf_attr __user *uattr)
|
||||
{
|
||||
struct cgroup *cgrp;
|
||||
int ret;
|
||||
|
||||
cgrp = cgroup_get_from_fd(attr->query.target_fd);
|
||||
if (IS_ERR(cgrp))
|
||||
return PTR_ERR(cgrp);
|
||||
|
||||
ret = cgroup_bpf_query(cgrp, attr, uattr);
|
||||
|
||||
cgroup_put(cgrp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* __cgroup_bpf_run_filter_skb() - Run a program for packet filtering
|
||||
* @sk: The socket sending or receiving traffic
|
||||
|
@@ -1915,6 +1915,24 @@ int sock_map_prog(struct bpf_map *map, struct bpf_prog *prog, u32 type)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sockmap_get_from_fd(const union bpf_attr *attr, int type,
|
||||
struct bpf_prog *prog)
|
||||
{
|
||||
int ufd = attr->target_fd;
|
||||
struct bpf_map *map;
|
||||
struct fd f;
|
||||
int err;
|
||||
|
||||
f = fdget(ufd);
|
||||
map = __bpf_map_get(f);
|
||||
if (IS_ERR(map))
|
||||
return PTR_ERR(map);
|
||||
|
||||
err = sock_map_prog(map, prog, attr->attach_type);
|
||||
fdput(f);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void *sock_map_lookup(struct bpf_map *map, void *key)
|
||||
{
|
||||
return NULL;
|
||||
|
@@ -1483,8 +1483,6 @@ out_free_tp:
|
||||
return err;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CGROUP_BPF
|
||||
|
||||
static int bpf_prog_attach_check_attach_type(const struct bpf_prog *prog,
|
||||
enum bpf_attach_type attach_type)
|
||||
{
|
||||
@@ -1499,40 +1497,6 @@ static int bpf_prog_attach_check_attach_type(const struct bpf_prog *prog,
|
||||
|
||||
#define BPF_PROG_ATTACH_LAST_FIELD attach_flags
|
||||
|
||||
static int sockmap_get_from_fd(const union bpf_attr *attr,
|
||||
int type, bool attach)
|
||||
{
|
||||
struct bpf_prog *prog = NULL;
|
||||
int ufd = attr->target_fd;
|
||||
struct bpf_map *map;
|
||||
struct fd f;
|
||||
int err;
|
||||
|
||||
f = fdget(ufd);
|
||||
map = __bpf_map_get(f);
|
||||
if (IS_ERR(map))
|
||||
return PTR_ERR(map);
|
||||
|
||||
if (attach) {
|
||||
prog = bpf_prog_get_type(attr->attach_bpf_fd, type);
|
||||
if (IS_ERR(prog)) {
|
||||
fdput(f);
|
||||
return PTR_ERR(prog);
|
||||
}
|
||||
}
|
||||
|
||||
err = sock_map_prog(map, prog, attr->attach_type);
|
||||
if (err) {
|
||||
fdput(f);
|
||||
if (prog)
|
||||
bpf_prog_put(prog);
|
||||
return err;
|
||||
}
|
||||
|
||||
fdput(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define BPF_F_ATTACH_MASK \
|
||||
(BPF_F_ALLOW_OVERRIDE | BPF_F_ALLOW_MULTI)
|
||||
|
||||
@@ -1540,7 +1504,6 @@ static int bpf_prog_attach(const union bpf_attr *attr)
|
||||
{
|
||||
enum bpf_prog_type ptype;
|
||||
struct bpf_prog *prog;
|
||||
struct cgroup *cgrp;
|
||||
int ret;
|
||||
|
||||
if (!capable(CAP_NET_ADMIN))
|
||||
@@ -1577,12 +1540,15 @@ static int bpf_prog_attach(const union bpf_attr *attr)
|
||||
ptype = BPF_PROG_TYPE_CGROUP_DEVICE;
|
||||
break;
|
||||
case BPF_SK_MSG_VERDICT:
|
||||
return sockmap_get_from_fd(attr, BPF_PROG_TYPE_SK_MSG, true);
|
||||
ptype = BPF_PROG_TYPE_SK_MSG;
|
||||
break;
|
||||
case BPF_SK_SKB_STREAM_PARSER:
|
||||
case BPF_SK_SKB_STREAM_VERDICT:
|
||||
return sockmap_get_from_fd(attr, BPF_PROG_TYPE_SK_SKB, true);
|
||||
ptype = BPF_PROG_TYPE_SK_SKB;
|
||||
break;
|
||||
case BPF_LIRC_MODE2:
|
||||
return lirc_prog_attach(attr);
|
||||
ptype = BPF_PROG_TYPE_LIRC_MODE2;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -1596,18 +1562,20 @@ static int bpf_prog_attach(const union bpf_attr *attr)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cgrp = cgroup_get_from_fd(attr->target_fd);
|
||||
if (IS_ERR(cgrp)) {
|
||||
bpf_prog_put(prog);
|
||||
return PTR_ERR(cgrp);
|
||||
switch (ptype) {
|
||||
case BPF_PROG_TYPE_SK_SKB:
|
||||
case BPF_PROG_TYPE_SK_MSG:
|
||||
ret = sockmap_get_from_fd(attr, ptype, prog);
|
||||
break;
|
||||
case BPF_PROG_TYPE_LIRC_MODE2:
|
||||
ret = lirc_prog_attach(attr, prog);
|
||||
break;
|
||||
default:
|
||||
ret = cgroup_bpf_prog_attach(attr, ptype, prog);
|
||||
}
|
||||
|
||||
ret = cgroup_bpf_attach(cgrp, prog, attr->attach_type,
|
||||
attr->attach_flags);
|
||||
if (ret)
|
||||
bpf_prog_put(prog);
|
||||
cgroup_put(cgrp);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1616,9 +1584,6 @@ static int bpf_prog_attach(const union bpf_attr *attr)
|
||||
static int bpf_prog_detach(const union bpf_attr *attr)
|
||||
{
|
||||
enum bpf_prog_type ptype;
|
||||
struct bpf_prog *prog;
|
||||
struct cgroup *cgrp;
|
||||
int ret;
|
||||
|
||||
if (!capable(CAP_NET_ADMIN))
|
||||
return -EPERM;
|
||||
@@ -1651,29 +1616,17 @@ static int bpf_prog_detach(const union bpf_attr *attr)
|
||||
ptype = BPF_PROG_TYPE_CGROUP_DEVICE;
|
||||
break;
|
||||
case BPF_SK_MSG_VERDICT:
|
||||
return sockmap_get_from_fd(attr, BPF_PROG_TYPE_SK_MSG, false);
|
||||
return sockmap_get_from_fd(attr, BPF_PROG_TYPE_SK_MSG, NULL);
|
||||
case BPF_SK_SKB_STREAM_PARSER:
|
||||
case BPF_SK_SKB_STREAM_VERDICT:
|
||||
return sockmap_get_from_fd(attr, BPF_PROG_TYPE_SK_SKB, false);
|
||||
return sockmap_get_from_fd(attr, BPF_PROG_TYPE_SK_SKB, NULL);
|
||||
case BPF_LIRC_MODE2:
|
||||
return lirc_prog_detach(attr);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cgrp = cgroup_get_from_fd(attr->target_fd);
|
||||
if (IS_ERR(cgrp))
|
||||
return PTR_ERR(cgrp);
|
||||
|
||||
prog = bpf_prog_get_type(attr->attach_bpf_fd, ptype);
|
||||
if (IS_ERR(prog))
|
||||
prog = NULL;
|
||||
|
||||
ret = cgroup_bpf_detach(cgrp, prog, attr->attach_type, 0);
|
||||
if (prog)
|
||||
bpf_prog_put(prog);
|
||||
cgroup_put(cgrp);
|
||||
return ret;
|
||||
return cgroup_bpf_prog_detach(attr, ptype);
|
||||
}
|
||||
|
||||
#define BPF_PROG_QUERY_LAST_FIELD query.prog_cnt
|
||||
@@ -1681,9 +1634,6 @@ static int bpf_prog_detach(const union bpf_attr *attr)
|
||||
static int bpf_prog_query(const union bpf_attr *attr,
|
||||
union bpf_attr __user *uattr)
|
||||
{
|
||||
struct cgroup *cgrp;
|
||||
int ret;
|
||||
|
||||
if (!capable(CAP_NET_ADMIN))
|
||||
return -EPERM;
|
||||
if (CHECK_ATTR(BPF_PROG_QUERY))
|
||||
@@ -1711,14 +1661,9 @@ static int bpf_prog_query(const union bpf_attr *attr,
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
cgrp = cgroup_get_from_fd(attr->query.target_fd);
|
||||
if (IS_ERR(cgrp))
|
||||
return PTR_ERR(cgrp);
|
||||
ret = cgroup_bpf_query(cgrp, attr, uattr);
|
||||
cgroup_put(cgrp);
|
||||
return ret;
|
||||
|
||||
return cgroup_bpf_prog_query(attr, uattr);
|
||||
}
|
||||
#endif /* CONFIG_CGROUP_BPF */
|
||||
|
||||
#define BPF_PROG_TEST_RUN_LAST_FIELD test.duration
|
||||
|
||||
@@ -2365,7 +2310,6 @@ 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;
|
||||
@@ -2375,7 +2319,6 @@ SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, siz
|
||||
case BPF_PROG_QUERY:
|
||||
err = bpf_prog_query(&attr, uattr);
|
||||
break;
|
||||
#endif
|
||||
case BPF_PROG_TEST_RUN:
|
||||
err = bpf_prog_test_run(&attr, uattr);
|
||||
break;
|
||||
|
Reference in New Issue
Block a user