Skip to content

Commit

Permalink
net/tls: fully initialize the msg wrapper skb
Browse files Browse the repository at this point in the history
If strparser gets cornered into starting a new message from
an sk_buff which already has frags, it will allocate a new
skb to become the "wrapper" around the fragments of the
message.

This new skb does not inherit any metadata fields.  In case
of TLS offload this may lead to unnecessarily re-encrypting
the message, as skb->decrypted is not set for the wrapper skb.

Try to be conservative and copy all fields of old skb
strparser's user may reasonably need.

Signed-off-by: Jakub Kicinski <[email protected]>
Reviewed-by: Dirk van der Merwe <[email protected]>
Reviewed-by: Simon Horman <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
Jakub Kicinski authored and davem330 committed Jun 4, 2019
1 parent 7e7d199 commit da29e4b
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 6 deletions.
1 change: 1 addition & 0 deletions include/linux/skbuff.h
Original file line number Diff line number Diff line change
Expand Up @@ -1063,6 +1063,7 @@ struct sk_buff *alloc_skb_with_frags(unsigned long header_len,
int max_page_order,
int *errcode,
gfp_t gfp_mask);
struct sk_buff *alloc_skb_for_msg(struct sk_buff *first);

/* Layout of fast clones : [skb1][skb2][fclone_ref] */
struct sk_buff_fclones {
Expand Down
25 changes: 25 additions & 0 deletions net/core/skbuff.c
Original file line number Diff line number Diff line change
Expand Up @@ -913,6 +913,31 @@ static struct sk_buff *__skb_clone(struct sk_buff *n, struct sk_buff *skb)
#undef C
}

/**
* alloc_skb_for_msg() - allocate sk_buff to wrap frag list forming a msg
* @first: first sk_buff of the msg
*/
struct sk_buff *alloc_skb_for_msg(struct sk_buff *first)
{
struct sk_buff *n;

n = alloc_skb(0, GFP_ATOMIC);
if (!n)
return NULL;

n->len = first->len;
n->data_len = first->len;
n->truesize = first->truesize;

skb_shinfo(n)->frag_list = first;

__copy_skb_header(n, first);
n->destructor = NULL;

return n;
}
EXPORT_SYMBOL_GPL(alloc_skb_for_msg);

/**
* skb_morph - morph one skb into another
* @dst: the skb to receive the contents
Expand Down
8 changes: 2 additions & 6 deletions net/strparser/strparser.c
Original file line number Diff line number Diff line change
Expand Up @@ -160,18 +160,14 @@ static int __strp_recv(read_descriptor_t *desc, struct sk_buff *orig_skb,
return 0;
}

skb = alloc_skb(0, GFP_ATOMIC);
skb = alloc_skb_for_msg(head);
if (!skb) {
STRP_STATS_INCR(strp->stats.mem_fail);
desc->error = -ENOMEM;
return 0;
}
skb->len = head->len;
skb->data_len = head->len;
skb->truesize = head->truesize;
*_strp_msg(skb) = *_strp_msg(head);

strp->skb_nextp = &head->next;
skb_shinfo(skb)->frag_list = head;
strp->skb_head = skb;
head = skb;
} else {
Expand Down

0 comments on commit da29e4b

Please sign in to comment.