From: Eugene Syromyatnikov Date: Wed, 23 May 2018 16:50:48 +0000 (+0200) Subject: nlattr: add size check to decode_nla_xval and decode_nla_flags X-Git-Tag: v4.23~42 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c0827b1ae93fa892a3e9cd97940d2b846b97b1b5;p=strace nlattr: add size check to decode_nla_xval and decode_nla_flags 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 --- diff --git a/nlattr.c b/nlattr.c index 3484c03b..cee827fc 100644 --- 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) diff --git a/nlattr.h b/nlattr.h index 10e085c4..34a36ad0 100644 --- 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,