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

Fabien Siron fabien.siron at epita.fr
Tue Jul 5 12:03:53 UTC 2016


Quoting Dmitry V. Levin (2016-07-04 22:14:40)
> 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;

Done.

> > +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).

What should be printed in these cases?

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

So let's add a test where nlmsghdr->nlmsg_len is 0 and a test with
nlmsghdr->nlmsg_len is greater than len. Do you have other pathological cases
in mind?

Cheers,
--
Fabien Siron




More information about the Strace-devel mailing list