]> granicus.if.org Git - strace/commitdiff
Update bpf syscall decoding
authorQuentin Monnet <quentin.monnet@6wind.com>
Thu, 26 Jan 2017 14:36:56 +0000 (15:36 +0100)
committerDmitry V. Levin <ldv@altlinux.org>
Sun, 29 Jan 2017 21:54:43 +0000 (21:54 +0000)
Implement decoding of BPF_OBJ_PIN, BPF_OBJ_GET, BPF_PROG_ATTACH,
and BPF_PROG_DETACH commands.

* bpf.c: Include "xlat/bpf_attach_type.h".
(bpf_obj_manage, bpf_prog_attach, bpf_prog_detach): New functions.
(SYS_FUNC(bpf)): Use them.
* configure.ac: Check for union bpf_attr.bpf_fd and union
bpf_attr.attach_type.
* xlat/bpf_attach_type.in: New file.
* xlat/bpf_commands.in: Update list of BPF_* command constants.
* xlat/bpf_map_types.in: Update list of BPF_MAP_TYPE_* constants.
* xlat/bpf_prog_types.in: Update list of BPF_PROG_TYPE_* constants.
* tests/bpf.c [HAVE_UNION_BPF_ATTR_BPF_FD] (obj_manage): New function.
[HAVE_UNION_BPF_ATTR_ATTACH_TYPE] (prog_cgroup): Likewise.
(main): Use them.

bpf.c
configure.ac
tests/bpf.c
xlat/bpf_attach_type.in [new file with mode: 0644]
xlat/bpf_commands.in
xlat/bpf_map_types.in
xlat/bpf_prog_types.in

diff --git a/bpf.c b/bpf.c
index 04c677a173adfc348830b2f3311fdcb7ad43b5e8..d36745ed89601045f2dcdad65cfe864a64cfd1a1 100644 (file)
--- a/bpf.c
+++ b/bpf.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2015 Dmitry V. Levin <ldv@altlinux.org>
+ * Copyright (c) 2017 Quentin Monnet <quentin.monnet@6wind.com>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -35,6 +36,7 @@
 #include "xlat/bpf_map_types.h"
 #include "xlat/bpf_prog_types.h"
 #include "xlat/bpf_map_update_elem_flags.h"
+#include "xlat/bpf_attach_type.h"
 
 static int
 bpf_map_create(struct tcb *const tcp, const kernel_ulong_t addr,
@@ -177,6 +179,87 @@ bpf_prog_load(struct tcb *const tcp, const kernel_ulong_t addr,
        return RVAL_DECODED | RVAL_FD;
 }
 
+static int
+bpf_obj_manage(struct tcb *const tcp, const kernel_ulong_t addr,
+               unsigned int size)
+{
+       struct {
+               uint64_t ATTRIBUTE_ALIGNED(8) pathname;
+               uint32_t bpf_fd;
+       } attr = {};
+
+       if (!size) {
+               printaddr(addr);
+               return RVAL_DECODED | RVAL_FD;
+       }
+       if (size > sizeof(attr))
+               size = sizeof(attr);
+       if (umoven_or_printaddr(tcp, addr, size, &attr))
+               return RVAL_DECODED | RVAL_FD;
+
+       tprintf("{pathname=");
+       printpath(tcp, attr.pathname);
+       tprints(", bpf_fd=");
+       printfd(tcp, attr.bpf_fd);
+       tprintf("}");
+
+       return RVAL_DECODED | RVAL_FD;
+}
+
+static int
+bpf_prog_attach(struct tcb *const tcp, const kernel_ulong_t addr,
+               unsigned int size)
+{
+       struct {
+               uint32_t target_fd, attach_bpf_fd, attach_type;
+       } attr = {};
+
+       if (!size) {
+               printaddr(addr);
+               return RVAL_DECODED;
+       }
+       if (size > sizeof(attr))
+               size = sizeof(attr);
+       if (umoven_or_printaddr(tcp, addr, size, &attr))
+               return RVAL_DECODED;
+
+       tprintf("{target_fd=");
+       printfd(tcp, attr.target_fd);
+       tprintf(", attach_bpf_fd=");
+       printfd(tcp, attr.attach_bpf_fd);
+       tprintf(", attach_type=");
+       printxval(bpf_attach_type, attr.attach_type, "BPF_???");
+       tprintf("}");
+
+       return RVAL_DECODED;
+}
+
+static int
+bpf_prog_detach(struct tcb *const tcp, const kernel_ulong_t addr,
+               unsigned int size)
+{
+       struct {
+               uint32_t target_fd, attach_bpf_fd, attach_type;
+       } attr = {};
+
+       if (!size) {
+               printaddr(addr);
+               return RVAL_DECODED;
+       }
+       if (size > sizeof(attr))
+               size = sizeof(attr);
+       if (umoven_or_printaddr(tcp, addr, size, &attr))
+               return RVAL_DECODED;
+
+       tprintf("{target_fd=");
+       printfd(tcp, attr.target_fd);
+       tprintf(", attach_type=");
+       printxval(bpf_attach_type, attr.attach_type, "BPF_???");
+       tprintf("}");
+
+       return RVAL_DECODED;
+}
+
 SYS_FUNC(bpf)
 {
        const unsigned int cmd = tcp->u_arg[0];
@@ -208,6 +291,18 @@ SYS_FUNC(bpf)
        case BPF_PROG_LOAD:
                rc = bpf_prog_load(tcp, addr, size);
                break;
+       case BPF_OBJ_PIN:
+               rc = bpf_obj_manage(tcp, addr, size);
+               break;
+       case BPF_OBJ_GET:
+               rc = bpf_obj_manage(tcp, addr, size);
+               break;
+       case BPF_PROG_ATTACH:
+               rc = bpf_prog_attach(tcp, addr, size);
+               break;
+       case BPF_PROG_DETACH:
+               rc = bpf_prog_detach(tcp, addr, size);
+               break;
        default:
                printaddr(addr);
                break;
index 27d457c690f429b4818e0a4038b56a44d48f22e9..018a8df390f9d3b2a692332cf41900be0552dbba 100644 (file)
@@ -424,6 +424,28 @@ AC_CHECK_HEADERS([linux/bpf.h], [
                AC_DEFINE(HAVE_UNION_BPF_ATTR_LOG_BUF, [1],
                          [Define to 1 if union bpf_attr.log_buf initialization works])
        fi
+       AC_CACHE_CHECK([whether union bpf_attr.bpf_fd initialization works],
+                      [st_cv_have_union_bpf_attr_bpf_fd],
+               [AC_COMPILE_IFELSE(
+                       [AC_LANG_PROGRAM([[#include <linux/bpf.h>]],
+                                        [[union bpf_attr a = { .bpf_fd = 0 };]])],
+                       [st_cv_have_union_bpf_attr_bpf_fd=yes],
+                       [st_cv_have_union_bpf_attr_bpf_fd=no])])
+       if test $st_cv_have_union_bpf_attr_bpf_fd = yes; then
+               AC_DEFINE(HAVE_UNION_BPF_ATTR_BPF_FD, [1],
+                         [Define to 1 if union bpf_attr.bpf_fd initialization works])
+       fi
+       AC_CACHE_CHECK([whether union bpf_attr.attach_type initialization works],
+                      [st_cv_have_union_bpf_attr_attach_type],
+               [AC_COMPILE_IFELSE(
+                       [AC_LANG_PROGRAM([[#include <linux/bpf.h>]],
+                                        [[union bpf_attr a = { .attach_type = 0 };]])],
+                       [st_cv_have_union_bpf_attr_attach_type=yes],
+                       [st_cv_have_union_bpf_attr_attach_type=no])])
+       if test $st_cv_have_union_bpf_attr_attach_type = yes; then
+               AC_DEFINE(HAVE_UNION_BPF_ATTR_ATTACH_TYPE, [1],
+                         [Define to 1 if union bpf_attr.attach_type initialization works])
+       fi
 ])
 
 AC_CHECK_TYPES([struct statfs], [
index 5a1fcdc7d72d9386279f5616d24c35be3ca8de02..c1fa1e8289b8e17fcc8ef9dece6ebf92c17748cc 100644 (file)
@@ -76,6 +76,39 @@ prog_load(void)
        return syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr));
 }
 
+/*
+ * bpf() syscall and its first six commands were introduced in Linux kernel
+ * 3.18. Some additional commands were added afterwards, so we need to take
+ * precautions to make sure the tests compile.
+ *
+ * BPF_OBJ_PIN and BPF_OBJ_GET commands appear in kernel 4.4.
+ */
+# ifdef HAVE_UNION_BPF_ATTR_BPF_FD
+static int
+obj_manage(int cmd)
+{
+       union bpf_attr attr = {
+               .pathname = (unsigned long) "/sys/fs/bpf/foo/bar",
+               .bpf_fd = -1
+       };
+       return syscall(__NR_bpf, cmd, &attr, sizeof(attr));
+}
+# endif
+
+/* BPF_PROG_ATTACH and BPF_PROG_DETACH commands appear in kernel 4.10. */
+# ifdef HAVE_UNION_BPF_ATTR_ATTACH_TYPE
+static int
+prog_cgroup(int cmd)
+{
+       union bpf_attr attr = {
+               .target_fd = -1,
+               .attach_bpf_fd = -1,
+               .attach_type = 0
+       };
+       return syscall(__NR_bpf, cmd, &attr, sizeof(attr));
+}
+# endif
+
 int
 main(void)
 {
@@ -119,6 +152,38 @@ main(void)
               "kern_version=0\\}, %u\\) += -1 .*\n",
                insns, log_buf, (unsigned) sizeof(union bpf_attr));
 
+# ifdef HAVE_UNION_BPF_ATTR_BPF_FD
+       if (!obj_manage(BPF_OBJ_PIN))
+               perror_msg_and_skip("BPF_OBJ_PIN");
+       printf("bpf\\(BPF_OBJ_PIN, "
+              "\\{pathname=\"/sys/fs/bpf/foo/bar\", "
+              "bpf_fd=-1\\}, %u\\) += -1 .*\n",
+               (unsigned) sizeof(union bpf_attr));
+
+       if (!obj_manage(BPF_OBJ_GET))
+               perror_msg_and_skip("BPF_OBJ_GET");
+       printf("bpf\\(BPF_OBJ_GET, "
+              "\\{pathname=\"/sys/fs/bpf/foo/bar\", "
+              "bpf_fd=-1\\}, %u\\) += -1 .*\n",
+               (unsigned) sizeof(union bpf_attr));
+# endif
+
+# ifdef HAVE_UNION_BPF_ATTR_ATTACH_TYPE
+       if (!prog_cgroup(BPF_PROG_ATTACH))
+               perror_msg_and_skip("BPF_PROG_ATTACH");
+       printf("bpf\\(BPF_PROG_ATTACH, "
+              "{target_fd=-1, attach_bpf_fd=-1, "
+              "attach_type=BPF_CGROUP_INET_INGRESS\\}, %u\\) += -1 .*\n",
+               (unsigned) sizeof(union bpf_attr));
+
+       if (!prog_cgroup(BPF_PROG_DETACH))
+               perror_msg_and_skip("BPF_PROG_DETACH");
+       printf("bpf\\(BPF_PROG_DETACH, "
+              "\\{target_fd=-1, attach_type=BPF_CGROUP_INET_INGRESS\\}, "
+              "%u\\) += -1 .*\n",
+               (unsigned) sizeof(union bpf_attr));
+# endif
+
        return 0;
 }
 
diff --git a/xlat/bpf_attach_type.in b/xlat/bpf_attach_type.in
new file mode 100644 (file)
index 0000000..f78bc5b
--- /dev/null
@@ -0,0 +1,3 @@
+BPF_CGROUP_INET_INGRESS 0
+BPF_CGROUP_INET_EGRESS 1
+BPF_CGROUP_INET_SOCK_CREATE 2
index 5c3035fde94fc1253d260f1a785e7ac29a9c6d6a..bcec9a5d7b3d174fbfd9e8772ef7d1c32a5f8024 100644 (file)
@@ -4,3 +4,7 @@ BPF_MAP_UPDATE_ELEM 2
 BPF_MAP_DELETE_ELEM 3
 BPF_MAP_GET_NEXT_KEY 4
 BPF_PROG_LOAD 5
+BPF_OBJ_PIN 6
+BPF_OBJ_GET 7
+BPF_PROG_ATTACH 8
+BPF_PROG_DETACH 9
index ccb24f33c7c8ed6959a98265129abdb4d7dd409d..e3222d38d78dfc7419718bb49ebb9803f9a50fcb 100644 (file)
@@ -7,3 +7,6 @@ BPF_MAP_TYPE_PERCPU_HASH 5
 BPF_MAP_TYPE_PERCPU_ARRAY 6
 BPF_MAP_TYPE_STACK_TRACE 7
 BPF_MAP_TYPE_CGROUP_ARRAY 8
+BPF_MAP_TYPE_LRU_HASH 9
+BPF_MAP_TYPE_LRU_PERCPU_HASH 10
+BPF_MAP_TYPE_LPM_TRIE 11
index 38e8ed29153b8d03dfc1d4cf29ede2403fd3ea94..bad608ec12d9080464f87756308d769cefdbfd98 100644 (file)
@@ -6,3 +6,8 @@ BPF_PROG_TYPE_SCHED_ACT 4
 BPF_PROG_TYPE_TRACEPOINT 5
 BPF_PROG_TYPE_XDP 6
 BPF_PROG_TYPE_PERF_EVENT 7
+BPF_PROG_TYPE_CGROUP_SKB 8
+BPF_PROG_TYPE_CGROUP_SOCK 9
+BPF_PROG_TYPE_LWT_IN 10
+BPF_PROG_TYPE_LWT_OUT 11
+BPF_PROG_TYPE_LWT_XMIT 12