diff options
-rw-r--r-- | include/net/ipv6.h | 2 | ||||
-rw-r--r-- | net/core/filter.c | 5 | ||||
-rw-r--r-- | net/ipv4/ipcomp.c | 7 | ||||
-rw-r--r-- | net/ipv4/tcp_output.c | 4 | ||||
-rw-r--r-- | net/ipv6/exthdrs.c | 16 | ||||
-rw-r--r-- | net/ipv6/ip6_input.c | 3 | ||||
-rw-r--r-- | net/ipv6/xfrm6_policy.c | 8 | ||||
-rw-r--r-- | net/tipc/name_distr.c | 3 |
8 files changed, 30 insertions, 18 deletions
diff --git a/include/net/ipv6.h b/include/net/ipv6.h index 6d6f0634ae4..4abedb8eaec 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -230,7 +230,7 @@ extern int ip6_ra_control(struct sock *sk, int sel, void (*destructor)(struct sock *)); -extern int ipv6_parse_hopopts(struct sk_buff *skb, int); +extern int ipv6_parse_hopopts(struct sk_buff *skb); extern struct ipv6_txoptions * ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt); extern struct ipv6_txoptions * ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt, diff --git a/net/core/filter.c b/net/core/filter.c index 93fbd01d225..5b4486a60cf 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -34,6 +34,7 @@ #include <linux/timer.h> #include <asm/system.h> #include <asm/uaccess.h> +#include <asm/unaligned.h> #include <linux/filter.h> /* No hurry in this branch */ @@ -177,7 +178,7 @@ unsigned int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int load_w: ptr = load_pointer(skb, k, 4, &tmp); if (ptr != NULL) { - A = ntohl(*(u32 *)ptr); + A = ntohl(get_unaligned((u32 *)ptr)); continue; } break; @@ -186,7 +187,7 @@ load_w: load_h: ptr = load_pointer(skb, k, 2, &tmp); if (ptr != NULL) { - A = ntohs(*(u16 *)ptr); + A = ntohs(get_unaligned((u16 *)ptr)); continue; } break; diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c index 04a42946566..cd810f41af1 100644 --- a/net/ipv4/ipcomp.c +++ b/net/ipv4/ipcomp.c @@ -290,11 +290,8 @@ static void ipcomp_free_scratches(void) if (!scratches) return; - for_each_possible_cpu(i) { - void *scratch = *per_cpu_ptr(scratches, i); - if (scratch) - vfree(scratch); - } + for_each_possible_cpu(i) + vfree(*per_cpu_ptr(scratches, i)); free_percpu(scratches); } diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index b871db6adc5..44df1db726a 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -551,7 +551,9 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss buff = sk_stream_alloc_skb(sk, nsize, GFP_ATOMIC); if (buff == NULL) return -ENOMEM; /* We'll just try again later. */ - sk_charge_skb(sk, buff); + + buff->truesize = skb->len - len; + skb->truesize -= buff->truesize; /* Correct the sequence numbers. */ TCP_SKB_CB(buff)->seq = TCP_SKB_CB(skb)->seq + len; diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index 2a1e7e45b89..a18d4256372 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c @@ -485,15 +485,27 @@ static struct tlvtype_proc tlvprochopopt_lst[] = { { -1, } }; -int ipv6_parse_hopopts(struct sk_buff *skb, int nhoff) +int ipv6_parse_hopopts(struct sk_buff *skb) { struct inet6_skb_parm *opt = IP6CB(skb); + /* + * skb->nh.raw is equal to skb->data, and + * skb->h.raw - skb->nh.raw is always equal to + * sizeof(struct ipv6hdr) by definition of + * hop-by-hop options. + */ + if (!pskb_may_pull(skb, sizeof(struct ipv6hdr) + 8) || + !pskb_may_pull(skb, sizeof(struct ipv6hdr) + ((skb->h.raw[1] + 1) << 3))) { + kfree_skb(skb); + return -1; + } + opt->hop = sizeof(struct ipv6hdr); if (ip6_parse_tlv(tlvprochopopt_lst, skb)) { skb->h.raw += (skb->h.raw[1]+1)<<3; opt->nhoff = sizeof(struct ipv6hdr); - return sizeof(struct ipv6hdr); + return 1; } return -1; } diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index 29f73592e68..aceee252503 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c @@ -114,11 +114,10 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt } if (hdr->nexthdr == NEXTHDR_HOP) { - if (ipv6_parse_hopopts(skb, IP6CB(skb)->nhoff) < 0) { + if (ipv6_parse_hopopts(skb) < 0) { IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); return 0; } - hdr = skb->nh.ipv6h; } return NF_HOOK(PF_INET6,NF_IP6_PRE_ROUTING, skb, dev, NULL, ip6_rcv_finish); diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index 91cce8b2d7a..88c840f1beb 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c @@ -191,16 +191,18 @@ error: static inline void _decode_session6(struct sk_buff *skb, struct flowi *fl) { - u16 offset = sizeof(struct ipv6hdr); + u16 offset = skb->h.raw - skb->nh.raw; struct ipv6hdr *hdr = skb->nh.ipv6h; - struct ipv6_opt_hdr *exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset); - u8 nexthdr = skb->nh.ipv6h->nexthdr; + struct ipv6_opt_hdr *exthdr; + u8 nexthdr = skb->nh.raw[IP6CB(skb)->nhoff]; memset(fl, 0, sizeof(struct flowi)); ipv6_addr_copy(&fl->fl6_dst, &hdr->daddr); ipv6_addr_copy(&fl->fl6_src, &hdr->saddr); while (pskb_may_pull(skb, skb->nh.raw + offset + 1 - skb->data)) { + exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset); + switch (nexthdr) { case NEXTHDR_ROUTING: case NEXTHDR_HOP: diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c index 953307a9df1..a3bbc891f95 100644 --- a/net/tipc/name_distr.c +++ b/net/tipc/name_distr.c @@ -229,8 +229,7 @@ static void node_is_down(struct publication *publ) publ->node, publ->ref, publ->key); assert(p == publ); write_unlock_bh(&tipc_nametbl_lock); - if (publ) - kfree(publ); + kfree(publ); } /** |