In tcpdump, we have generally used the "extract" approach rather
than __packed, for various reasons including potential encapculation
cases where compiler generated code has been insufficiently cynical --
meaning, __packed doesn't mean "must access everything as bytes".

Visa Hankala <v...@hankala.org> wrote:

> On Tue, May 04, 2021 at 07:29:20AM +0200, Peter J. Philipp wrote:
> > > Index: print-wg.c
> > > ===================================================================
> > > RCS file: /cvs/src/usr.sbin/tcpdump/print-wg.c,v
> > > retrieving revision 1.6
> > > diff -u -p -u -r1.6 print-wg.c
> > > --- print-wg.c    14 Apr 2021 19:34:56 -0000      1.6
> > > +++ print-wg.c    3 May 2021 16:29:29 -0000
> > > @@ -21,6 +21,7 @@
> > >  
> > >  #include <stdio.h>
> > >  #include <stddef.h>
> > > +#include <string.h>
> > >  
> > >  #include "interface.h"
> > >  #include "extract.h"
> > > @@ -104,6 +105,9 @@ wg_print(const u_char *bp, u_int length)
> > >   struct wg_data          *data = (void *)bp;
> > >   u_int                    caplen;
> > >  
> > > + uint32_t                receiver;
> > > + uint64_t                nonce;
> > > +
> > >   caplen = snapend - bp;
> > >   if (caplen < sizeof(type))
> > >           goto trunc;
> > > @@ -142,8 +146,12 @@ wg_print(const u_char *bp, u_int length)
> > >                   printf("[wg] keepalive ");
> > >           if (caplen < offsetof(struct wg_data, mac))
> > >                   goto trunc;
> > > +
> > > +         memcpy((void *)&receiver, (void *)&data->receiver, 
> > > sizeof(receiver));
> > > +         memcpy((void *)&nonce, (void *)&data->nonce, sizeof(nonce));
> > > +
> > >           printf("to 0x%08x nonce %llu",
> > > -             letoh32(data->receiver), letoh64(data->nonce));
> > > +             letoh32(receiver), letoh64(nonce));
> > >           break;
> > >   }
> > >   return;
> > > 
> > > 
> > > There may be other variables that need the same treatment... if that 
> > > looks ok
> > > for you I'll work on that and submit the patch formally.
> > 
> > I dumped with this patch for about an hour, and even restarted the wg tunnel
> > on the device behind vlan6 so that other types get used (initialization) and
> > I found that there was no more SIGBUS's for tcpdump on octeon, so I am 
> > unsure
> > if other variables actually do need same treatment still.
> 
> data->nonce is the (most) offending variable because it needs 8-byte
> alignment.
> 
> An alternative to memcpy() is to use tcpdump's EXTRACT_* macros that
> handle unaligned data.
> 
> Yet another option is to declare the structs with the "packed" type
> attribute. This makes the compiler emit machine code that is safe with
> unaligned data. This also enables type checking that is better than with
> EXTRACT_* because types are not overridden with explicit type casts.
> However, "packed" makes it non obvious that unaligned accesses
> may happen.
> 
> Index: print-wg.c
> ===================================================================
> RCS file: src/usr.sbin/tcpdump/print-wg.c,v
> retrieving revision 1.6
> diff -u -p -r1.6 print-wg.c
> --- print-wg.c        14 Apr 2021 19:34:56 -0000      1.6
> +++ print-wg.c        14 Sep 2021 12:42:32 -0000
> @@ -34,20 +34,20 @@ struct wg_initiation {
>       uint32_t        type;
>       uint32_t        sender;
>       uint8_t         fill[140]; /* Includes ephemeral + MAC */
> -};
> +} __packed;
>  
>  struct wg_response {
>       uint32_t        type;
>       uint32_t        sender;
>       uint32_t        receiver;
>       uint8_t         fill[80]; /* Includes ephemeral + MAC */
> -};
> +} __packed;
>  
>  struct wg_cookie {
>       uint32_t        type;
>       uint32_t        receiver;
>       uint8_t         fill[56]; /* Includes nonce + encrypted cookie */
> -};
> +} __packed;
>  
>  struct wg_data {
>       uint32_t        type;
> @@ -55,7 +55,7 @@ struct wg_data {
>       uint64_t        nonce;
>       /* uint8_t      data[variable]; - Variable length data */
>       uint8_t         mac[16];
> -};
> +} __packed;
>  
>  /*
>   * Check if packet is a WireGuard packet, as WireGuard may run on any port.
> 

Reply via email to