From bc515c7f54df7d0b64b8f7f3ec34852cb4df0d99 Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Sat, 8 Jul 2017 14:57:44 +0000 Subject: [PATCH] Implement decoding of linux socket filter programs * bpf_sock_filter.c: New file. * Makefile.am (strace_SOURCES): Add it. * xlat/skf_ad.in: New file. * defs.h (decode_sock_fprog, print_sock_fprog): New prototypes. * fetch_bpf_fprog.c (get_bpf_fprog_size): New mpers printer. * net.c (print_getsockopt): Use decode_sock_fprog to print socket filter programs for SO_GET_FILTER socket option. (print_setsockopt): Use decode_sock_fprog and get_bpf_fprog_size to print socket filter programs for SO_ATTACH_FILTER and SO_ATTACH_REUSEPORT_CBPF socket options. * NEWS: Mention this. --- Makefile.am | 1 + NEWS | 2 ++ bpf_sock_filter.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++ defs.h | 6 ++++ fetch_bpf_fprog.c | 5 ++++ net.c | 19 +++++++++++++ xlat/skf_ad.in | 16 +++++++++++ 7 files changed, 120 insertions(+) create mode 100644 bpf_sock_filter.c create mode 100644 xlat/skf_ad.in diff --git a/Makefile.am b/Makefile.am index bb3d21da..f0c42fff 100644 --- a/Makefile.am +++ b/Makefile.am @@ -93,6 +93,7 @@ strace_SOURCES = \ bpf_filter.h \ bpf_fprog.h \ bpf_seccomp_filter.c \ + bpf_sock_filter.c \ btrfs.c \ cacheflush.c \ capability.c \ diff --git a/NEWS b/NEWS index 4cb22a3f..947d506c 100644 --- a/NEWS +++ b/NEWS @@ -4,6 +4,8 @@ Noteworthy changes in release ?.?? (????-??-??) * Improvements * Enhanced decoding of optlen argument of getsockopt syscall. * Enhanced decoding of SO_LINGER option of getsockopt and setsockopt syscalls. + * Implemented decoding of linux socket filter programs specified + for SO_ATTACH_FILTER and SO_ATTACH_REUSEPORT_CBPF socket options. Noteworthy changes in release 4.18 (2017-07-05) =============================================== diff --git a/bpf_sock_filter.c b/bpf_sock_filter.c new file mode 100644 index 00000000..7f8e16a8 --- /dev/null +++ b/bpf_sock_filter.c @@ -0,0 +1,71 @@ +/* + * Decoder of socket filter programs. + * + * Copyright (c) 2017 Dmitry V. Levin + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "defs.h" + +#include "bpf_filter.h" + +#include +#include "xlat/skf_ad.h" + +static bool +print_sock_filter_k(const struct bpf_filter_block *const fp) +{ + if (BPF_CLASS(fp->code) == BPF_LD && BPF_MODE(fp->code) == BPF_ABS) { + if (fp->k >= (unsigned int) SKF_AD_OFF) { + tprints("SKF_AD_OFF+"); + printxval(skf_ad, fp->k - (unsigned int) SKF_AD_OFF, + "SKF_AD_???"); + return true; + } else if (fp->k >= (unsigned int) SKF_NET_OFF) { + tprintf("%s+%u", "SKF_NET_OFF", + fp->k - (unsigned int) SKF_NET_OFF); + return true; + } else if (fp->k >= (unsigned int) SKF_LL_OFF) { + tprintf("%s+%u", "SKF_LL_OFF", + fp->k - (unsigned int) SKF_LL_OFF); + return true; + } + } + + return false; +} + +void +print_sock_fprog(struct tcb *const tcp, const kernel_ulong_t addr, + const unsigned short len) +{ + print_bpf_fprog(tcp, addr, len, print_sock_filter_k); +} + +void +decode_sock_fprog(struct tcb *const tcp, const kernel_ulong_t addr) +{ + decode_bpf_fprog(tcp, addr, print_sock_filter_k); +} diff --git a/defs.h b/defs.h index 3eb9a440..f23bca11 100644 --- a/defs.h +++ b/defs.h @@ -649,6 +649,12 @@ decode_seccomp_fprog(struct tcb *, kernel_ulong_t addr); extern void print_seccomp_fprog(struct tcb *, kernel_ulong_t addr, unsigned short len); +extern void +decode_sock_fprog(struct tcb *, kernel_ulong_t addr); + +extern void +print_sock_fprog(struct tcb *, kernel_ulong_t addr, unsigned short len); + struct strace_stat; extern void print_struct_stat(struct tcb *, const struct strace_stat *const st); diff --git a/fetch_bpf_fprog.c b/fetch_bpf_fprog.c index d4bf69de..e46ddf9e 100644 --- a/fetch_bpf_fprog.c +++ b/fetch_bpf_fprog.c @@ -35,6 +35,11 @@ typedef struct sock_fprog struct_sock_fprog; #include MPERS_DEFS #include "bpf_fprog.h" +MPERS_PRINTER_DECL(unsigned int, get_sock_fprog_size, void) +{ + return sizeof(struct_sock_fprog); +} + MPERS_PRINTER_DECL(bool, fetch_bpf_fprog, struct tcb *const tcp, const kernel_ulong_t addr, void *const p) { diff --git a/net.c b/net.c index 58a1bbf3..257e0df3 100644 --- a/net.c +++ b/net.c @@ -606,6 +606,14 @@ print_getsockopt(struct tcb *const tcp, const unsigned int level, print_ucred(tcp, addr, len); return; #endif +#ifdef SO_ATTACH_FILTER + case SO_ATTACH_FILTER: + if (len && (unsigned short) len == (unsigned int) len) + print_sock_fprog(tcp, addr, len); + else + printaddr(addr); + return; +#endif /* SO_ATTACH_FILTER */ } break; @@ -799,6 +807,17 @@ print_setsockopt(struct tcb *const tcp, const unsigned int level, case SO_LINGER: print_set_linger(tcp, addr, len); return; +#ifdef SO_ATTACH_FILTER + case SO_ATTACH_FILTER: +# ifdef SO_ATTACH_REUSEPORT_CBPF + case SO_ATTACH_REUSEPORT_CBPF: +# endif + if ((unsigned int) len == get_sock_fprog_size()) + decode_sock_fprog(tcp, addr); + else + printaddr(addr); + return; +#endif /* SO_ATTACH_FILTER */ } break; diff --git a/xlat/skf_ad.in b/xlat/skf_ad.in new file mode 100644 index 00000000..d083c635 --- /dev/null +++ b/xlat/skf_ad.in @@ -0,0 +1,16 @@ +SKF_AD_PROTOCOL 0 +SKF_AD_PKTTYPE 4 +SKF_AD_IFINDEX 8 +SKF_AD_NLATTR 12 +SKF_AD_NLATTR_NEST 16 +SKF_AD_MARK 20 +SKF_AD_QUEUE 24 +SKF_AD_HATYPE 28 +SKF_AD_RXHASH 32 +SKF_AD_CPU 36 +SKF_AD_ALU_XOR_X 40 +SKF_AD_VLAN_TAG 44 +SKF_AD_VLAN_TAG_PRESENT 48 +SKF_AD_PAY_OFFSET 52 +SKF_AD_RANDOM 56 +SKF_AD_VLAN_TPID 60 -- 2.40.0