[PATCH] netlink: add type decoding

Dmitry V. Levin ldv at altlinux.org
Sun Jun 4 19:40:09 UTC 2017


On Mon, Jul 11, 2016 at 12:54:59PM +0000, Fabien Siron wrote:
> Decode and print the type of the main netlink protocols.

JingPiao Chen, I've reworked Fabien's commits from your netlink branch
up to and including this one (52dc63cc "netlink: add type decoding")
for merge into master.  I've pushed them to ldv/netlink branch
and now waiting for a new version of your
"tests: add check for nlmsg_type decoding" commit to test these changes.

A few notes about Fabien's code that might be useful for your netlink efforts:

> @@ -96,7 +96,8 @@ print_iovec(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data)
>  				len = c->data_size;
>  			if (c->data_size != (kernel_ulong_t) -1)
>  				c->data_size -= len;
> -			decode_netlink(tcp, iov[0], len);
> +			decode_netlink(tcp, *(int *)c->optional_data,
> +				       iov[0], len);
>  			break;
>  		default:
>  			printaddr(iov[0]);
> @@ -354,7 +354,7 @@ print_struct_msghdr(struct tcb *tcp, const struct msghdr *msg,
>  	tprints(", msg_iov=");
>  
>  	tprint_iov_upto(tcp, msg->msg_iovlen, ptr_to_kulong(msg->msg_iov),
> -			decode, data_size, NULL);
> +			decode, data_size, &tcp->u_arg[0]);
>  	tprintf(", msg_iovlen=%" PRI_klu, (kernel_ulong_t) msg->msg_iovlen);
>  
>  	decode_msg_control(tcp, ptr_to_kulong(msg->msg_control),

If sizeof(tcp->u_arg[0]) > sizeof(int), a wrong value will be passed to decode_netlink.

> @@ -29,9 +29,23 @@
>  
>  #include "defs.h"
>  #include <sys/socket.h>
> +#include <linux/audit.h>
> +#include <linux/inet_diag.h>
> +#include <linux/netfilter/nfnetlink.h>

linux/netfilter/nfnetlink.h was introduced in 2.6.14

> @@ -55,13 +69,62 @@ fetch_nlmsghdr(struct tcb *const tcp, struct nlmsghdr *const nlmsghdr,
>  }
>  
>  static void
> -print_nlmsghdr(struct tcb *tcp, const struct nlmsghdr *const nlmsghdr)
> +decode_netlink_type(int type, int proto)
> +{
> +	if (type < NLMSG_MIN_TYPE) {
> +		printxval(netlink_types, type, "NLMSG_???");
> +	} else {
> +		const struct xlat *x;
> +		const char *dflt;
> +
> +		switch (proto) {
> +		case NETLINK_ROUTE:
> +			x = netlink_route_types;
> +			dflt = "RTM_???";
> +			break;
> +		case NETLINK_SOCK_DIAG:
> +			x = netlink_sock_diag_types;
> +			dflt = "SOCK_DIAG_???";
> +			break;
> +		case NETLINK_XFRM:
> +			x = netlink_xfrm_types;
> +			dflt = "XFRM_MSG_???";
> +			break;
> +		case NETLINK_AUDIT:
> +			x = netlink_audit_types;
> +			dflt = "AUDIT_???";
> +			break;
> +		case NETLINK_SELINUX:
> +			x = netlink_selinux_types;
> +			dflt = "SELNL_MSG_???";
> +			break;
> +		case NETLINK_NETFILTER:
> +			x = netlink_netfilter_ids;
> +			dflt = "NFNL_SUBSYS_???";
> +			break;
> +		default:
> +			x = netlink_types;
> +			dflt = "NLMSG_???";
> +		}
> +		if (proto == NETLINK_NETFILTER) {
> +			tprints("{");
> +			printxval(x, NFNL_SUBSYS_ID(type), dflt);
> +			tprintf(", %d}", NFNL_MSG_TYPE(type));
> +		} else {
> +			printxval(x, type, dflt);
> +		}
> +	}
> +}

Too much cut-n-paste in this switch statement.
I transformed it into a table:

static const struct {
	const struct xlat *const xlat;
	const char *const dflt;
} nlmsg_types[] = {
	[NETLINK_AUDIT] = { nl_audit_types, "AUDIT_???" },
	[NETLINK_ROUTE] = { nl_route_types, "RTM_???" },
	[NETLINK_SELINUX] = { nl_selinux_types, "SELNL_MSG_???" },
	[NETLINK_SOCK_DIAG] = { nl_sock_diag_types, "SOCK_DIAG_???" },
	[NETLINK_XFRM] = { nl_xfrm_types, "XFRM_MSG_???" }
};

if (family < ARRAY_SIZE(nlmsg_types)
    && nlmsg_types[family].xlat) {
	printxval(nlmsg_types[family].xlat, type, nlmsg_types[family].dflt);
} else {
	printxval(netlink_types, type, "NLMSG_???");
}

Well, not exactly into this because NETLINK_NETFILTER message types are not as
simple (even more complex than Fabien thought when he wrote this code).

> @@ -132,20 +196,21 @@ decode_payload(struct tcb *const tcp,
>  }
>  
>  static void
> -decode_nlmsghdr_with_payload(struct tcb *const tcp,
> +decode_nlmsghdr_with_payload(struct tcb *const tcp, int fd,
>  			     const struct nlmsghdr *const nlmsghdr,
>  			     const kernel_ulong_t addr,
>  			     const kernel_ulong_t len)
>  {
>  	tprints("{");
>  
> -	print_nlmsghdr(tcp, nlmsghdr);
> +	int proto = getfdnlproto(tcp, fd, netlink_protocols);
> +	print_nlmsghdr(tcp, nlmsghdr, proto);

getfdnlproto (get_fd_nl_family in my edition) is not cheap
(it invokes syscalls), needless calls should be avoided.


-- 
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/20170604/c5e7bbd2/attachment.bin>


More information about the Strace-devel mailing list