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 @@ -905,6 +905,7 @@ static int pppoe_sendmsg(struct kiocb *iocb, struct socket *sock,
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
27 changes: 23 additions & 4 deletions drivers/net/tun.c
Original file line number Diff line number Diff line change
Expand Up @@ -978,11 +978,16 @@ static void tun_poll_controller(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 int tun_net_change_carrier(struct net_device *dev, bool new_carrier)
Expand Down Expand Up @@ -1399,7 +1404,16 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
switch (tun->flags & TUN_TYPE_MASK) {
case IFF_TUN:
if (tun->flags & IFF_NO_PI) {
switch (skb->data[0] & 0xf0) {
u8 ip_version;

if (!pskb_may_pull(skb, 1)) {
this_cpu_inc(tun->pcpu_stats->rx_dropped);
kfree_skb(skb);
return -EINVAL;
}
ip_version = skb->data[0] & 0xf0;

switch (ip_version) {
case 0x40:
pi.proto = htons(ETH_P_IP);
break;
Expand All @@ -1418,6 +1432,11 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
skb->dev = tun->dev;
break;
case IFF_TAP:
if (!pskb_may_pull(skb, ETH_HLEN)) {
this_cpu_inc(tun->pcpu_stats->rx_dropped);
kfree_skb(skb);
return -ENOMEM;
}
skb->protocol = eth_type_trans(skb, tun->dev);
break;
}
Expand Down
29 changes: 18 additions & 11 deletions net/ipv6/ah6.c
Original file line number Diff line number Diff line change
Expand Up @@ -222,26 +222,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 @@ -251,6 +253,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 @@ -263,6 +267,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 @@ -282,7 +287,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 @@ -623,6 +623,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(net, addr, gfp);
if (!peer)
return NULL;
Expand Down
Loading