Commit 0ddaa278 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'net-skb_put_padto-fixes'



Eric Dumazet says:

====================
net: skb_put_padto() fixes

sysbot reported a bug in qrtr leading to use-after-free.

First patch fixes the issue.

Second patch addes __must_check attribute to avoid similar
issues in the future.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents ba9e04a7 4a009cb0
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -3223,7 +3223,8 @@ static inline int skb_padto(struct sk_buff *skb, unsigned int len)
 *	is untouched. Otherwise it is extended. Returns zero on
 *	success. The skb is freed on error if @free_on_error is true.
 */
static inline int __skb_put_padto(struct sk_buff *skb, unsigned int len,
static inline int __must_check __skb_put_padto(struct sk_buff *skb,
					       unsigned int len,
					       bool free_on_error)
{
	unsigned int size = skb->len;
@@ -3247,7 +3248,7 @@ static inline int __skb_put_padto(struct sk_buff *skb, unsigned int len,
 *	is untouched. Otherwise it is extended. Returns zero on
 *	success. The skb is freed on error.
 */
static inline int skb_put_padto(struct sk_buff *skb, unsigned int len)
static inline int __must_check skb_put_padto(struct sk_buff *skb, unsigned int len)
{
	return __skb_put_padto(skb, len, true);
}
+11 −10
Original line number Diff line number Diff line
@@ -332,8 +332,7 @@ static int qrtr_node_enqueue(struct qrtr_node *node, struct sk_buff *skb,
{
	struct qrtr_hdr_v1 *hdr;
	size_t len = skb->len;
	int rc = -ENODEV;
	int confirm_rx;
	int rc, confirm_rx;

	confirm_rx = qrtr_tx_wait(node, to->sq_node, to->sq_port, type);
	if (confirm_rx < 0) {
@@ -357,15 +356,17 @@ static int qrtr_node_enqueue(struct qrtr_node *node, struct sk_buff *skb,
	hdr->size = cpu_to_le32(len);
	hdr->confirm_rx = !!confirm_rx;

	skb_put_padto(skb, ALIGN(len, 4) + sizeof(*hdr));
	rc = skb_put_padto(skb, ALIGN(len, 4) + sizeof(*hdr));

	if (!rc) {
		mutex_lock(&node->ep_lock);
		rc = -ENODEV;
		if (node->ep)
			rc = node->ep->xmit(node->ep, skb);
		else
			kfree_skb(skb);
		mutex_unlock(&node->ep_lock);

	}
	/* Need to ensure that a subsequent message carries the otherwise lost
	 * confirm_rx flag if we dropped this one */
	if (rc && confirm_rx)