* bpf.c: Add decoding for BPF_OBJ_PIN, BPF_OBJ_GET, BPF_PROG_ATTACH, and BPF_PROG_DETACH commands. * configure.ac: Add checks for BPF features. * 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: New tests. --- bpf.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++ configure.ac | 22 ++++++++++++ tests/bpf.c | 65 +++++++++++++++++++++++++++++++++ xlat/bpf_attach_type.in | 3 ++ xlat/bpf_commands.in | 4 +++ xlat/bpf_map_types.in | 3 ++ xlat/bpf_prog_types.in | 5 +++ 7 files changed, 197 insertions(+) create mode 100644 xlat/bpf_attach_type.in
diff --git a/bpf.c b/bpf.c index 04c677a173ad..d36745ed8960 100644 --- a/bpf.c +++ b/bpf.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2015 Dmitry V. Levin <l...@altlinux.org> + * Copyright (c) 2017 Quentin Monnet <quentin.mon...@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; diff --git a/configure.ac b/configure.ac index 38177146cd21..b163bea783ab 100644 --- a/configure.ac +++ b/configure.ac @@ -427,6 +427,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], [ diff --git a/tests/bpf.c b/tests/bpf.c index 5a1fcdc7d72d..57b1183244de 100644 --- a/tests/bpf.c +++ b/tests/bpf.c @@ -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. + */ +#if defined HAVE_UNION_BPF_ATTR_BPF_FD +static int +obj_manage(int cmd) +{ + union bpf_attr attr = { + .pathname = (uint64_t)(void *) "/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. */ +#if defined 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 = BPF_CGROUP_INET_INGRESS + }; + 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)); +#if defined 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 + +#if defined 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 index 000000000000..f78bc5bef8cd --- /dev/null +++ b/xlat/bpf_attach_type.in @@ -0,0 +1,3 @@ +BPF_CGROUP_INET_INGRESS 0 +BPF_CGROUP_INET_EGRESS 1 +BPF_CGROUP_INET_SOCK_CREATE 2 diff --git a/xlat/bpf_commands.in b/xlat/bpf_commands.in index 5c3035fde94f..bcec9a5d7b3d 100644 --- a/xlat/bpf_commands.in +++ b/xlat/bpf_commands.in @@ -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 diff --git a/xlat/bpf_map_types.in b/xlat/bpf_map_types.in index ccb24f33c7c8..e3222d38d78d 100644 --- a/xlat/bpf_map_types.in +++ b/xlat/bpf_map_types.in @@ -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 diff --git a/xlat/bpf_prog_types.in b/xlat/bpf_prog_types.in index 38e8ed29153b..bad608ec12d9 100644 --- a/xlat/bpf_prog_types.in +++ b/xlat/bpf_prog_types.in @@ -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 -- 2.7.4 ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, SlashDot.org! http://sdm.link/slashdot _______________________________________________ Strace-devel mailing list Strace-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/strace-devel