]> granicus.if.org Git - strace/commitdiff
nlattr: add ability to pass nla_type to decoder in decode_nlattr
authorEugene Syromyatnikov <evgsyr@gmail.com>
Mon, 7 May 2018 06:28:38 +0000 (08:28 +0200)
committerDmitry V. Levin <ldv@altlinux.org>
Wed, 6 Jun 2018 15:10:37 +0000 (15:10 +0000)
As of now, it's impossible to introduce a dispatching nlattr decoder
that performs actions based on the type of the message, so let's use
a combination of zero decoder list size and non-zero decoder pointer
for this.

This is going to be used later in IFLA_AF_SPEC decoding.

* nlattr.c (decode_nlattr_with_data): Handle zero size and non-NULL
decoders in a special way.
(decode_nlattr): Add an error message about ignoring of opaque_data
argument when zero size and non-NULL decoders are provided.
* nlattr.h (decode_nlattr): Add a comment about the new special case.

nlattr.c
nlattr.h

index 8dea4847721514b69013b5db7fe363c0530c7677..f65d9cf6a6288f245aefff97f6512cd322b2d552 100644 (file)
--- a/nlattr.c
+++ b/nlattr.c
@@ -101,13 +101,18 @@ decode_nlattr_with_data(struct tcb *const tcp,
        print_nlattr(nla, table, dflt);
 
        if (nla_len > NLA_HDRLEN) {
+               const unsigned int idx = size ? nla->nla_type : 0;
+
                tprints(", ");
                if (!decoders
-                   || nla->nla_type >= size
-                   || !decoders[nla->nla_type]
-                   || !decoders[nla->nla_type](tcp, addr + NLA_HDRLEN,
-                                               nla_len - NLA_HDRLEN,
-                                               opaque_data))
+                   || (size && idx >= size)
+                   || !decoders[idx]
+                   || !decoders[idx](
+                               tcp, addr + NLA_HDRLEN,
+                               nla_len - NLA_HDRLEN,
+                               size ? opaque_data
+                                    : (const void *) (uintptr_t) nla->nla_type)
+                   )
                        printstr_ex(tcp, addr + NLA_HDRLEN,
                                    nla_len - NLA_HDRLEN, QUOTE_FORCE_HEX);
                tprints("}");
@@ -128,6 +133,13 @@ decode_nlattr(struct tcb *const tcp,
        bool is_array = false;
        unsigned int elt;
 
+       if (decoders && !size && opaque_data)
+               error_func_msg("[xlat %p, dflt \"%s\", decoders %p] "
+                              "size is zero (going to pass nla_type as "
+                              "decoder argument), but opaque data (%p) is not "
+                              "- will be ignored",
+                              table, dflt, decoders, opaque_data);
+
        for (elt = 0; fetch_nlattr(tcp, &nla, addr, len, is_array); elt++) {
                if (abbrev(tcp) && elt == max_strlen) {
                        tprints("...");
index 7f0ee0cd2fe02628b623fba777b432ba1212d574..765aba82389f81aa92287dc7f36e874501b7d4c1 100644 (file)
--- a/nlattr.h
+++ b/nlattr.h
@@ -42,13 +42,19 @@ struct decode_nla_xlat_opts {
 
 typedef bool (*nla_decoder_t)(struct tcb *, kernel_ulong_t addr,
                              unsigned int len, const void *opaque_data);
+
+/**
+ * The case of non-NULL decoders and zero size is handled in a special way:
+ * the zeroth decoder is always called with nla_type being passed as opaque
+ * data.
+ */
 extern void
 decode_nlattr(struct tcb *,
              kernel_ulong_t addr,
              unsigned int len,
              const struct xlat *,
              const char *dflt,
-             const nla_decoder_t *,
+             const nla_decoder_t *decoders,
              unsigned int size,
              const void *opaque_data);