Commit 5c723d26 authored by Linus Torvalds's avatar Linus Torvalds

Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6

* master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6:
  [NET]: Remove redundant NULL checks before [kv]free
  unaligned access in sk_run_filter()
  [IPV6]: Clean up hop-by-hop options handler.
  [IPV6] XFRM: Fix decoding session with preceding extension header(s).
  [IPV6] XFRM: Don't use old copy of pointer after pskb_may_pull().
  [IPV6]: Ensure to have hop-by-hop options in our header of &sk_buff.
  [TCP]: Fix truesize underflow
parents a196e788 63903ca6
...@@ -230,7 +230,7 @@ extern int ip6_ra_control(struct sock *sk, int sel, ...@@ -230,7 +230,7 @@ extern int ip6_ra_control(struct sock *sk, int sel,
void (*destructor)(struct sock *)); 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_dup_options(struct sock *sk, struct ipv6_txoptions *opt);
extern struct ipv6_txoptions * ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt, extern struct ipv6_txoptions * ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt,
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include <linux/timer.h> #include <linux/timer.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/unaligned.h>
#include <linux/filter.h> #include <linux/filter.h>
/* No hurry in this branch */ /* No hurry in this branch */
...@@ -177,7 +178,7 @@ unsigned int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int ...@@ -177,7 +178,7 @@ unsigned int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int
load_w: load_w:
ptr = load_pointer(skb, k, 4, &tmp); ptr = load_pointer(skb, k, 4, &tmp);
if (ptr != NULL) { if (ptr != NULL) {
A = ntohl(*(u32 *)ptr); A = ntohl(get_unaligned((u32 *)ptr));
continue; continue;
} }
break; break;
...@@ -186,7 +187,7 @@ unsigned int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int ...@@ -186,7 +187,7 @@ unsigned int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int
load_h: load_h:
ptr = load_pointer(skb, k, 2, &tmp); ptr = load_pointer(skb, k, 2, &tmp);
if (ptr != NULL) { if (ptr != NULL) {
A = ntohs(*(u16 *)ptr); A = ntohs(get_unaligned((u16 *)ptr));
continue; continue;
} }
break; break;
......
...@@ -290,11 +290,8 @@ static void ipcomp_free_scratches(void) ...@@ -290,11 +290,8 @@ static void ipcomp_free_scratches(void)
if (!scratches) if (!scratches)
return; return;
for_each_possible_cpu(i) { for_each_possible_cpu(i)
void *scratch = *per_cpu_ptr(scratches, i); vfree(*per_cpu_ptr(scratches, i));
if (scratch)
vfree(scratch);
}
free_percpu(scratches); free_percpu(scratches);
} }
......
...@@ -551,7 +551,9 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss ...@@ -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); buff = sk_stream_alloc_skb(sk, nsize, GFP_ATOMIC);
if (buff == NULL) if (buff == NULL)
return -ENOMEM; /* We'll just try again later. */ 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. */ /* Correct the sequence numbers. */
TCP_SKB_CB(buff)->seq = TCP_SKB_CB(skb)->seq + len; TCP_SKB_CB(buff)->seq = TCP_SKB_CB(skb)->seq + len;
......
...@@ -485,15 +485,27 @@ static struct tlvtype_proc tlvprochopopt_lst[] = { ...@@ -485,15 +485,27 @@ static struct tlvtype_proc tlvprochopopt_lst[] = {
{ -1, } { -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); 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); opt->hop = sizeof(struct ipv6hdr);
if (ip6_parse_tlv(tlvprochopopt_lst, skb)) { if (ip6_parse_tlv(tlvprochopopt_lst, skb)) {
skb->h.raw += (skb->h.raw[1]+1)<<3; skb->h.raw += (skb->h.raw[1]+1)<<3;
opt->nhoff = sizeof(struct ipv6hdr); opt->nhoff = sizeof(struct ipv6hdr);
return sizeof(struct ipv6hdr); return 1;
} }
return -1; return -1;
} }
......
...@@ -114,11 +114,10 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt ...@@ -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 (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); IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
return 0; return 0;
} }
hdr = skb->nh.ipv6h;
} }
return NF_HOOK(PF_INET6,NF_IP6_PRE_ROUTING, skb, dev, NULL, ip6_rcv_finish); return NF_HOOK(PF_INET6,NF_IP6_PRE_ROUTING, skb, dev, NULL, ip6_rcv_finish);
......
...@@ -191,16 +191,18 @@ __xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int ...@@ -191,16 +191,18 @@ __xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
static inline void static inline void
_decode_session6(struct sk_buff *skb, struct flowi *fl) _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 ipv6hdr *hdr = skb->nh.ipv6h;
struct ipv6_opt_hdr *exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset); struct ipv6_opt_hdr *exthdr;
u8 nexthdr = skb->nh.ipv6h->nexthdr; u8 nexthdr = skb->nh.raw[IP6CB(skb)->nhoff];
memset(fl, 0, sizeof(struct flowi)); memset(fl, 0, sizeof(struct flowi));
ipv6_addr_copy(&fl->fl6_dst, &hdr->daddr); ipv6_addr_copy(&fl->fl6_dst, &hdr->daddr);
ipv6_addr_copy(&fl->fl6_src, &hdr->saddr); ipv6_addr_copy(&fl->fl6_src, &hdr->saddr);
while (pskb_may_pull(skb, skb->nh.raw + offset + 1 - skb->data)) { while (pskb_may_pull(skb, skb->nh.raw + offset + 1 - skb->data)) {
exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset);
switch (nexthdr) { switch (nexthdr) {
case NEXTHDR_ROUTING: case NEXTHDR_ROUTING:
case NEXTHDR_HOP: case NEXTHDR_HOP:
......
...@@ -229,8 +229,7 @@ static void node_is_down(struct publication *publ) ...@@ -229,8 +229,7 @@ static void node_is_down(struct publication *publ)
publ->node, publ->ref, publ->key); publ->node, publ->ref, publ->key);
assert(p == publ); assert(p == publ);
write_unlock_bh(&tipc_nametbl_lock); write_unlock_bh(&tipc_nametbl_lock);
if (publ) kfree(publ);
kfree(publ);
} }
/** /**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment