]> granicus.if.org Git - strace/commitdiff
Implement decoding of linux socket filter programs
authorDmitry V. Levin <ldv@altlinux.org>
Sat, 8 Jul 2017 14:57:44 +0000 (14:57 +0000)
committerDmitry V. Levin <ldv@altlinux.org>
Sat, 8 Jul 2017 14:57:44 +0000 (14:57 +0000)
* 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
NEWS
bpf_sock_filter.c [new file with mode: 0644]
defs.h
fetch_bpf_fprog.c
net.c
xlat/skf_ad.in [new file with mode: 0644]

index bb3d21dab02cc194bab49ebc4c957c8b45391e91..f0c42fff93f24234a6c0747a512e6fb093ce1a2a 100644 (file)
@@ -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 4cb22a3f68ad5a4c23a6145a54c16809a7b6b2c1..947d506c0eb3ccab6b935d64bfc28d73af08dd06 100644 (file)
--- 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 (file)
index 0000000..7f8e16a
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Decoder of socket filter programs.
+ *
+ * Copyright (c) 2017 Dmitry V. Levin <ldv@altlinux.org>
+ * 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 <linux/filter.h>
+#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 3eb9a440535451f0d11a4404ba28433d15f694dc..f23bca11e828b6155b891cc924a1257c4e7251c7 100644 (file)
--- 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);
 
index d4bf69de323f591c44079f15cf74c7dc59513a15..e46ddf9ee8e29359865d47701447085e94a4663f 100644 (file)
@@ -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 58a1bbf3c905f50a162941984e8975053d94ac20..257e0df3fc174868119ae0a02dede1b9254221ba 100644 (file)
--- 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 (file)
index 0000000..d083c63
--- /dev/null
@@ -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