Commit 6044ab32 authored by Linus Torvalds's avatar Linus Torvalds

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

* 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6:
  [NET]: Fix race condition about network device name allocation.
  [IPV4]: icmp: fix crash with sysctl_icmp_errors_use_inbound_ifaddr
  [NETFILTER]: nf_conntrack_ipv4: fix incorrect #ifdef config name
  [NETFILTER]: nf_conntrack: fix use-after-free in helper destroy callback invocation
  [IPSEC] pfkey: Load specific algorithm in pfkey_add rather than all
  [TCP] FRTO: Prevent state inconsistency in corner cases
  [TCP] FRTO: Add missing ECN CWR sending to one of the responses
  [NET]: Fix net/core/skbuff.c gcc-3.2.3 compilation error
  [RFKILL]: Fix check for correct rfkill allocation
  [IPV6]: Add ip6_tunnel.h to headers_install
parents d07b3c25 9093bbb2
...@@ -239,6 +239,7 @@ unifdef-y += ipc.h ...@@ -239,6 +239,7 @@ unifdef-y += ipc.h
unifdef-y += ipmi.h unifdef-y += ipmi.h
unifdef-y += ipv6.h unifdef-y += ipv6.h
unifdef-y += ipv6_route.h unifdef-y += ipv6_route.h
unifdef-y += ip6_tunnel.h
unifdef-y += isdn.h unifdef-y += isdn.h
unifdef-y += isdnif.h unifdef-y += isdnif.h
unifdef-y += isdn_divertif.h unifdef-y += isdn_divertif.h
......
...@@ -3314,7 +3314,6 @@ void netdev_run_todo(void) ...@@ -3314,7 +3314,6 @@ void netdev_run_todo(void)
continue; continue;
} }
netdev_unregister_sysfs(dev);
dev->reg_state = NETREG_UNREGISTERED; dev->reg_state = NETREG_UNREGISTERED;
netdev_wait_allrefs(dev); netdev_wait_allrefs(dev);
...@@ -3325,11 +3324,11 @@ void netdev_run_todo(void) ...@@ -3325,11 +3324,11 @@ void netdev_run_todo(void)
BUG_TRAP(!dev->ip6_ptr); BUG_TRAP(!dev->ip6_ptr);
BUG_TRAP(!dev->dn_ptr); BUG_TRAP(!dev->dn_ptr);
/* It must be the very last action,
* after this 'dev' may point to freed up memory.
*/
if (dev->destructor) if (dev->destructor)
dev->destructor(dev); dev->destructor(dev);
/* Free network device */
kobject_put(&dev->dev.kobj);
} }
out: out:
...@@ -3480,6 +3479,9 @@ void unregister_netdevice(struct net_device *dev) ...@@ -3480,6 +3479,9 @@ void unregister_netdevice(struct net_device *dev)
/* Notifier chain MUST detach us from master device. */ /* Notifier chain MUST detach us from master device. */
BUG_TRAP(!dev->master); BUG_TRAP(!dev->master);
/* Remove entries from sysfs */
netdev_unregister_sysfs(dev);
/* Finish processing unregister after unlock */ /* Finish processing unregister after unlock */
net_set_todo(dev); net_set_todo(dev);
......
...@@ -456,9 +456,15 @@ static struct class net_class = { ...@@ -456,9 +456,15 @@ static struct class net_class = {
#endif #endif
}; };
/* Delete sysfs entries but hold kobject reference until after all
* netdev references are gone.
*/
void netdev_unregister_sysfs(struct net_device * net) void netdev_unregister_sysfs(struct net_device * net)
{ {
device_del(&(net->dev)); struct device *dev = &(net->dev);
kobject_get(&dev->kobj);
device_del(dev);
} }
/* Create sysfs entries for network device. */ /* Create sysfs entries for network device. */
......
...@@ -644,11 +644,10 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail, ...@@ -644,11 +644,10 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail,
/* Copy only real data... and, alas, header. This should be /* Copy only real data... and, alas, header. This should be
* optimized for the cases when header is void. */ * optimized for the cases when header is void. */
memcpy(data + nhead, skb->head,
#ifdef NET_SKBUFF_DATA_USES_OFFSET #ifdef NET_SKBUFF_DATA_USES_OFFSET
skb->tail); memcpy(data + nhead, skb->head, skb->tail);
#else #else
skb->tail - skb->head); memcpy(data + nhead, skb->head, skb->tail - skb->head);
#endif #endif
memcpy(data + size, skb_end_pointer(skb), memcpy(data + size, skb_end_pointer(skb),
sizeof(struct skb_shared_info)); sizeof(struct skb_shared_info));
......
...@@ -514,7 +514,10 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) ...@@ -514,7 +514,10 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
saddr = iph->daddr; saddr = iph->daddr;
if (!(rt->rt_flags & RTCF_LOCAL)) { if (!(rt->rt_flags & RTCF_LOCAL)) {
if (sysctl_icmp_errors_use_inbound_ifaddr) /* This is broken, skb_in->dev points to the outgoing device
* after the packet passes through ip_output().
*/
if (skb_in->dev && sysctl_icmp_errors_use_inbound_ifaddr)
saddr = inet_select_addr(skb_in->dev, 0, RT_SCOPE_LINK); saddr = inet_select_addr(skb_in->dev, 0, RT_SCOPE_LINK);
else else
saddr = 0; saddr = 0;
......
...@@ -154,12 +154,10 @@ static unsigned int ipv4_conntrack_defrag(unsigned int hooknum, ...@@ -154,12 +154,10 @@ static unsigned int ipv4_conntrack_defrag(unsigned int hooknum,
const struct net_device *out, const struct net_device *out,
int (*okfn)(struct sk_buff *)) int (*okfn)(struct sk_buff *))
{ {
#if !defined(CONFIG_IP_NF_NAT) && !defined(CONFIG_IP_NF_NAT_MODULE)
/* Previously seen (loopback)? Ignore. Do this before /* Previously seen (loopback)? Ignore. Do this before
fragment check. */ fragment check. */
if ((*pskb)->nfct) if ((*pskb)->nfct)
return NF_ACCEPT; return NF_ACCEPT;
#endif
/* Gather fragments. */ /* Gather fragments. */
if (ip_hdr(*pskb)->frag_off & htons(IP_MF | IP_OFFSET)) { if (ip_hdr(*pskb)->frag_off & htons(IP_MF | IP_OFFSET)) {
......
...@@ -1501,6 +1501,8 @@ void tcp_enter_loss(struct sock *sk, int how) ...@@ -1501,6 +1501,8 @@ void tcp_enter_loss(struct sock *sk, int how)
tcp_set_ca_state(sk, TCP_CA_Loss); tcp_set_ca_state(sk, TCP_CA_Loss);
tp->high_seq = tp->snd_nxt; tp->high_seq = tp->snd_nxt;
TCP_ECN_queue_cwr(tp); TCP_ECN_queue_cwr(tp);
/* Abort FRTO algorithm if one is in progress */
tp->frto_counter = 0;
clear_all_retrans_hints(tp); clear_all_retrans_hints(tp);
} }
...@@ -2608,6 +2610,7 @@ static void tcp_conservative_spur_to_response(struct tcp_sock *tp) ...@@ -2608,6 +2610,7 @@ static void tcp_conservative_spur_to_response(struct tcp_sock *tp)
{ {
tp->snd_cwnd = min(tp->snd_cwnd, tp->snd_ssthresh); tp->snd_cwnd = min(tp->snd_cwnd, tp->snd_ssthresh);
tp->snd_cwnd_cnt = 0; tp->snd_cwnd_cnt = 0;
TCP_ECN_queue_cwr(tp);
tcp_moderate_cwnd(tp); tcp_moderate_cwnd(tp);
} }
......
...@@ -1448,8 +1448,6 @@ static int pfkey_add(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, ...@@ -1448,8 +1448,6 @@ static int pfkey_add(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr,
int err; int err;
struct km_event c; struct km_event c;
xfrm_probe_algs();
x = pfkey_msg2xfrm_state(hdr, ext_hdrs); x = pfkey_msg2xfrm_state(hdr, ext_hdrs);
if (IS_ERR(x)) if (IS_ERR(x))
return PTR_ERR(x); return PTR_ERR(x);
......
...@@ -298,7 +298,6 @@ static void ...@@ -298,7 +298,6 @@ static void
destroy_conntrack(struct nf_conntrack *nfct) destroy_conntrack(struct nf_conntrack *nfct)
{ {
struct nf_conn *ct = (struct nf_conn *)nfct; struct nf_conn *ct = (struct nf_conn *)nfct;
struct nf_conn_help *help = nfct_help(ct);
struct nf_conntrack_l4proto *l4proto; struct nf_conntrack_l4proto *l4proto;
typeof(nf_conntrack_destroyed) destroyed; typeof(nf_conntrack_destroyed) destroyed;
...@@ -309,9 +308,6 @@ destroy_conntrack(struct nf_conntrack *nfct) ...@@ -309,9 +308,6 @@ destroy_conntrack(struct nf_conntrack *nfct)
nf_conntrack_event(IPCT_DESTROY, ct); nf_conntrack_event(IPCT_DESTROY, ct);
set_bit(IPS_DYING_BIT, &ct->status); set_bit(IPS_DYING_BIT, &ct->status);
if (help && help->helper && help->helper->destroy)
help->helper->destroy(ct);
/* To make sure we don't get any weird locking issues here: /* To make sure we don't get any weird locking issues here:
* destroy_conntrack() MUST NOT be called with a write lock * destroy_conntrack() MUST NOT be called with a write lock
* to nf_conntrack_lock!!! -HW */ * to nf_conntrack_lock!!! -HW */
...@@ -353,6 +349,10 @@ destroy_conntrack(struct nf_conntrack *nfct) ...@@ -353,6 +349,10 @@ destroy_conntrack(struct nf_conntrack *nfct)
static void death_by_timeout(unsigned long ul_conntrack) static void death_by_timeout(unsigned long ul_conntrack)
{ {
struct nf_conn *ct = (void *)ul_conntrack; struct nf_conn *ct = (void *)ul_conntrack;
struct nf_conn_help *help = nfct_help(ct);
if (help && help->helper && help->helper->destroy)
help->helper->destroy(ct);
write_lock_bh(&nf_conntrack_lock); write_lock_bh(&nf_conntrack_lock);
/* Inside lock so preempt is disabled on module removal path. /* Inside lock so preempt is disabled on module removal path.
......
...@@ -296,7 +296,7 @@ struct rfkill *rfkill_allocate(struct device *parent, enum rfkill_type type) ...@@ -296,7 +296,7 @@ struct rfkill *rfkill_allocate(struct device *parent, enum rfkill_type type)
struct device *dev; struct device *dev;
rfkill = kzalloc(sizeof(struct rfkill), GFP_KERNEL); rfkill = kzalloc(sizeof(struct rfkill), GFP_KERNEL);
if (rfkill) if (!rfkill)
return NULL; return NULL;
mutex_init(&rfkill->mutex); mutex_init(&rfkill->mutex);
......
...@@ -347,67 +347,44 @@ static inline int calg_entries(void) ...@@ -347,67 +347,44 @@ static inline int calg_entries(void)
return ARRAY_SIZE(calg_list); return ARRAY_SIZE(calg_list);
} }
/* Todo: generic iterators */ struct xfrm_algo_list {
struct xfrm_algo_desc *xfrm_aalg_get_byid(int alg_id) struct xfrm_algo_desc *algs;
{ int entries;
int i; u32 type;
u32 mask;
for (i = 0; i < aalg_entries(); i++) { };
if (aalg_list[i].desc.sadb_alg_id == alg_id) {
if (aalg_list[i].available)
return &aalg_list[i];
else
break;
}
}
return NULL;
}
EXPORT_SYMBOL_GPL(xfrm_aalg_get_byid);
struct xfrm_algo_desc *xfrm_ealg_get_byid(int alg_id)
{
int i;
for (i = 0; i < ealg_entries(); i++) { static const struct xfrm_algo_list xfrm_aalg_list = {
if (ealg_list[i].desc.sadb_alg_id == alg_id) { .algs = aalg_list,
if (ealg_list[i].available) .entries = ARRAY_SIZE(aalg_list),
return &ealg_list[i]; .type = CRYPTO_ALG_TYPE_HASH,
else .mask = CRYPTO_ALG_TYPE_HASH_MASK | CRYPTO_ALG_ASYNC,
break; };
}
}
return NULL;
}
EXPORT_SYMBOL_GPL(xfrm_ealg_get_byid);
struct xfrm_algo_desc *xfrm_calg_get_byid(int alg_id) static const struct xfrm_algo_list xfrm_ealg_list = {
{ .algs = ealg_list,
int i; .entries = ARRAY_SIZE(ealg_list),
.type = CRYPTO_ALG_TYPE_BLKCIPHER,
.mask = CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC,
};
for (i = 0; i < calg_entries(); i++) { static const struct xfrm_algo_list xfrm_calg_list = {
if (calg_list[i].desc.sadb_alg_id == alg_id) { .algs = calg_list,
if (calg_list[i].available) .entries = ARRAY_SIZE(calg_list),
return &calg_list[i]; .type = CRYPTO_ALG_TYPE_COMPRESS,
else .mask = CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC,
break; };
}
}
return NULL;
}
EXPORT_SYMBOL_GPL(xfrm_calg_get_byid);
static struct xfrm_algo_desc *xfrm_get_byname(struct xfrm_algo_desc *list, static struct xfrm_algo_desc *xfrm_find_algo(
int entries, u32 type, u32 mask, const struct xfrm_algo_list *algo_list,
char *name, int probe) int match(const struct xfrm_algo_desc *entry, const void *data),
const void *data, int probe)
{ {
struct xfrm_algo_desc *list = algo_list->algs;
int i, status; int i, status;
if (!name) for (i = 0; i < algo_list->entries; i++) {
return NULL; if (!match(list + i, data))
for (i = 0; i < entries; i++) {
if (strcmp(name, list[i].name) &&
(!list[i].compat || strcmp(name, list[i].compat)))
continue; continue;
if (list[i].available) if (list[i].available)
...@@ -416,8 +393,8 @@ static struct xfrm_algo_desc *xfrm_get_byname(struct xfrm_algo_desc *list, ...@@ -416,8 +393,8 @@ static struct xfrm_algo_desc *xfrm_get_byname(struct xfrm_algo_desc *list,
if (!probe) if (!probe)
break; break;
status = crypto_has_alg(list[i].name, type, status = crypto_has_alg(list[i].name, algo_list->type,
mask | CRYPTO_ALG_ASYNC); algo_list->mask);
if (!status) if (!status)
break; break;
...@@ -427,27 +404,60 @@ static struct xfrm_algo_desc *xfrm_get_byname(struct xfrm_algo_desc *list, ...@@ -427,27 +404,60 @@ static struct xfrm_algo_desc *xfrm_get_byname(struct xfrm_algo_desc *list,
return NULL; return NULL;
} }
static int xfrm_alg_id_match(const struct xfrm_algo_desc *entry,
const void *data)
{
return entry->desc.sadb_alg_id == (int)data;
}
struct xfrm_algo_desc *xfrm_aalg_get_byid(int alg_id)
{
return xfrm_find_algo(&xfrm_aalg_list, xfrm_alg_id_match,
(void *)alg_id, 1);
}
EXPORT_SYMBOL_GPL(xfrm_aalg_get_byid);
struct xfrm_algo_desc *xfrm_ealg_get_byid(int alg_id)
{
return xfrm_find_algo(&xfrm_ealg_list, xfrm_alg_id_match,
(void *)alg_id, 1);
}
EXPORT_SYMBOL_GPL(xfrm_ealg_get_byid);
struct xfrm_algo_desc *xfrm_calg_get_byid(int alg_id)
{
return xfrm_find_algo(&xfrm_calg_list, xfrm_alg_id_match,
(void *)alg_id, 1);
}
EXPORT_SYMBOL_GPL(xfrm_calg_get_byid);
static int xfrm_alg_name_match(const struct xfrm_algo_desc *entry,
const void *data)
{
const char *name = data;
return name && (!strcmp(name, entry->name) ||
(entry->compat && !strcmp(name, entry->compat)));
}
struct xfrm_algo_desc *xfrm_aalg_get_byname(char *name, int probe) struct xfrm_algo_desc *xfrm_aalg_get_byname(char *name, int probe)
{ {
return xfrm_get_byname(aalg_list, aalg_entries(), return xfrm_find_algo(&xfrm_aalg_list, xfrm_alg_name_match, name,
CRYPTO_ALG_TYPE_HASH, CRYPTO_ALG_TYPE_HASH_MASK, probe);
name, probe);
} }
EXPORT_SYMBOL_GPL(xfrm_aalg_get_byname); EXPORT_SYMBOL_GPL(xfrm_aalg_get_byname);
struct xfrm_algo_desc *xfrm_ealg_get_byname(char *name, int probe) struct xfrm_algo_desc *xfrm_ealg_get_byname(char *name, int probe)
{ {
return xfrm_get_byname(ealg_list, ealg_entries(), return xfrm_find_algo(&xfrm_ealg_list, xfrm_alg_name_match, name,
CRYPTO_ALG_TYPE_BLKCIPHER, CRYPTO_ALG_TYPE_MASK, probe);
name, probe);
} }
EXPORT_SYMBOL_GPL(xfrm_ealg_get_byname); EXPORT_SYMBOL_GPL(xfrm_ealg_get_byname);
struct xfrm_algo_desc *xfrm_calg_get_byname(char *name, int probe) struct xfrm_algo_desc *xfrm_calg_get_byname(char *name, int probe)
{ {
return xfrm_get_byname(calg_list, calg_entries(), return xfrm_find_algo(&xfrm_calg_list, xfrm_alg_name_match, name,
CRYPTO_ALG_TYPE_COMPRESS, CRYPTO_ALG_TYPE_MASK, probe);
name, probe);
} }
EXPORT_SYMBOL_GPL(xfrm_calg_get_byname); EXPORT_SYMBOL_GPL(xfrm_calg_get_byname);
......
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