/*
* 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
#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,
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];
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;
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], [
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)
{
"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;
}
--- /dev/null
+BPF_CGROUP_INET_INGRESS 0
+BPF_CGROUP_INET_EGRESS 1
+BPF_CGROUP_INET_SOCK_CREATE 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
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
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