From 5c511738301565ed694d5a02abe7ac4bd688b96a Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Tue, 21 Nov 2017 23:12:04 +0000 Subject: [PATCH] Implement decoding of BPF_OBJ_GET_INFO_BY_FD command of bpf syscall * configure.ac (AC_CHECK_MEMBERS): Add union bpf_attr.info.info. * bpf.c (decode_BPF_OBJ_GET_INFO_BY_FD): New function. (SYS_FUNC(bpf)) : Use it. * NEWS: Mention this. * tests/bpf.c: Add macro guard for BPF_OBJ_GET_INFO_BY_FD decoder test. [HAVE_UNION_BPF_ATTR_INFO_INFO] (sample_BPF_OBJ_GET_INFO_BY_FD_attr): New variable. [HAVE_UNION_BPF_ATTR_INFO_INFO] (init_BPF_OBJ_GET_INFO_BY_FD_first, print_BPF_OBJ_GET_INFO_BY_FD_first, init_BPF_OBJ_GET_INFO_BY_FD_attr, print_BPF_OBJ_GET_INFO_BY_FD_attr): New functions. (main) [HAVE_UNION_BPF_ATTR_INFO_INFO]: Use them. --- NEWS | 4 ++-- bpf.c | 21 +++++++++++++++++++++ configure.ac | 1 + tests/bpf.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 77 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index 1c5d0026..d62f5ebc 100644 --- a/NEWS +++ b/NEWS @@ -5,8 +5,8 @@ Noteworthy changes in release ?.?? (????-??-??) * Implemented decoding of netlink descriptor attributes as file descriptors. * Implemented decoding of hugetlb page size selection flags. * 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. + BPF_MAP_GET_NEXT_ID, BPF_PROG_GET_FD_BY_ID, BPF_MAP_GET_FD_BY_ID, + and BPF_OBJ_GET_INFO_BY_FD 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 321212ff..59d1e749 100644 --- a/bpf.c +++ b/bpf.c @@ -359,6 +359,26 @@ DEF_BPF_CMD_DECODER(BPF_MAP_GET_FD_BY_ID) return RVAL_DECODED; } +DEF_BPF_CMD_DECODER(BPF_OBJ_GET_INFO_BY_FD) +{ + struct { + uint32_t bpf_fd, info_len; + uint64_t ATTRIBUTE_ALIGNED(8) info; + } attr = {}; + const unsigned int len = size < sizeof(attr) ? size : sizeof(attr); + + memcpy(&attr, data, len); + + PRINT_FIELD_FD("{info={", attr, bpf_fd, tcp); + PRINT_FIELD_U(", ", attr, info_len); + PRINT_FIELD_X(", ", attr, info); + tprints("}"); + decode_attr_extra_data(tcp, data, size, sizeof(attr)); + tprints("}"); + + return RVAL_DECODED | RVAL_FD; +} + SYS_FUNC(bpf) { static const bpf_cmd_decoder_t bpf_cmd_decoders[] = { @@ -377,6 +397,7 @@ SYS_FUNC(bpf) 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), + BPF_CMD_ENTRY(BPF_OBJ_GET_INFO_BY_FD), }; const unsigned int cmd = tcp->u_arg[0]; diff --git a/configure.ac b/configure.ac index 0f74fe18..f140a56c 100644 --- a/configure.ac +++ b/configure.ac @@ -463,6 +463,7 @@ AC_CHECK_HEADERS([linux/bpf.h], [ union bpf_attr.attach_flags, union bpf_attr.bpf_fd, union bpf_attr.flags, + union bpf_attr.info.info, union bpf_attr.next_id, union bpf_attr.numa_node, union bpf_attr.prog_flags, diff --git a/tests/bpf.c b/tests/bpf.c index d18aebf2..d134302f 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_INFO_INFO \ || defined HAVE_UNION_BPF_ATTR_NEXT_ID \ || defined HAVE_UNION_BPF_ATTR_NUMA_NODE \ || defined HAVE_UNION_BPF_ATTR_PROG_FLAGS \ @@ -701,6 +702,54 @@ print_BPF_MAP_GET_FD_BY_ID_attr(const unsigned long addr) # endif /* HAVE_UNION_BPF_ATTR_NEXT_ID */ +# ifdef HAVE_UNION_BPF_ATTR_INFO_INFO + +static unsigned int +init_BPF_OBJ_GET_INFO_BY_FD_first(const unsigned long eop) +{ + static const union bpf_attr attr = { .info.bpf_fd = -1 }; + static const unsigned int offset = sizeof(attr.info.bpf_fd); + const unsigned long addr = eop - offset; + + memcpy((void *) addr, &attr.info.bpf_fd, offset); + return offset; +} + +static void +print_BPF_OBJ_GET_INFO_BY_FD_first(const unsigned long addr) +{ + printf("info={bpf_fd=-1, info_len=0, info=0}"); +} + +static const union bpf_attr sample_BPF_OBJ_GET_INFO_BY_FD_attr = { + .info = { + .bpf_fd = -1, + .info_len = 0xdeadbeef, + .info = (uint64_t) 0xfacefeedbadc0ded + } +}; +static unsigned int +init_BPF_OBJ_GET_INFO_BY_FD_attr(const unsigned long eop) +{ + static const unsigned int offset = + offsetofend(union bpf_attr, info); + const unsigned long addr = eop - offset; + + memcpy((void *) addr, &sample_BPF_OBJ_GET_INFO_BY_FD_attr, offset); + return offset; +} + +static void +print_BPF_OBJ_GET_INFO_BY_FD_attr(const unsigned long addr) +{ + PRINT_FIELD_D("info={", sample_BPF_OBJ_GET_INFO_BY_FD_attr.info, bpf_fd); + PRINT_FIELD_U(", ", sample_BPF_OBJ_GET_INFO_BY_FD_attr.info, info_len); + PRINT_FIELD_X(", ", sample_BPF_OBJ_GET_INFO_BY_FD_attr.info, info); + printf("}"); +} + +# endif /* HAVE_UNION_BPF_ATTR_INFO_INFO */ + int main(void) { @@ -743,6 +792,10 @@ main(void) TEST_BPF(BPF_MAP_GET_FD_BY_ID); # endif +# ifdef HAVE_UNION_BPF_ATTR_INFO_INFO + TEST_BPF(BPF_OBJ_GET_INFO_BY_FD); +# endif + sys_bpf(0xfacefeed, end_of_page, 40); printf("bpf(0xfacefeed /* BPF_??? */, %#lx, 40) = %s\n", end_of_page, errstr); -- 2.40.0