]> granicus.if.org Git - strace/commitdiff
netlink: introduce a basic netlink attributes parser
authorJingPiao Chen <chenjingpiao@gmail.com>
Wed, 21 Jun 2017 16:24:23 +0000 (00:24 +0800)
committerDmitry V. Levin <ldv@altlinux.org>
Wed, 21 Jun 2017 16:36:33 +0000 (16:36 +0000)
* linux/unix_diag.h (UNIX_DIAG_*): New enum.
* nlattr.c: New file.
* nlattr.h: Likewise.
* Makefile.am (strace_SOURCES): Add them.
* netlink_sock_diag.c: Include "nlattr.h" and "xlat/unix_diag_attrs.h".
(decode_unix_diag_msg): Use decode_nlattr.
* xlat/unix_diag_attrs.in: New file.

Co-authored-by: Fabien Siron <fabien.siron@epita.fr>
Makefile.am
linux/unix_diag.h
netlink_sock_diag.c
nlattr.c [new file with mode: 0644]
nlattr.h [new file with mode: 0644]
xlat/unix_diag_attrs.in [new file with mode: 0644]

index 0d7597008bb9180af02b329527b31ba8cf54d8dd..76be3ca3d3128988735b8424c98760bba9ebe694 100644 (file)
@@ -175,6 +175,8 @@ strace_SOURCES =    \
        netlink.c       \
        netlink.h       \
        netlink_sock_diag.c \
+       nlattr.c        \
+       nlattr.h        \
        nsfs.c          \
        nsfs.h          \
        nsig.h          \
index a6b62bab0cca4dc08076eb09b1285cbe01df6479..3c9d99f89b233d2d13fc9bdf24f540b8d2a3e635 100644 (file)
@@ -27,7 +27,14 @@ struct unix_diag_msg {
        uint32_t udiag_cookie[2];
 };
 
-#define UNIX_DIAG_NAME 0
-#define UNIX_DIAG_PEER 2
+enum {
+       UNIX_DIAG_NAME,
+       UNIX_DIAG_VFS,
+       UNIX_DIAG_PEER,
+       UNIX_DIAG_ICONS,
+       UNIX_DIAG_RQLEN,
+       UNIX_DIAG_MEMINFO,
+       UNIX_DIAG_SHUTDOWN,
+};
 
 #endif /* !STRACE_LINUX_UNIX_DIAG_H */
index bdefe8b68d6105b91f831a5c303e38f507eb46c9..d854808e023377e3094054e99267c9d5b638dd9b 100644 (file)
@@ -29,6 +29,7 @@
 
 #include "defs.h"
 #include "netlink.h"
+#include "nlattr.h"
 
 #include <arpa/inet.h>
 #include <linux/inet_diag.h>
@@ -54,6 +55,7 @@
 # include "xlat/smc_states.h"
 #endif
 
+#include "xlat/unix_diag_attrs.h"
 #include "xlat/unix_diag_show.h"
 
 static void
@@ -112,7 +114,8 @@ decode_unix_diag_msg(struct tcb *const tcp,
                     const kernel_ulong_t len)
 {
        struct unix_diag_msg msg = { .udiag_family = family };
-       const size_t offset = sizeof(msg.udiag_family);
+       size_t offset = sizeof(msg.udiag_family);
+       bool decode_nla = false;
 
        tprints("{udiag_family=");
        printxval(addrfams, msg.udiag_family, "AF_???");
@@ -130,10 +133,18 @@ decode_unix_diag_msg(struct tcb *const tcp,
                                ", udiag_cookie=[%" PRIu32 ", %" PRIu32 "]",
                                msg.udiag_ino,
                                msg.udiag_cookie[0], msg.udiag_cookie[1]);
+                       decode_nla = true;
                }
        } else
                tprints("...");
        tprints("}");
+
+       offset = NLMSG_ALIGN(sizeof(msg));
+       if (decode_nla && len > offset) {
+               tprints(", ");
+               decode_nlattr(tcp, addr + offset, len - offset,
+                             unix_diag_attrs, "UNIX_DIAG_???");
+       }
 }
 
 static void
diff --git a/nlattr.c b/nlattr.c
new file mode 100644 (file)
index 0000000..8c51629
--- /dev/null
+++ b/nlattr.c
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2016 Fabien Siron <fabien.siron@epita.fr>
+ * Copyright (c) 2017 JingPiao Chen <chenjingpiao@gmail.com>
+ * Copyright (c) 2016-2017 The strace developers.
+ * 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 "netlink.h"
+
+static bool
+fetch_nlattr(struct tcb *const tcp, struct nlattr *const nlattr,
+            const kernel_ulong_t addr, const kernel_ulong_t len)
+{
+       if (len < sizeof(struct nlattr)) {
+               printstrn(tcp, addr, len);
+               return false;
+       }
+
+       if (umove_or_printaddr(tcp, addr, nlattr))
+               return false;
+
+       return true;
+}
+
+static void
+print_nlattr(const struct nlattr *const nla,
+            const struct xlat *const table,
+            const char *const dflt)
+{
+       tprintf("{nla_len=%u, nla_type=", nla->nla_len);
+       if (nla->nla_type & NLA_F_NESTED)
+               tprints("NLA_F_NESTED|");
+       if (nla->nla_type & NLA_F_NET_BYTEORDER)
+               tprints("NLA_F_NET_BYTEORDER|");
+       printxval(table, nla->nla_type & NLA_TYPE_MASK, dflt);
+       tprints("}");
+}
+
+static void
+decode_nlattr_with_data(struct tcb *tcp,
+                       const struct nlattr *const nla,
+                       kernel_ulong_t addr,
+                       kernel_ulong_t len,
+                       const struct xlat *const table,
+                       const char *const dflt)
+{
+       const unsigned int nla_len = nla->nla_len > len ? len : nla->nla_len;
+
+       if (nla_len > NLA_HDRLEN)
+               tprints("{");
+
+       print_nlattr(nla, table, dflt);
+
+       if (nla_len > NLA_HDRLEN) {
+               tprints(", ");
+               printstrn(tcp, addr + NLA_HDRLEN, nla_len - NLA_HDRLEN);
+               tprints("}");
+       }
+}
+
+void
+decode_nlattr(struct tcb *const tcp,
+             kernel_ulong_t addr,
+             kernel_ulong_t len,
+             const struct xlat *const table,
+             const char *const dflt)
+{
+       struct nlattr nla;
+       bool print_array = false;
+       unsigned int elt;
+
+       for (elt = 0; fetch_nlattr(tcp, &nla, addr, len); elt++) {
+               if (abbrev(tcp) && elt == max_strlen) {
+                       tprints("...");
+                       break;
+               }
+
+               const unsigned long nla_len = NLA_ALIGN(nla.nla_len);
+               kernel_ulong_t next_addr = 0;
+               kernel_ulong_t next_len = 0;
+
+               if (nla.nla_len >= NLA_HDRLEN) {
+                       next_len = (len >= nla_len) ? len - nla_len : 0;
+
+                       if (next_len && addr + nla_len > addr)
+                               next_addr = addr + nla_len;
+               }
+
+               if (!print_array && next_addr) {
+                       tprints("[");
+                       print_array = true;
+               }
+
+               decode_nlattr_with_data(tcp, &nla, addr, len, table, dflt);
+
+               if (!next_addr)
+                       break;
+
+               tprints(", ");
+               addr = next_addr;
+               len = next_len;
+       }
+
+       if (print_array) {
+               tprints("]");
+       }
+}
diff --git a/nlattr.h b/nlattr.h
new file mode 100644 (file)
index 0000000..ade2271
--- /dev/null
+++ b/nlattr.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2016 Fabien Siron <fabien.siron@epita.fr>
+ * Copyright (c) 2017 JingPiao Chen <chenjingpiao@gmail.com>
+ * Copyright (c) 2016-2017 The strace developers.
+ * 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.
+ */
+
+#ifndef STRACE_NLATTR_H
+#define STRACE_NLATTR_H
+
+extern void
+decode_nlattr(struct tcb *, kernel_ulong_t addr, kernel_ulong_t len,
+             const struct xlat *, const char *);
+
+#endif /* !STRACE_NLATTR_H */
diff --git a/xlat/unix_diag_attrs.in b/xlat/unix_diag_attrs.in
new file mode 100644 (file)
index 0000000..4c3d9b2
--- /dev/null
@@ -0,0 +1,8 @@
+#unconditional
+UNIX_DIAG_NAME
+UNIX_DIAG_VFS
+UNIX_DIAG_PEER
+UNIX_DIAG_ICONS
+UNIX_DIAG_RQLEN
+UNIX_DIAG_MEMINFO
+UNIX_DIAG_SHUTDOWN