Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions drivers/net/ppp/pppoe.c
Original file line number Diff line number Diff line change
Expand Up @@ -893,6 +893,7 @@ static int pppoe_sendmsg(struct socket *sock, struct msghdr *m,
dev_hard_header(skb, dev, ETH_P_PPP_SES,
po->pppoe_pa.remote, NULL, total_len);

ph = pppoe_hdr(skb);
memcpy(ph, &hdr, sizeof(struct pppoe_hdr));

ph->length = htons(total_len);
Expand Down
86 changes: 45 additions & 41 deletions drivers/net/tun.c
Original file line number Diff line number Diff line change
Expand Up @@ -1161,11 +1161,16 @@ static netdev_features_t tun_net_fix_features(struct net_device *dev,
static void tun_set_headroom(struct net_device *dev, int new_hr)
{
struct tun_struct *tun = netdev_priv(dev);
size_t max_headroom;

if (new_hr < NET_SKB_PAD)
new_hr = NET_SKB_PAD;
max_headroom = min_t(size_t, SKB_MAX_HEAD(0), U16_MAX - 1);

tun->align = new_hr;
if ((tun->flags & TUN_TYPE_MASK) == IFF_TAP)
max_headroom -= ETH_HLEN + NET_IP_ALIGN;
else
max_headroom -= 1;

tun->align = clamp_t(int, new_hr, NET_SKB_PAD, max_headroom);
}

static void
Expand Down Expand Up @@ -1735,7 +1740,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
u32 rxhash = 0;
int skb_xdp = 1;
bool frags = tun_napi_frags_enabled(tfile);
enum skb_drop_reason drop_reason;
enum skb_drop_reason drop_reason = SKB_DROP_REASON_NOT_SPECIFIED;

if (!(tun->flags & IFF_NO_PI)) {
if (len < sizeof(pi))
Expand Down Expand Up @@ -1796,10 +1801,9 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
* skb was created with generic XDP routine.
*/
skb = tun_build_skb(tun, tfile, from, &gso, len, &skb_xdp);
if (IS_ERR(skb)) {
dev_core_stats_rx_dropped_inc(tun->dev);
return PTR_ERR(skb);
}
err = PTR_ERR_OR_ZERO(skb);
if (err)
goto drop;
if (!skb)
return total_len;
} else {
Expand All @@ -1824,13 +1828,9 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
noblock);
}

if (IS_ERR(skb)) {
if (PTR_ERR(skb) != -EAGAIN)
dev_core_stats_rx_dropped_inc(tun->dev);
if (frags)
mutex_unlock(&tfile->napi_mutex);
return PTR_ERR(skb);
}
err = PTR_ERR_OR_ZERO(skb);
if (err)
goto drop;

if (zerocopy)
err = zerocopy_sg_from_iter(skb, from);
Expand All @@ -1840,33 +1840,26 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
if (err) {
err = -EFAULT;
drop_reason = SKB_DROP_REASON_SKB_UCOPY_FAULT;
drop:
dev_core_stats_rx_dropped_inc(tun->dev);
kfree_skb_reason(skb, drop_reason);
if (frags) {
tfile->napi.skb = NULL;
mutex_unlock(&tfile->napi_mutex);
}

return err;
goto drop;
}
}

if (virtio_net_hdr_to_skb(skb, &gso, tun_is_little_endian(tun))) {
atomic_long_inc(&tun->rx_frame_errors);
kfree_skb(skb);
if (frags) {
tfile->napi.skb = NULL;
mutex_unlock(&tfile->napi_mutex);
}

return -EINVAL;
err = -EINVAL;
goto free_skb;
}

switch (tun->flags & TUN_TYPE_MASK) {
case IFF_TUN:
if (tun->flags & IFF_NO_PI) {
u8 ip_version = skb->len ? (skb->data[0] >> 4) : 0;
u8 ip_version;

if (!pskb_may_pull(skb, 1)) {
err = -EINVAL;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to define a drop_reason before the goto drop;, otherwise drop_reason is passed undefined to kfree_skb_reason.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch the 8.6 had the same but doesn't have the drop_reason ..
I chose to backport the precondition commit as it cleans up this jumping around awkwardly

goto drop;
}
ip_version = skb->data[0] >> 4;

switch (ip_version) {
case 4:
Expand All @@ -1876,9 +1869,8 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
pi.proto = htons(ETH_P_IPV6);
break;
default:
dev_core_stats_rx_dropped_inc(tun->dev);
kfree_skb(skb);
return -EINVAL;
err = -EINVAL;
goto drop;
}
}

Expand All @@ -1887,7 +1879,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
skb->dev = tun->dev;
break;
case IFF_TAP:
if (frags && !pskb_may_pull(skb, ETH_HLEN)) {
if (!pskb_may_pull(skb, ETH_HLEN)) {
err = -ENOMEM;
drop_reason = SKB_DROP_REASON_HDR_TRUNC;
goto drop;
Expand Down Expand Up @@ -1920,11 +1912,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
if (ret != XDP_PASS) {
rcu_read_unlock();
local_bh_enable();
if (frags) {
tfile->napi.skb = NULL;
mutex_unlock(&tfile->napi_mutex);
}
return total_len;
goto unlock_frags;
}
}
rcu_read_unlock();
Expand Down Expand Up @@ -1996,6 +1984,22 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
tun_flow_update(tun, rxhash, tfile);

return total_len;

drop:
if (err != -EAGAIN)
dev_core_stats_rx_dropped_inc(tun->dev);

free_skb:
if (!IS_ERR_OR_NULL(skb))
kfree_skb_reason(skb, drop_reason);

unlock_frags:
if (frags) {
tfile->napi.skb = NULL;
mutex_unlock(&tfile->napi_mutex);
}

return err ?: total_len;
}

static ssize_t tun_chr_write_iter(struct kiocb *iocb, struct iov_iter *from)
Expand Down
29 changes: 18 additions & 11 deletions net/ipv6/ah6.c
Original file line number Diff line number Diff line change
Expand Up @@ -210,26 +210,28 @@ static void ipv6_rearrange_destopt(struct ipv6hdr *iph, struct ipv6_opt_hdr *des
* Rearrange the destination address in @iph and the addresses in @rthdr
* so that they appear in the order they will at the final destination.
* See Appendix A2 of RFC 2402 for details.
*
* Return: 0 on success, -EINVAL if segments_left exceeds the number of
* addresses described by hdrlen.
*/
static void ipv6_rearrange_rthdr(struct ipv6hdr *iph, struct ipv6_rt_hdr *rthdr)
static int ipv6_rearrange_rthdr(struct ipv6hdr *iph, struct ipv6_rt_hdr *rthdr)
{
int segments, segments_left;
unsigned int segments, segments_left;
struct in6_addr *addrs;
struct in6_addr final_addr;

segments_left = rthdr->segments_left;
if (segments_left == 0)
return;
rthdr->segments_left = 0;
return 0;

/* The value of rthdr->hdrlen has been verified either by the system
* call if it is locally generated, or by ipv6_rthdr_rcv() for incoming
* packets. So we can assume that it is even and that segments is
* greater than or equal to segments_left.
*
* For the same reason we can assume that this option is of type 0.
/* Raw locally generated packets can reach AH6 without the invariant
* required by the rt0-style address rearrangement below.
*/
segments = rthdr->hdrlen >> 1;
if (segments_left > segments)
return -EINVAL;

rthdr->segments_left = 0;

addrs = ((struct rt0_hdr *)rthdr)->addr;
final_addr = addrs[segments - 1];
Expand All @@ -239,6 +241,8 @@ static void ipv6_rearrange_rthdr(struct ipv6hdr *iph, struct ipv6_rt_hdr *rthdr)

addrs[0] = iph->daddr;
iph->daddr = final_addr;

return 0;
}

static int ipv6_clear_mutable_options(struct ipv6hdr *iph, int len, int dir)
Expand All @@ -251,6 +255,7 @@ static int ipv6_clear_mutable_options(struct ipv6hdr *iph, int len, int dir)
} exthdr = { .iph = iph };
char *end = exthdr.raw + len;
int nexthdr = iph->nexthdr;
int err;

exthdr.iph++;

Expand All @@ -270,7 +275,9 @@ static int ipv6_clear_mutable_options(struct ipv6hdr *iph, int len, int dir)
break;

case NEXTHDR_ROUTING:
ipv6_rearrange_rthdr(iph, exthdr.rth);
err = ipv6_rearrange_rthdr(iph, exthdr.rth);
if (err)
return err;
break;

default:
Expand Down
3 changes: 3 additions & 0 deletions net/sctp/associola.c
Original file line number Diff line number Diff line change
Expand Up @@ -615,6 +615,9 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
return peer;
}

if (asoc->peer.transport_count == U16_MAX)
return NULL;

peer = sctp_transport_new(asoc->base.net, addr, gfp);
if (!peer)
return NULL;
Expand Down
Loading