]> granicus.if.org Git - strace/commitdiff
nlattr: add size check to decode_nla_xval and decode_nla_flags
authorEugene Syromyatnikov <evgsyr@gmail.com>
Wed, 23 May 2018 16:50:48 +0000 (18:50 +0200)
committerDmitry V. Levin <ldv@altlinux.org>
Wed, 6 Jun 2018 15:10:37 +0000 (15:10 +0000)
If the field size is known, do not print as valid numbers those
attributes that are too short, and ignore extra data.

This change puts xval/flags printing in line with the reset of attribute
decoders.

* nlattr.h (struct decode_nla_xlat_opts): Add size field.
* nlattr.c (decode_nla_xval, decode_nla_flags): Check that len is at
least opts->size, limit len to opts->size.
(decode_nla_ip_proto): Specify size of 1.

Co-Authored-by: Dmitry V. Levin <ldv@altlinux.org>
nlattr.c
nlattr.h

index 3484c03b9a613ebdc4b9db2a373de5305f17a843..cee827fc3a66ab2e8dc4319d70ebabec93c2bbf3 100644 (file)
--- a/nlattr.c
+++ b/nlattr.c
@@ -283,22 +283,24 @@ decode_nla_ifindex(struct tcb *const tcp,
 bool
 decode_nla_xval(struct tcb *const tcp,
                const kernel_ulong_t addr,
-               const unsigned int len,
+               unsigned int len,
                const void *const opaque_data)
 {
        const struct decode_nla_xlat_opts * const opts = opaque_data;
        union {
                uint64_t val;
                uint8_t  bytes[sizeof(uint64_t)];
-       } data;
-       const size_t bytes_offs = is_bigendian ? sizeof(data) - len : 0;
-
-       data.val = 0;
+       } data = { .val = 0 };
 
-       if (len > sizeof(data))
+       if (len > sizeof(data) || len < opts->size)
                return false;
-       else if (!umoven_or_printaddr(tcp, addr, len, data.bytes + bytes_offs))
-       {
+
+       if (opts->size)
+               len = MIN(len, opts->size);
+
+       const size_t bytes_offs = is_bigendian ? sizeof(data) - len : 0;
+
+       if (!umoven_or_printaddr(tcp, addr, len, data.bytes + bytes_offs)) {
                if (opts->process_fn)
                        data.val = opts->process_fn(data.val);
                if (opts->prefix)
@@ -348,6 +350,7 @@ decode_nla_ip_proto(struct tcb *const tcp,
                .xlat_size = inet_protocols_size,
                .xt = XT_SORTED,
                .dflt = "IPPROTO_???",
+               .size = 1,
        };
 
        return decode_nla_xval(tcp, addr, len, &opts);
@@ -356,7 +359,7 @@ decode_nla_ip_proto(struct tcb *const tcp,
 bool
 decode_nla_flags(struct tcb *const tcp,
                 const kernel_ulong_t addr,
-                const unsigned int len,
+                unsigned int len,
                 const void *const opaque_data)
 {
        const struct decode_nla_xlat_opts * const opts = opaque_data;
@@ -364,16 +367,20 @@ decode_nla_flags(struct tcb *const tcp,
                uint64_t flags;
                uint8_t  bytes[sizeof(uint64_t)];
        } data = { .flags = 0 };
+
+       if (len > sizeof(data) || len < opts->size)
+               return false;
+
+       if (opts->size)
+               len = MIN(len, opts->size);
+
        const size_t bytes_offs = is_bigendian ? sizeof(data) - len : 0;
 
        if (opts->xt == XT_INDEXED)
                error_func_msg("indexed xlats are currently incompatible with "
                               "printflags");
 
-       if (len > sizeof(data))
-               return false;
-       else if (!umoven_or_printaddr(tcp, addr, len, data.bytes + bytes_offs))
-       {
+       if (!umoven_or_printaddr(tcp, addr, len, data.bytes + bytes_offs)) {
                if (opts->process_fn)
                        data.flags = opts->process_fn(data.flags);
                if (opts->prefix)
index 10e085c4f25ebb985231101a08df7a7064abd837..34a36ad02af232135e56f87aef23b7cc4f2feec7 100644 (file)
--- a/nlattr.h
+++ b/nlattr.h
@@ -41,6 +41,7 @@ struct decode_nla_xlat_opts {
        const char *prefix;
        const char *suffix;
        uint64_t (*process_fn)(uint64_t val);
+       size_t size;
 };
 
 typedef bool (*nla_decoder_t)(struct tcb *, kernel_ulong_t addr,