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
This commit is contained in:
@@ -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 @@
|
|||||||
#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
|
|||||||
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 @@ load_w:
|
|||||||
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)
|
|||||||
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
|
|||||||
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[] = {
|
|||||||
{ -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
|
|||||||
}
|
}
|
||||||
|
|
||||||
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 @@ error:
|
|||||||
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)
|
|||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user