From 3a43ce3c07b58ca4c218849a93d0fecafe5f2c36 Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Tue, 21 Nov 2017 21:08:19 +0000 Subject: [PATCH] Implement decoding of BPF_*_GET_*_ID commands of bpf syscall * configure.ac: Check for union bpf_attr.next_id. * bpf.c (decode_BPF_PROG_GET_NEXT_ID, decode_BPF_PROG_GET_FD_BY_ID, * decode_BPF_MAP_GET_FD_BY_ID): New functions. (decode_BPF_MAP_GET_NEXT_ID): New macro. (SYS_FUNC(bpf)) : Use them. * NEWS: Mention this. * tests/bpf.c: Add macro guard for BPF_*_GET_*_ID decoder tests. [HAVE_UNION_BPF_ATTR_NEXT_ID] (init_BPF_PROG_GET_NEXT_ID_first, print_BPF_PROG_GET_NEXT_ID_first, init_BPF_PROG_GET_NEXT_ID_attr, print_BPF_PROG_GET_NEXT_ID_attr, print_BPF_PROG_GET_FD_BY_ID_first, print_BPF_PROG_GET_FD_BY_ID_attr, print_BPF_MAP_GET_NEXT_ID_first, print_BPF_MAP_GET_NEXT_ID_attr): New functions. (init_BPF_MAP_GET_NEXT_ID_first, print_BPF_MAP_GET_NEXT_ID_first, init_BPF_MAP_GET_NEXT_ID_attr, print_BPF_MAP_GET_NEXT_ID_attr, init_BPF_PROG_GET_FD_BY_ID_first, init_BPF_PROG_GET_FD_BY_ID_attr, init_BPF_MAP_GET_FD_BY_ID_first, init_BPF_MAP_GET_FD_BY_ID_attr): New macros. (main) [HAVE_UNION_BPF_ATTR_NEXT_ID]: Use them. --- NEWS | 4 ++- bpf.c | 57 +++++++++++++++++++++++++++++++++++ configure.ac | 1 + tests/bpf.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 146 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index d52b5c36..1c5d0026 100644 --- a/NEWS +++ b/NEWS @@ -4,7 +4,9 @@ Noteworthy changes in release ?.?? (????-??-??) * Improvements * Implemented decoding of netlink descriptor attributes as file descriptors. * Implemented decoding of hugetlb page size selection flags. - * Implemented decoding of BPF_PROG_TEST_RUN command of bpf syscall. + * Implemented decoding of BPF_PROG_TEST_RUN, BPF_PROG_GET_NEXT_ID, + BPF_MAP_GET_NEXT_ID, BPF_PROG_GET_FD_BY_ID, and BPF_MAP_GET_FD_BY_ID + commands of bpf syscall. * Enhanced decoding of getsockopt and setsockopt syscalls for SOL_NETLINK level. * Enhanced decoding of BPF_MAP_CREATE command of bpf syscall. diff --git a/bpf.c b/bpf.c index 5b4035ef..321212ff 100644 --- a/bpf.c +++ b/bpf.c @@ -306,6 +306,59 @@ DEF_BPF_CMD_DECODER(BPF_PROG_TEST_RUN) return RVAL_DECODED; } +DEF_BPF_CMD_DECODER(BPF_PROG_GET_NEXT_ID) +{ + struct { + uint32_t start_id, next_id; + } attr = {}; + const unsigned int len = size < sizeof(attr) ? size : sizeof(attr); + + memcpy(&attr, data, len); + + PRINT_FIELD_U("{", attr, start_id); + PRINT_FIELD_U(", ", attr, next_id); + decode_attr_extra_data(tcp, data, size, sizeof(attr)); + tprints("}"); + + return RVAL_DECODED; +} + +#define decode_BPF_MAP_GET_NEXT_ID decode_BPF_PROG_GET_NEXT_ID + +DEF_BPF_CMD_DECODER(BPF_PROG_GET_FD_BY_ID) +{ + struct { + uint32_t prog_id, next_id; + } attr = {}; + const unsigned int len = size < sizeof(attr) ? size : sizeof(attr); + + memcpy(&attr, data, len); + + PRINT_FIELD_U("{", attr, prog_id); + PRINT_FIELD_U(", ", attr, next_id); + decode_attr_extra_data(tcp, data, size, sizeof(attr)); + tprints("}"); + + return RVAL_DECODED; +} + +DEF_BPF_CMD_DECODER(BPF_MAP_GET_FD_BY_ID) +{ + struct { + uint32_t map_id, next_id; + } attr = {}; + const unsigned int len = size < sizeof(attr) ? size : sizeof(attr); + + memcpy(&attr, data, len); + + PRINT_FIELD_U("{", attr, map_id); + PRINT_FIELD_U(", ", attr, next_id); + decode_attr_extra_data(tcp, data, size, sizeof(attr)); + tprints("}"); + + return RVAL_DECODED; +} + SYS_FUNC(bpf) { static const bpf_cmd_decoder_t bpf_cmd_decoders[] = { @@ -320,6 +373,10 @@ SYS_FUNC(bpf) BPF_CMD_ENTRY(BPF_PROG_ATTACH), BPF_CMD_ENTRY(BPF_PROG_DETACH), BPF_CMD_ENTRY(BPF_PROG_TEST_RUN), + BPF_CMD_ENTRY(BPF_PROG_GET_NEXT_ID), + BPF_CMD_ENTRY(BPF_MAP_GET_NEXT_ID), + BPF_CMD_ENTRY(BPF_PROG_GET_FD_BY_ID), + BPF_CMD_ENTRY(BPF_MAP_GET_FD_BY_ID), }; const unsigned int cmd = tcp->u_arg[0]; diff --git a/configure.ac b/configure.ac index e57e8989..4fab3b1f 100644 --- a/configure.ac +++ b/configure.ac @@ -462,6 +462,7 @@ AC_CHECK_HEADERS([linux/bpf.h], [ st_CHECK_UNION_BPF_ATTR([attach_flags]) st_CHECK_UNION_BPF_ATTR([bpf_fd]) st_CHECK_UNION_BPF_ATTR([flags]) + st_CHECK_UNION_BPF_ATTR([next_id]) st_CHECK_UNION_BPF_ATTR([numa_node]) st_CHECK_UNION_BPF_ATTR([prog_flags]) AC_CHECK_MEMBERS([union bpf_attr.test.duration],,, [#include ]) diff --git a/tests/bpf.c b/tests/bpf.c index c5e1293a..d18aebf2 100644 --- a/tests/bpf.c +++ b/tests/bpf.c @@ -34,6 +34,7 @@ && (defined HAVE_UNION_BPF_ATTR_ATTACH_FLAGS \ || defined HAVE_UNION_BPF_ATTR_BPF_FD \ || defined HAVE_UNION_BPF_ATTR_FLAGS \ + || defined HAVE_UNION_BPF_ATTR_NEXT_ID \ || defined HAVE_UNION_BPF_ATTR_NUMA_NODE \ || defined HAVE_UNION_BPF_ATTR_PROG_FLAGS \ || defined HAVE_UNION_BPF_ATTR_TEST_DURATION) @@ -623,6 +624,83 @@ print_BPF_PROG_TEST_RUN_attr(const unsigned long addr) # endif /* HAVE_UNION_BPF_ATTR_TEST_DURATION */ +# ifdef HAVE_UNION_BPF_ATTR_NEXT_ID + +static unsigned int +init_BPF_PROG_GET_NEXT_ID_first(const unsigned long eop) +{ + static const union bpf_attr attr = { .start_id = 0xdeadbeef }; + static const unsigned int offset = sizeof(attr.start_id); + const unsigned long addr = eop - offset; + + memcpy((void *) addr, &attr.start_id, offset); + return offset; +} + +static void +print_BPF_PROG_GET_NEXT_ID_first(const unsigned long addr) +{ + printf("start_id=%u, next_id=0", 0xdeadbeef); +} + +static unsigned int +init_BPF_PROG_GET_NEXT_ID_attr(const unsigned long eop) +{ + static const union bpf_attr attr = { + .start_id = 0xbadc0ded, + .next_id = 0xcafef00d + }; + static const unsigned int offset = + offsetofend(union bpf_attr, next_id); + const unsigned long addr = eop - offset; + + memcpy((void *) addr, &attr, offset); + return offset; +} + +static void +print_BPF_PROG_GET_NEXT_ID_attr(const unsigned long addr) +{ + printf("start_id=%u, next_id=%u", 0xbadc0ded, 0xcafef00d); +} + +# define init_BPF_MAP_GET_NEXT_ID_first init_BPF_PROG_GET_NEXT_ID_first +# define print_BPF_MAP_GET_NEXT_ID_first print_BPF_PROG_GET_NEXT_ID_first +# define init_BPF_MAP_GET_NEXT_ID_attr init_BPF_PROG_GET_NEXT_ID_attr +# define print_BPF_MAP_GET_NEXT_ID_attr print_BPF_PROG_GET_NEXT_ID_attr + +# define init_BPF_PROG_GET_FD_BY_ID_first init_BPF_PROG_GET_NEXT_ID_first +# define init_BPF_PROG_GET_FD_BY_ID_attr init_BPF_PROG_GET_NEXT_ID_attr + +static void +print_BPF_PROG_GET_FD_BY_ID_first(const unsigned long addr) +{ + printf("prog_id=%u, next_id=0", 0xdeadbeef); +} + +static void +print_BPF_PROG_GET_FD_BY_ID_attr(const unsigned long addr) +{ + printf("prog_id=%u, next_id=%u", 0xbadc0ded, 0xcafef00d); +} + +# define init_BPF_MAP_GET_FD_BY_ID_first init_BPF_PROG_GET_NEXT_ID_first +# define init_BPF_MAP_GET_FD_BY_ID_attr init_BPF_PROG_GET_NEXT_ID_attr + +static void +print_BPF_MAP_GET_FD_BY_ID_first(const unsigned long addr) +{ + printf("map_id=%u, next_id=0", 0xdeadbeef); +} + +static void +print_BPF_MAP_GET_FD_BY_ID_attr(const unsigned long addr) +{ + printf("map_id=%u, next_id=%u", 0xbadc0ded, 0xcafef00d); +} + +# endif /* HAVE_UNION_BPF_ATTR_NEXT_ID */ + int main(void) { @@ -658,6 +736,13 @@ main(void) TEST_BPF(BPF_PROG_TEST_RUN); # endif +# ifdef HAVE_UNION_BPF_ATTR_NEXT_ID + TEST_BPF(BPF_PROG_GET_NEXT_ID); + TEST_BPF(BPF_MAP_GET_NEXT_ID); + TEST_BPF(BPF_PROG_GET_FD_BY_ID); + TEST_BPF(BPF_MAP_GET_FD_BY_ID); +# endif + sys_bpf(0xfacefeed, end_of_page, 40); printf("bpf(0xfacefeed /* BPF_??? */, %#lx, 40) = %s\n", end_of_page, errstr); -- 2.40.0