[PATCH v8 3/4] Netlink: handle multi netlink messages

Dmitry V. Levin ldv at altlinux.org
Mon Jul 4 22:14:40 UTC 2016


On Wed, Jun 29, 2016 at 12:20:00PM +0000, Fabien Siron wrote:
> +static unsigned long
> +next_nlmsg(struct nlmsghdr *nlmsghdr, unsigned long addr, unsigned long *len) {
> +	if (NLMSG_ALIGN(nlmsghdr->nlmsg_len) == 0 ||
> +	    NLMSG_ALIGN(nlmsghdr->nlmsg_len) > *len) {
> +		*len = NLMSG_ALIGN(nlmsghdr->nlmsg_len);
> +		return 0;
> +	}

*len may increase as result

> +	*len -= NLMSG_ALIGN(nlmsghdr->nlmsg_len);
> +
> +	if (addr + NLMSG_ALIGN(nlmsghdr->nlmsg_len) > addr) {
> +		return addr + NLMSG_ALIGN(nlmsghdr->nlmsg_len);
> +	} else {
> +		*len = 0;
> +		return 0;
> +	}
> +}

Could it be written in a more clear and robust way?  For example,

unsigned long nlmsg_len = NLMSG_ALIGN(nlmsghdr->nlmsg_len);

if (nlmsg_len < sizeof(struct nlmsghdr)) {
	addr = 0;
	nlmsg_len = sizeof(struct nlmsghdr);
}

if (*len >= nlmsg_len)
	*len -= nlmsg_len;
else
	*len = 0;

if (addr && addr + nlmsg_len > addr)
	return addr + nlmsg_len;
else
	return 0;

> +static void
> +decode_netlink_msg(struct tcb *tcp, struct nlmsghdr *nlmsghdr,
> +		   unsigned long addr, unsigned long size)
> +{
>  	if (size < sizeof(struct nlmsghdr)) {
>  		printstr(tcp, addr, size);
>  		return;
>  	}
> -	if (umove_or_printaddr(tcp, addr, &nlmsghdr))
> -		return;
>  
> -	tprintf("{{len=%u, type=", nlmsghdr.nlmsg_len);
> +	tprintf("{{len=%u, type=", nlmsghdr->nlmsg_len);
>  
> -	printxval(netlink_types, nlmsghdr.nlmsg_type, "NLMSG_???");
> +	printxval(netlink_types, nlmsghdr->nlmsg_type, "NLMSG_???");
>  
>  	tprints(", flags=");
> -	printflags(netlink_flags, nlmsghdr.nlmsg_flags, "NLM_F_???");
> +	printflags(netlink_flags, nlmsghdr->nlmsg_flags, "NLM_F_???");
>  	/* manage get/new requests */
>  
> -	tprintf(", seq=%u, pid=%u}", nlmsghdr.nlmsg_seq,
> -		nlmsghdr.nlmsg_pid);
> +	tprintf(", seq=%u, pid=%u}", nlmsghdr->nlmsg_seq,
> +		nlmsghdr->nlmsg_pid);
>  
> -	if (size - sizeof(struct nlmsghdr) > 0) {
> +	if (nlmsghdr->nlmsg_len - sizeof(struct nlmsghdr) > 0) {
>  		tprints(", ");
> +
>  		printstr(tcp, addr + sizeof(struct nlmsghdr),
> -			 size - sizeof(struct nlmsghdr));
> +			 nlmsghdr->nlmsg_len - sizeof(struct nlmsghdr));
>  	}
>  
>  	tprints("}");
>  }
> +
> +void
> +decode_netlink(struct tcb *tcp, unsigned long addr, unsigned long total_size) {
> +	struct nlmsghdr nlmsghdr;
> +	unsigned long elt, size = total_size;
> +	int print_array = 0;
> +
> +	for (elt = 0; fetch_nlmsg(tcp, &nlmsghdr, addr, size);
> +	     addr = next_nlmsg(&nlmsghdr, addr, &size), elt++) {
> +		if (elt == max_strlen && abbrev(tcp)) {
> +			tprints("...");
> +			break;
> +		}
> +		if (nlmsghdr.nlmsg_len < sizeof(struct nlmsghdr))
> +			break;

This edition of decode_netlink will print nothing if addr == NULL,
or if the first nlmsghdr.nlmsg_len < sizeof(struct nlmsghdr).

Please add to the test all pathological cases we discussed so far.


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


More information about the Strace-devel mailing list