Skip to content
  • Liping Zhang's avatar
    netfilter: nf_tables: fix mismatch in big-endian system · 10596608
    Liping Zhang authored
    
    
    Currently, there are two different methods to store an u16 integer to
    the u32 data register. For example:
      u32 *dest = &regs->data[priv->dreg];
      1. *dest = 0; *(u16 *) dest = val_u16;
      2. *dest = val_u16;
    
    For method 1, the u16 value will be stored like this, either in
    big-endian or little-endian system:
      0          15           31
      +-+-+-+-+-+-+-+-+-+-+-+-+
      |   Value   |     0     |
      +-+-+-+-+-+-+-+-+-+-+-+-+
    
    For method 2, in little-endian system, the u16 value will be the same
    as listed above. But in big-endian system, the u16 value will be stored
    like this:
      0          15           31
      +-+-+-+-+-+-+-+-+-+-+-+-+
      |     0     |   Value   |
      +-+-+-+-+-+-+-+-+-+-+-+-+
    
    So later we use "memcmp(&regs->data[priv->sreg], data, 2);" to do
    compare in nft_cmp, nft_lookup expr ..., method 2 will get the wrong
    result in big-endian system, as 0~15 bits will always be zero.
    
    For the similar reason, when loading an u16 value from the u32 data
    register, we should use "*(u16 *) sreg;" instead of "(u16)*sreg;",
    the 2nd method will get the wrong value in the big-endian system.
    
    So introduce some wrapper functions to store/load an u8 or u16
    integer to/from the u32 data register, and use them in the right
    place.
    
    Signed-off-by: default avatarLiping Zhang <zlpnobody@gmail.com>
    Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
    10596608