skbuff: Extend gso_type to unsigned int.
authorSteffen Klassert <steffen.klassert@secunet.com>
Sat, 8 Apr 2017 18:36:24 +0000 (20:36 +0200)
committerDavid S. Miller <davem@davemloft.net>
Sat, 8 Apr 2017 19:32:07 +0000 (12:32 -0700)
commit7f564528a480084e2318cd48caba7aef4a54a77f
tree5447b2e2ae1f0d4ae3772c2743fb000587ea9a61
parent0c264588b5de50353e4a1ce0c2521576426dd89d
skbuff: Extend gso_type to unsigned int.

All available gso_type flags are currently in use, so
extend gso_type from 'unsigned short' to 'unsigned int'
to be able to add further flags.

We reorder the struct skb_shared_info to use
two bytes of the four byte hole before dataref.
All fields before dataref are cleared, i.e.
four bytes more than before the change.

The remaining two byte hole is moved to the
beginning of the structure, this protects us
from immediate overwites on out of bound writes
to the sk_buff head.

Structure layout on x86-64 before the change:

struct skb_shared_info {
unsigned char              nr_frags;             /*     0     1 */
__u8                       tx_flags;             /*     1     1 */
short unsigned int         gso_size;             /*     2     2 */
short unsigned int         gso_segs;             /*     4     2 */
short unsigned int         gso_type;             /*     6     2 */
struct sk_buff *           frag_list;            /*     8     8 */
struct skb_shared_hwtstamps hwtstamps;           /*    16     8 */
u32                        tskey;                /*    24     4 */
__be32                     ip6_frag_id;          /*    28     4 */
atomic_t                   dataref;              /*    32     4 */

/* XXX 4 bytes hole, try to pack */

void *                     destructor_arg;       /*    40     8 */
skb_frag_t                 frags[17];            /*    48   272 */
/* --- cacheline 5 boundary (320 bytes) --- */

/* size: 320, cachelines: 5, members: 12 */
/* sum members: 316, holes: 1, sum holes: 4 */
};

Structure layout on x86-64 after the change:

struct skb_shared_info {
short unsigned int         _unused;              /*     0     2 */
unsigned char              nr_frags;             /*     2     1 */
__u8                       tx_flags;             /*     3     1 */
short unsigned int         gso_size;             /*     4     2 */
short unsigned int         gso_segs;             /*     6     2 */
struct sk_buff *           frag_list;            /*     8     8 */
struct skb_shared_hwtstamps hwtstamps;           /*    16     8 */
unsigned int               gso_type;             /*    24     4 */
u32                        tskey;                /*    28     4 */
__be32                     ip6_frag_id;          /*    32     4 */
atomic_t                   dataref;              /*    36     4 */
void *                     destructor_arg;       /*    40     8 */
skb_frag_t                 frags[17];            /*    48   272 */
/* --- cacheline 5 boundary (320 bytes) --- */

/* size: 320, cachelines: 5, members: 13 */
};

Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
Acked-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/linux/skbuff.h