[PATCH v3 13/16] netlink: introduce nla_decoder_t to parse netlink attribute data

Dmitry V. Levin ldv at altlinux.org
Tue Jun 20 00:06:45 UTC 2017


On Mon, Jun 19, 2017 at 09:15:37AM +0800, JingPiao Chen wrote:
> * nlattr.h (nla_decoder_t): New typedef.
> (DECL_NLA): New macro.
> (decode_nlattr): Add decoders, size and opaque_data argument.
> * nlattr.c: (decode_nlattr_with_data): Likewise.
> (decode_nla_*): New functions.
> * netlink_sock_diag.c (decode_inet_diag_req_compat)
> (decode_inet_diag_req_v2, decode_inet_diag_msg)
> (decode_netlink_diag_msg, (decode_packet_diag_msg)
> (decode_smc_diag_msg, decode_unix_diag_msg): Add decoders,
> size and opaque_data arguments. All callers updated.
> 
> Co-authored-by: Fabien Siron <fabien.siron at epita.fr>
> ---
>  netlink_sock_diag.c | 21 ++++++++++++------
>  nlattr.c            | 63 +++++++++++++++++++++++++++++++++++++++++++++++++----
>  nlattr.h            | 27 +++++++++++++++++++++--
>  3 files changed, 98 insertions(+), 13 deletions(-)
> 
> diff --git a/netlink_sock_diag.c b/netlink_sock_diag.c
> index f46c441..57c2439 100644
> --- a/netlink_sock_diag.c
> +++ b/netlink_sock_diag.c
> @@ -149,7 +149,8 @@ decode_unix_diag_msg(struct tcb *const tcp,
>  	if (decode_nla && len > offset) {
>  		tprints(", ");
>  		decode_nlattr(tcp, addr + offset, len - offset,
> -			      unix_diag_attrs, "UNIX_DIAG_???");
> +			      unix_diag_attrs, "UNIX_DIAG_???",
> +			      NULL, 0, NULL);
>  	}
>  }
>  
> @@ -238,7 +239,8 @@ decode_netlink_diag_msg(struct tcb *const tcp,
>  	if (decode_nla && len > offset) {
>  		tprints(", ");
>  		decode_nlattr(tcp, addr + offset, len - offset,
> -			      netlink_diag_attrs, "NETLINK_DIAG_???");
> +			      netlink_diag_attrs, "NETLINK_DIAG_???",
> +			      NULL, 0, NULL);
>  	}
>  }
>  
> @@ -309,7 +311,8 @@ decode_packet_diag_msg(struct tcb *const tcp,
>  	if (decode_nla && len > offset) {
>  		tprints(", ");
>  		decode_nlattr(tcp, addr + offset, len - offset,
> -			      packet_diag_attrs, "PACKET_DIAG_???");
> +			      packet_diag_attrs, "PACKET_DIAG_???",
> +			      NULL, 0, NULL);
>  	}
>  }
>  
> @@ -373,7 +376,8 @@ decode_inet_diag_req_compat(struct tcb *const tcp,
>  	if (decode_nla && len > offset) {
>  		tprints(", ");
>  		decode_nlattr(tcp, addr + offset, len - offset,
> -			      inet_diag_req_attrs, "INET_DIAG_REQ_???");
> +			      inet_diag_req_attrs, "INET_DIAG_REQ_???",
> +			      NULL, 0, NULL);
>  	}
>  }
>  
> @@ -417,7 +421,8 @@ decode_inet_diag_req_v2(struct tcb *const tcp,
>  	if (decode_nla && len > offset) {
>  		tprints(", ");
>  		decode_nlattr(tcp, addr + offset, len - offset,
> -			      inet_diag_req_attrs, "INET_DIAG_REQ_???");
> +			      inet_diag_req_attrs, "INET_DIAG_REQ_???",
> +			      NULL, 0, NULL);
>  	}
>  }
>  
> @@ -483,7 +488,8 @@ decode_inet_diag_msg(struct tcb *const tcp,
>  	if (decode_nla && len > offset) {
>  		tprints(", ");
>  		decode_nlattr(tcp, addr + offset, len - offset,
> -			      inet_diag_attrs, "INET_DIAG_???");
> +			      inet_diag_attrs, "INET_DIAG_???",
> +			      NULL, 0, NULL);
>  	}
>  }
>  
> @@ -563,7 +569,8 @@ decode_smc_diag_msg(struct tcb *const tcp,
>  	if (decode_nla && len > offset) {
>  		tprints(", ");
>  		decode_nlattr(tcp, addr + offset, len - offset,
> -			      smc_diag_attrs, "SMC_DIAG_???");
> +			      smc_diag_attrs, "SMC_DIAG_???",
> +			      NULL, 0, NULL);
>  	}
>  }
>  #endif
> diff --git a/nlattr.c b/nlattr.c
> index eaf7e39..daa8261 100644
> --- a/nlattr.c
> +++ b/nlattr.c
> @@ -28,6 +28,7 @@
>   */
>  
>  #include "defs.h"
> +#include "nlattr.h"
>  
>  #include <linux/netlink.h>
>  
> @@ -66,7 +67,10 @@ decode_nlattr_with_data(struct tcb *tcp,
>  			kernel_ulong_t addr,
>  			kernel_ulong_t len,
>  			const struct xlat *const table,
> -			const char *const dflt)
> +			const char *const dflt,
> +			const nla_decoder_t *decoders,
> +			unsigned int size,
> +			void *const opaque_data)
>  {
>  	unsigned int nla_len = nla->nla_len > len ? len : nla->nla_len;
>  
> @@ -77,7 +81,13 @@ decode_nlattr_with_data(struct tcb *tcp,
>  
>  	if (nla_len > NLA_HDRLEN) {
>  		tprints(", ");
> -		printstrn(tcp, addr + NLA_HDRLEN, nla_len - NLA_HDRLEN);
> +		if (!decoders
> +		    || nla->nla_type >= size
> +		    || !decoders[nla->nla_type]
> +		    || !decoders[nla->nla_type](tcp, addr + NLA_HDRLEN,
> +						nla_len - NLA_HDRLEN,
> +						opaque_data))
> +			printstrn(tcp, addr + NLA_HDRLEN, len - NLA_HDRLEN);
>  		tprints("}");
>  	}
>  }
> @@ -87,7 +97,10 @@ decode_nlattr(struct tcb *const tcp,
>  	      kernel_ulong_t addr,
>  	      kernel_ulong_t len,
>  	      const struct xlat *const table,
> -	      const char *const dflt)
> +	      const char *const dflt,
> +	      const nla_decoder_t *decoders,
> +	      unsigned int size,
> +	      void *const opaque_data)
>  {
>  	struct nlattr nla;
>  	bool print_array = false;
> @@ -115,7 +128,8 @@ decode_nlattr(struct tcb *const tcp,
>  			print_array = true;
>  		}
>  
> -		decode_nlattr_with_data(tcp, &nla, addr, len, table, dflt);
> +		decode_nlattr_with_data(tcp, &nla, addr, len, table, dflt,
> +					decoders, size, opaque_data);
>  
>  		if (!next_addr)
>  			break;
> @@ -129,3 +143,44 @@ decode_nlattr(struct tcb *const tcp,
>  		tprints("]");
>  	}
>  }
> +
> +bool
> +decode_nla_str(struct tcb *tcp, kernel_ulong_t addr,
> +	       kernel_ulong_t len, void *const opaque_data)
> +{
> +	printstr(tcp, addr);

I'm afraid this is not correct, "len" should be taken into account, too.
Maybe printstr_ex(tcp, addr, len, QUOTE_0_TERMINATED) or something like this.

> +
> +	return true;
> +}
> +
> +bool
> +decode_nla_strn(struct tcb *tcp, kernel_ulong_t addr,
> +		kernel_ulong_t len, void *const opaque_data)
> +{
> +	printstrn(tcp, addr, len);
> +
> +	return true;
> +}
> +
> +#define DECODE_NLA_INTEGER(name, type, fmt)				\
> +bool									\
> +decode_nla_ ## name(struct tcb *tcp, kernel_ulong_t addr,		\
> +		    kernel_ulong_t len, void *const opaque_data)	\
> +{									\
> +	type num;							\
> +									\
> +	if (len < sizeof(num))						\
> +		return false;						\
> +	else if (!umove_or_printaddr(tcp, addr, &num))			\

No need for "else" after "return".

> +		tprintf(fmt, num);					\
> +	return true;							\
> +}
> +
> +DECODE_NLA_INTEGER(u8, uint8_t, "%" PRIu8)
> +DECODE_NLA_INTEGER(u16, uint16_t, "%" PRIu16)
> +DECODE_NLA_INTEGER(u32, uint32_t, "%" PRIu32)
> +DECODE_NLA_INTEGER(u64, uint64_t, "%" PRIu64)
> +DECODE_NLA_INTEGER(s8, int8_t, "%" PRId8)
> +DECODE_NLA_INTEGER(s16, int16_t, "%" PRId16)
> +DECODE_NLA_INTEGER(s32, int32_t, "%" PRId32)
> +DECODE_NLA_INTEGER(s64, int64_t, "%" PRId64)
> diff --git a/nlattr.h b/nlattr.h
> index 6b94fc1..8501c4d 100644
> --- a/nlattr.h
> +++ b/nlattr.h
> @@ -27,6 +27,29 @@
>   * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
>   */
>  
> +typedef bool (*nla_decoder_t)(struct tcb *, kernel_ulong_t addr,
> +			      kernel_ulong_t len, void *opaque_data);
>  extern void
> -decode_nlattr(struct tcb *, kernel_ulong_t addr, kernel_ulong_t len,
> -	      const struct xlat *, const char *);
> +decode_nlattr(struct tcb *,
> +	      kernel_ulong_t addr,
> +	      kernel_ulong_t len,
> +	      const struct xlat *,
> +	      const char *,
> +	      const nla_decoder_t *,
> +	      unsigned int size,
> +	      void *);
> +
> +#define DECL_NLA(name)					\
> +extern bool						\
> +decode_nla_ ## name(struct tcb *, kernel_ulong_t addr,	\
> +		    kernel_ulong_t len, void *)
> +DECL_NLA(u8);
> +DECL_NLA(u16);
> +DECL_NLA(u32);
> +DECL_NLA(u64);
> +DECL_NLA(s8);
> +DECL_NLA(s16);
> +DECL_NLA(s32);
> +DECL_NLA(s64);
> +DECL_NLA(str);
> +DECL_NLA(strn);

-- 
ldv
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: not available
URL: <http://lists.strace.io/pipermail/strace-devel/attachments/20170620/7edee9dc/attachment.bin>


More information about the Strace-devel mailing list