aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSean Young <sean@mess.org>2018-06-18 19:04:24 -0400
committerDaniel Borkmann <daniel@iogearbox.net>2018-06-26 05:28:38 -0400
commitfdb5c4531c1e0e50e609df83f736b6f3a02896e2 (patch)
treec2ca0792e966f0bfb00f08d4df3401f2d68d52a9
parent68d676a089625daed9d61df56ac63b5cd7189efe (diff)
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: f4364dcfc86d ("media: rc: introduce BPF_PROG_LIRC_MODE2") Signed-off-by: Sean Young <sean@mess.org> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
-rw-r--r--drivers/media/rc/bpf-lirc.c14
-rw-r--r--include/linux/bpf-cgroup.h26
-rw-r--r--include/linux/bpf.h8
-rw-r--r--include/linux/bpf_lirc.h5
-rw-r--r--kernel/bpf/cgroup.c54
-rw-r--r--kernel/bpf/sockmap.c18
-rw-r--r--kernel/bpf/syscall.c99
7 files changed, 132 insertions, 92 deletions
diff --git a/drivers/media/rc/bpf-lirc.c b/drivers/media/rc/bpf-lirc.c
index 40826bba06b6..fcfab6635f9c 100644
--- a/drivers/media/rc/bpf-lirc.c
+++ b/drivers/media/rc/bpf-lirc.c
@@ -207,29 +207,19 @@ void lirc_bpf_free(struct rc_dev *rcdev)
207 bpf_prog_array_free(rcdev->raw->progs); 207 bpf_prog_array_free(rcdev->raw->progs);
208} 208}
209 209
210int lirc_prog_attach(const union bpf_attr *attr) 210int lirc_prog_attach(const union bpf_attr *attr, struct bpf_prog *prog)
211{ 211{
212 struct bpf_prog *prog;
213 struct rc_dev *rcdev; 212 struct rc_dev *rcdev;
214 int ret; 213 int ret;
215 214
216 if (attr->attach_flags) 215 if (attr->attach_flags)
217 return -EINVAL; 216 return -EINVAL;
218 217
219 prog = bpf_prog_get_type(attr->attach_bpf_fd,
220 BPF_PROG_TYPE_LIRC_MODE2);
221 if (IS_ERR(prog))
222 return PTR_ERR(prog);
223
224 rcdev = rc_dev_get_from_fd(attr->target_fd); 218 rcdev = rc_dev_get_from_fd(attr->target_fd);
225 if (IS_ERR(rcdev)) { 219 if (IS_ERR(rcdev))
226 bpf_prog_put(prog);
227 return PTR_ERR(rcdev); 220 return PTR_ERR(rcdev);
228 }
229 221
230 ret = lirc_bpf_attach(rcdev, prog); 222 ret = lirc_bpf_attach(rcdev, prog);
231 if (ret)
232 bpf_prog_put(prog);
233 223
234 put_device(&rcdev->dev); 224 put_device(&rcdev->dev);
235 225
diff --git a/include/linux/bpf-cgroup.h b/include/linux/bpf-cgroup.h
index 975fb4cf1bb7..79795c5fa7c3 100644
--- a/include/linux/bpf-cgroup.h
+++ b/include/linux/bpf-cgroup.h
@@ -188,12 +188,38 @@ int __cgroup_bpf_check_dev_permission(short dev_type, u32 major, u32 minor,
188 \ 188 \
189 __ret; \ 189 __ret; \
190}) 190})
191int cgroup_bpf_prog_attach(const union bpf_attr *attr,
192 enum bpf_prog_type ptype, struct bpf_prog *prog);
193int cgroup_bpf_prog_detach(const union bpf_attr *attr,
194 enum bpf_prog_type ptype);
195int cgroup_bpf_prog_query(const union bpf_attr *attr,
196 union bpf_attr __user *uattr);
191#else 197#else
192 198
199struct bpf_prog;
193struct cgroup_bpf {}; 200struct cgroup_bpf {};
194static inline void cgroup_bpf_put(struct cgroup *cgrp) {} 201static inline void cgroup_bpf_put(struct cgroup *cgrp) {}
195static inline int cgroup_bpf_inherit(struct cgroup *cgrp) { return 0; } 202static inline int cgroup_bpf_inherit(struct cgroup *cgrp) { return 0; }
196 203
204static inline int cgroup_bpf_prog_attach(const union bpf_attr *attr,
205 enum bpf_prog_type ptype,
206 struct bpf_prog *prog)
207{
208 return -EINVAL;
209}
210
211static inline int cgroup_bpf_prog_detach(const union bpf_attr *attr,
212 enum bpf_prog_type ptype)
213{
214 return -EINVAL;
215}
216
217static inline int cgroup_bpf_prog_query(const union bpf_attr *attr,
218 union bpf_attr __user *uattr)
219{
220 return -EINVAL;
221}
222
197#define cgroup_bpf_enabled (0) 223#define cgroup_bpf_enabled (0)
198#define BPF_CGROUP_PRE_CONNECT_ENABLED(sk) (0) 224#define BPF_CGROUP_PRE_CONNECT_ENABLED(sk) (0)
199#define BPF_CGROUP_RUN_PROG_INET_INGRESS(sk,skb) ({ 0; }) 225#define BPF_CGROUP_RUN_PROG_INET_INGRESS(sk,skb) ({ 0; })
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 7df32a3200f7..8827e797ff97 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -696,6 +696,8 @@ static inline void bpf_map_offload_map_free(struct bpf_map *map)
696struct sock *__sock_map_lookup_elem(struct bpf_map *map, u32 key); 696struct sock *__sock_map_lookup_elem(struct bpf_map *map, u32 key);
697struct sock *__sock_hash_lookup_elem(struct bpf_map *map, void *key); 697struct sock *__sock_hash_lookup_elem(struct bpf_map *map, void *key);
698int sock_map_prog(struct bpf_map *map, struct bpf_prog *prog, u32 type); 698int sock_map_prog(struct bpf_map *map, struct bpf_prog *prog, u32 type);
699int sockmap_get_from_fd(const union bpf_attr *attr, int type,
700 struct bpf_prog *prog);
699#else 701#else
700static inline struct sock *__sock_map_lookup_elem(struct bpf_map *map, u32 key) 702static inline struct sock *__sock_map_lookup_elem(struct bpf_map *map, u32 key)
701{ 703{
@@ -714,6 +716,12 @@ static inline int sock_map_prog(struct bpf_map *map,
714{ 716{
715 return -EOPNOTSUPP; 717 return -EOPNOTSUPP;
716} 718}
719
720static inline int sockmap_get_from_fd(const union bpf_attr *attr, int type,
721 struct bpf_prog *prog)
722{
723 return -EINVAL;
724}
717#endif 725#endif
718 726
719#if defined(CONFIG_XDP_SOCKETS) 727#if defined(CONFIG_XDP_SOCKETS)
diff --git a/include/linux/bpf_lirc.h b/include/linux/bpf_lirc.h
index 5f8a4283092d..9d9ff755ec29 100644
--- a/include/linux/bpf_lirc.h
+++ b/include/linux/bpf_lirc.h
@@ -5,11 +5,12 @@
5#include <uapi/linux/bpf.h> 5#include <uapi/linux/bpf.h>
6 6
7#ifdef CONFIG_BPF_LIRC_MODE2 7#ifdef CONFIG_BPF_LIRC_MODE2
8int lirc_prog_attach(const union bpf_attr *attr); 8int lirc_prog_attach(const union bpf_attr *attr, struct bpf_prog *prog);
9int lirc_prog_detach(const union bpf_attr *attr); 9int lirc_prog_detach(const union bpf_attr *attr);
10int lirc_prog_query(const union bpf_attr *attr, union bpf_attr __user *uattr); 10int lirc_prog_query(const union bpf_attr *attr, union bpf_attr __user *uattr);
11#else 11#else
12static inline int lirc_prog_attach(const union bpf_attr *attr) 12static inline int lirc_prog_attach(const union bpf_attr *attr,
13 struct bpf_prog *prog)
13{ 14{
14 return -EINVAL; 15 return -EINVAL;
15} 16}
diff --git a/kernel/bpf/cgroup.c b/kernel/bpf/cgroup.c
index f7c00bd6f8e4..3d83ee7df381 100644
--- a/kernel/bpf/cgroup.c
+++ b/kernel/bpf/cgroup.c
@@ -428,6 +428,60 @@ int __cgroup_bpf_query(struct cgroup *cgrp, const union bpf_attr *attr,
428 return ret; 428 return ret;
429} 429}
430 430
431int cgroup_bpf_prog_attach(const union bpf_attr *attr,
432 enum bpf_prog_type ptype, struct bpf_prog *prog)
433{
434 struct cgroup *cgrp;
435 int ret;
436
437 cgrp = cgroup_get_from_fd(attr->target_fd);
438 if (IS_ERR(cgrp))
439 return PTR_ERR(cgrp);
440
441 ret = cgroup_bpf_attach(cgrp, prog, attr->attach_type,
442 attr->attach_flags);
443 cgroup_put(cgrp);
444 return ret;
445}
446
447int cgroup_bpf_prog_detach(const union bpf_attr *attr, enum bpf_prog_type ptype)
448{
449 struct bpf_prog *prog;
450 struct cgroup *cgrp;
451 int ret;
452
453 cgrp = cgroup_get_from_fd(attr->target_fd);
454 if (IS_ERR(cgrp))
455 return PTR_ERR(cgrp);
456
457 prog = bpf_prog_get_type(attr->attach_bpf_fd, ptype);
458 if (IS_ERR(prog))
459 prog = NULL;
460
461 ret = cgroup_bpf_detach(cgrp, prog, attr->attach_type, 0);
462 if (prog)
463 bpf_prog_put(prog);
464
465 cgroup_put(cgrp);
466 return ret;
467}
468
469int cgroup_bpf_prog_query(const union bpf_attr *attr,
470 union bpf_attr __user *uattr)
471{
472 struct cgroup *cgrp;
473 int ret;
474
475 cgrp = cgroup_get_from_fd(attr->query.target_fd);
476 if (IS_ERR(cgrp))
477 return PTR_ERR(cgrp);
478
479 ret = cgroup_bpf_query(cgrp, attr, uattr);
480
481 cgroup_put(cgrp);
482 return ret;
483}
484
431/** 485/**
432 * __cgroup_bpf_run_filter_skb() - Run a program for packet filtering 486 * __cgroup_bpf_run_filter_skb() - Run a program for packet filtering
433 * @sk: The socket sending or receiving traffic 487 * @sk: The socket sending or receiving traffic
diff --git a/kernel/bpf/sockmap.c b/kernel/bpf/sockmap.c
index 52a91d816c0e..81d0c55a77aa 100644
--- a/kernel/bpf/sockmap.c
+++ b/kernel/bpf/sockmap.c
@@ -1915,6 +1915,24 @@ int sock_map_prog(struct bpf_map *map, struct bpf_prog *prog, u32 type)
1915 return 0; 1915 return 0;
1916} 1916}
1917 1917
1918int sockmap_get_from_fd(const union bpf_attr *attr, int type,
1919 struct bpf_prog *prog)
1920{
1921 int ufd = attr->target_fd;
1922 struct bpf_map *map;
1923 struct fd f;
1924 int err;
1925
1926 f = fdget(ufd);
1927 map = __bpf_map_get(f);
1928 if (IS_ERR(map))
1929 return PTR_ERR(map);
1930
1931 err = sock_map_prog(map, prog, attr->attach_type);
1932 fdput(f);
1933 return err;
1934}
1935
1918static void *sock_map_lookup(struct bpf_map *map, void *key) 1936static void *sock_map_lookup(struct bpf_map *map, void *key)
1919{ 1937{
1920 return NULL; 1938 return NULL;
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 35dc466641f2..d10ecd78105f 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -1483,8 +1483,6 @@ out_free_tp:
1483 return err; 1483 return err;
1484} 1484}
1485 1485
1486#ifdef CONFIG_CGROUP_BPF
1487
1488static int bpf_prog_attach_check_attach_type(const struct bpf_prog *prog, 1486static int bpf_prog_attach_check_attach_type(const struct bpf_prog *prog,
1489 enum bpf_attach_type attach_type) 1487 enum bpf_attach_type attach_type)
1490{ 1488{
@@ -1499,40 +1497,6 @@ static int bpf_prog_attach_check_attach_type(const struct bpf_prog *prog,
1499 1497
1500#define BPF_PROG_ATTACH_LAST_FIELD attach_flags 1498#define BPF_PROG_ATTACH_LAST_FIELD attach_flags
1501 1499
1502static int sockmap_get_from_fd(const union bpf_attr *attr,
1503 int type, bool attach)
1504{
1505 struct bpf_prog *prog = NULL;
1506 int ufd = attr->target_fd;
1507 struct bpf_map *map;
1508 struct fd f;
1509 int err;
1510
1511 f = fdget(ufd);
1512 map = __bpf_map_get(f);
1513 if (IS_ERR(map))
1514 return PTR_ERR(map);
1515
1516 if (attach) {
1517 prog = bpf_prog_get_type(attr->attach_bpf_fd, type);
1518 if (IS_ERR(prog)) {
1519 fdput(f);
1520 return PTR_ERR(prog);
1521 }
1522 }
1523
1524 err = sock_map_prog(map, prog, attr->attach_type);
1525 if (err) {
1526 fdput(f);
1527 if (prog)
1528 bpf_prog_put(prog);
1529 return err;
1530 }
1531
1532 fdput(f);
1533 return 0;
1534}
1535
1536#define BPF_F_ATTACH_MASK \ 1500#define BPF_F_ATTACH_MASK \
1537 (BPF_F_ALLOW_OVERRIDE | BPF_F_ALLOW_MULTI) 1501 (BPF_F_ALLOW_OVERRIDE | BPF_F_ALLOW_MULTI)
1538 1502
@@ -1540,7 +1504,6 @@ static int bpf_prog_attach(const union bpf_attr *attr)
1540{ 1504{
1541 enum bpf_prog_type ptype; 1505 enum bpf_prog_type ptype;
1542 struct bpf_prog *prog; 1506 struct bpf_prog *prog;
1543 struct cgroup *cgrp;
1544 int ret; 1507 int ret;
1545 1508
1546 if (!capable(CAP_NET_ADMIN)) 1509 if (!capable(CAP_NET_ADMIN))
@@ -1577,12 +1540,15 @@ static int bpf_prog_attach(const union bpf_attr *attr)
1577 ptype = BPF_PROG_TYPE_CGROUP_DEVICE; 1540 ptype = BPF_PROG_TYPE_CGROUP_DEVICE;
1578 break; 1541 break;
1579 case BPF_SK_MSG_VERDICT: 1542 case BPF_SK_MSG_VERDICT:
1580 return sockmap_get_from_fd(attr, BPF_PROG_TYPE_SK_MSG, true); 1543 ptype = BPF_PROG_TYPE_SK_MSG;
1544 break;
1581 case BPF_SK_SKB_STREAM_PARSER: 1545 case BPF_SK_SKB_STREAM_PARSER:
1582 case BPF_SK_SKB_STREAM_VERDICT: 1546 case BPF_SK_SKB_STREAM_VERDICT:
1583 return sockmap_get_from_fd(attr, BPF_PROG_TYPE_SK_SKB, true); 1547 ptype = BPF_PROG_TYPE_SK_SKB;
1548 break;
1584 case BPF_LIRC_MODE2: 1549 case BPF_LIRC_MODE2:
1585 return lirc_prog_attach(attr); 1550 ptype = BPF_PROG_TYPE_LIRC_MODE2;
1551 break;
1586 default: 1552 default:
1587 return -EINVAL; 1553 return -EINVAL;
1588 } 1554 }
@@ -1596,18 +1562,20 @@ static int bpf_prog_attach(const union bpf_attr *attr)
1596 return -EINVAL; 1562 return -EINVAL;
1597 } 1563 }
1598 1564
1599 cgrp = cgroup_get_from_fd(attr->target_fd); 1565 switch (ptype) {
1600 if (IS_ERR(cgrp)) { 1566 case BPF_PROG_TYPE_SK_SKB:
1601 bpf_prog_put(prog); 1567 case BPF_PROG_TYPE_SK_MSG:
1602 return PTR_ERR(cgrp); 1568 ret = sockmap_get_from_fd(attr, ptype, prog);
1569 break;
1570 case BPF_PROG_TYPE_LIRC_MODE2:
1571 ret = lirc_prog_attach(attr, prog);
1572 break;
1573 default:
1574 ret = cgroup_bpf_prog_attach(attr, ptype, prog);
1603 } 1575 }
1604 1576
1605 ret = cgroup_bpf_attach(cgrp, prog, attr->attach_type,
1606 attr->attach_flags);
1607 if (ret) 1577 if (ret)
1608 bpf_prog_put(prog); 1578 bpf_prog_put(prog);
1609 cgroup_put(cgrp);
1610
1611 return ret; 1579 return ret;
1612} 1580}
1613 1581
@@ -1616,9 +1584,6 @@ static int bpf_prog_attach(const union bpf_attr *attr)
1616static int bpf_prog_detach(const union bpf_attr *attr) 1584static int bpf_prog_detach(const union bpf_attr *attr)
1617{ 1585{
1618 enum bpf_prog_type ptype; 1586 enum bpf_prog_type ptype;
1619 struct bpf_prog *prog;
1620 struct cgroup *cgrp;
1621 int ret;
1622 1587
1623 if (!capable(CAP_NET_ADMIN)) 1588 if (!capable(CAP_NET_ADMIN))
1624 return -EPERM; 1589 return -EPERM;
@@ -1651,29 +1616,17 @@ static int bpf_prog_detach(const union bpf_attr *attr)
1651 ptype = BPF_PROG_TYPE_CGROUP_DEVICE; 1616 ptype = BPF_PROG_TYPE_CGROUP_DEVICE;
1652 break; 1617 break;
1653 case BPF_SK_MSG_VERDICT: 1618 case BPF_SK_MSG_VERDICT:
1654 return sockmap_get_from_fd(attr, BPF_PROG_TYPE_SK_MSG, false); 1619 return sockmap_get_from_fd(attr, BPF_PROG_TYPE_SK_MSG, NULL);
1655 case BPF_SK_SKB_STREAM_PARSER: 1620 case BPF_SK_SKB_STREAM_PARSER:
1656 case BPF_SK_SKB_STREAM_VERDICT: 1621 case BPF_SK_SKB_STREAM_VERDICT:
1657 return sockmap_get_from_fd(attr, BPF_PROG_TYPE_SK_SKB, false); 1622 return sockmap_get_from_fd(attr, BPF_PROG_TYPE_SK_SKB, NULL);
1658 case BPF_LIRC_MODE2: 1623 case BPF_LIRC_MODE2:
1659 return lirc_prog_detach(attr); 1624 return lirc_prog_detach(attr);
1660 default: 1625 default:
1661 return -EINVAL; 1626 return -EINVAL;
1662 } 1627 }
1663 1628
1664 cgrp = cgroup_get_from_fd(attr->target_fd); 1629 return cgroup_bpf_prog_detach(attr, ptype);
1665 if (IS_ERR(cgrp))
1666 return PTR_ERR(cgrp);
1667
1668 prog = bpf_prog_get_type(attr->attach_bpf_fd, ptype);
1669 if (IS_ERR(prog))
1670 prog = NULL;
1671
1672 ret = cgroup_bpf_detach(cgrp, prog, attr->attach_type, 0);
1673 if (prog)
1674 bpf_prog_put(prog);
1675 cgroup_put(cgrp);
1676 return ret;
1677} 1630}
1678 1631
1679#define BPF_PROG_QUERY_LAST_FIELD query.prog_cnt 1632#define BPF_PROG_QUERY_LAST_FIELD query.prog_cnt
@@ -1681,9 +1634,6 @@ static int bpf_prog_detach(const union bpf_attr *attr)
1681static int bpf_prog_query(const union bpf_attr *attr, 1634static int bpf_prog_query(const union bpf_attr *attr,
1682 union bpf_attr __user *uattr) 1635 union bpf_attr __user *uattr)
1683{ 1636{
1684 struct cgroup *cgrp;
1685 int ret;
1686
1687 if (!capable(CAP_NET_ADMIN)) 1637 if (!capable(CAP_NET_ADMIN))
1688 return -EPERM; 1638 return -EPERM;
1689 if (CHECK_ATTR(BPF_PROG_QUERY)) 1639 if (CHECK_ATTR(BPF_PROG_QUERY))
@@ -1711,14 +1661,9 @@ static int bpf_prog_query(const union bpf_attr *attr,
1711 default: 1661 default:
1712 return -EINVAL; 1662 return -EINVAL;
1713 } 1663 }
1714 cgrp = cgroup_get_from_fd(attr->query.target_fd); 1664
1715 if (IS_ERR(cgrp)) 1665 return cgroup_bpf_prog_query(attr, uattr);
1716 return PTR_ERR(cgrp);
1717 ret = cgroup_bpf_query(cgrp, attr, uattr);
1718 cgroup_put(cgrp);
1719 return ret;
1720} 1666}
1721#endif /* CONFIG_CGROUP_BPF */
1722 1667
1723#define BPF_PROG_TEST_RUN_LAST_FIELD test.duration 1668#define BPF_PROG_TEST_RUN_LAST_FIELD test.duration
1724 1669
@@ -2365,7 +2310,6 @@ SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, siz
2365 case BPF_OBJ_GET: 2310 case BPF_OBJ_GET:
2366 err = bpf_obj_get(&attr); 2311 err = bpf_obj_get(&attr);
2367 break; 2312 break;
2368#ifdef CONFIG_CGROUP_BPF
2369 case BPF_PROG_ATTACH: 2313 case BPF_PROG_ATTACH:
2370 err = bpf_prog_attach(&attr); 2314 err = bpf_prog_attach(&attr);
2371 break; 2315 break;
@@ -2375,7 +2319,6 @@ SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, siz
2375 case BPF_PROG_QUERY: 2319 case BPF_PROG_QUERY:
2376 err = bpf_prog_query(&attr, uattr); 2320 err = bpf_prog_query(&attr, uattr);
2377 break; 2321 break;
2378#endif
2379 case BPF_PROG_TEST_RUN: 2322 case BPF_PROG_TEST_RUN:
2380 err = bpf_prog_test_run(&attr, uattr); 2323 err = bpf_prog_test_run(&attr, uattr);
2381 break; 2324 break;