提交 6044ab32 编写于 作者: L 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
......@@ -239,6 +239,7 @@ unifdef-y += ipc.h
unifdef-y += ipmi.h
unifdef-y += ipv6.h
unifdef-y += ipv6_route.h
unifdef-y += ip6_tunnel.h
unifdef-y += isdn.h
unifdef-y += isdnif.h
unifdef-y += isdn_divertif.h
......
......@@ -3314,7 +3314,6 @@ void netdev_run_todo(void)
continue;
}
netdev_unregister_sysfs(dev);
dev->reg_state = NETREG_UNREGISTERED;
netdev_wait_allrefs(dev);
......@@ -3325,11 +3324,11 @@ void netdev_run_todo(void)
BUG_TRAP(!dev->ip6_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)
dev->destructor(dev);
/* Free network device */
kobject_put(&dev->dev.kobj);
}
out:
......@@ -3480,6 +3479,9 @@ void unregister_netdevice(struct net_device *dev)
/* Notifier chain MUST detach us from master device. */
BUG_TRAP(!dev->master);
/* Remove entries from sysfs */
netdev_unregister_sysfs(dev);
/* Finish processing unregister after unlock */
net_set_todo(dev);
......
......@@ -456,9 +456,15 @@ static struct class net_class = {
#endif
};
/* Delete sysfs entries but hold kobject reference until after all
* netdev references are gone.
*/
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. */
......
......@@ -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
* optimized for the cases when header is void. */
memcpy(data + nhead, skb->head,
#ifdef NET_SKBUFF_DATA_USES_OFFSET
skb->tail);
memcpy(data + nhead, skb->head, skb->tail);
#else
skb->tail - skb->head);
memcpy(data + nhead, skb->head, skb->tail - skb->head);
#endif
memcpy(data + size, skb_end_pointer(skb),
sizeof(struct skb_shared_info));
......
......@@ -514,7 +514,10 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
saddr = iph->daddr;
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);
else
saddr = 0;
......
......@@ -154,12 +154,10 @@ static unsigned int ipv4_conntrack_defrag(unsigned int hooknum,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
#if !defined(CONFIG_IP_NF_NAT) && !defined(CONFIG_IP_NF_NAT_MODULE)
/* Previously seen (loopback)? Ignore. Do this before
fragment check. */
if ((*pskb)->nfct)
return NF_ACCEPT;
#endif
/* Gather fragments. */
if (ip_hdr(*pskb)->frag_off & htons(IP_MF | IP_OFFSET)) {
......
......@@ -1501,6 +1501,8 @@ void tcp_enter_loss(struct sock *sk, int how)
tcp_set_ca_state(sk, TCP_CA_Loss);
tp->high_seq = tp->snd_nxt;
TCP_ECN_queue_cwr(tp);
/* Abort FRTO algorithm if one is in progress */
tp->frto_counter = 0;
clear_all_retrans_hints(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_cnt = 0;
TCP_ECN_queue_cwr(tp);
tcp_moderate_cwnd(tp);
}
......
......@@ -1448,8 +1448,6 @@ static int pfkey_add(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr,
int err;
struct km_event c;
xfrm_probe_algs();
x = pfkey_msg2xfrm_state(hdr, ext_hdrs);
if (IS_ERR(x))
return PTR_ERR(x);
......
......@@ -298,7 +298,6 @@ static void
destroy_conntrack(struct nf_conntrack *nfct)
{
struct nf_conn *ct = (struct nf_conn *)nfct;
struct nf_conn_help *help = nfct_help(ct);
struct nf_conntrack_l4proto *l4proto;
typeof(nf_conntrack_destroyed) destroyed;
......@@ -309,9 +308,6 @@ destroy_conntrack(struct nf_conntrack *nfct)
nf_conntrack_event(IPCT_DESTROY, ct);
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:
* destroy_conntrack() MUST NOT be called with a write lock
* to nf_conntrack_lock!!! -HW */
......@@ -353,6 +349,10 @@ destroy_conntrack(struct nf_conntrack *nfct)
static void death_by_timeout(unsigned long 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);
/* 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)
struct device *dev;
rfkill = kzalloc(sizeof(struct rfkill), GFP_KERNEL);
if (rfkill)
if (!rfkill)
return NULL;
mutex_init(&rfkill->mutex);
......
......@@ -347,67 +347,44 @@ static inline int calg_entries(void)
return ARRAY_SIZE(calg_list);
}
/* Todo: generic iterators */
struct xfrm_algo_desc *xfrm_aalg_get_byid(int alg_id)
{
int i;
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;
struct xfrm_algo_list {
struct xfrm_algo_desc *algs;
int entries;
u32 type;
u32 mask;
};
for (i = 0; i < ealg_entries(); i++) {
if (ealg_list[i].desc.sadb_alg_id == alg_id) {
if (ealg_list[i].available)
return &ealg_list[i];
else
break;
}
}
return NULL;
}
EXPORT_SYMBOL_GPL(xfrm_ealg_get_byid);
static const struct xfrm_algo_list xfrm_aalg_list = {
.algs = aalg_list,
.entries = ARRAY_SIZE(aalg_list),
.type = CRYPTO_ALG_TYPE_HASH,
.mask = CRYPTO_ALG_TYPE_HASH_MASK | CRYPTO_ALG_ASYNC,
};
struct xfrm_algo_desc *xfrm_calg_get_byid(int alg_id)
{
int i;
static const struct xfrm_algo_list xfrm_ealg_list = {
.algs = ealg_list,
.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++) {
if (calg_list[i].desc.sadb_alg_id == alg_id) {
if (calg_list[i].available)
return &calg_list[i];
else
break;
}
}
return NULL;
}
EXPORT_SYMBOL_GPL(xfrm_calg_get_byid);
static const struct xfrm_algo_list xfrm_calg_list = {
.algs = calg_list,
.entries = ARRAY_SIZE(calg_list),
.type = CRYPTO_ALG_TYPE_COMPRESS,
.mask = CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC,
};
static struct xfrm_algo_desc *xfrm_get_byname(struct xfrm_algo_desc *list,
int entries, u32 type, u32 mask,
char *name, int probe)
static struct xfrm_algo_desc *xfrm_find_algo(
const struct xfrm_algo_list *algo_list,
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;
if (!name)
return NULL;
for (i = 0; i < entries; i++) {
if (strcmp(name, list[i].name) &&
(!list[i].compat || strcmp(name, list[i].compat)))
for (i = 0; i < algo_list->entries; i++) {
if (!match(list + i, data))
continue;
if (list[i].available)
......@@ -416,8 +393,8 @@ static struct xfrm_algo_desc *xfrm_get_byname(struct xfrm_algo_desc *list,
if (!probe)
break;
status = crypto_has_alg(list[i].name, type,
mask | CRYPTO_ALG_ASYNC);
status = crypto_has_alg(list[i].name, algo_list->type,
algo_list->mask);
if (!status)
break;
......@@ -427,27 +404,60 @@ static struct xfrm_algo_desc *xfrm_get_byname(struct xfrm_algo_desc *list,
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)
{
return xfrm_get_byname(aalg_list, aalg_entries(),
CRYPTO_ALG_TYPE_HASH, CRYPTO_ALG_TYPE_HASH_MASK,
name, probe);
return xfrm_find_algo(&xfrm_aalg_list, xfrm_alg_name_match, name,
probe);
}
EXPORT_SYMBOL_GPL(xfrm_aalg_get_byname);
struct xfrm_algo_desc *xfrm_ealg_get_byname(char *name, int probe)
{
return xfrm_get_byname(ealg_list, ealg_entries(),
CRYPTO_ALG_TYPE_BLKCIPHER, CRYPTO_ALG_TYPE_MASK,
name, probe);
return xfrm_find_algo(&xfrm_ealg_list, xfrm_alg_name_match, name,
probe);
}
EXPORT_SYMBOL_GPL(xfrm_ealg_get_byname);
struct xfrm_algo_desc *xfrm_calg_get_byname(char *name, int probe)
{
return xfrm_get_byname(calg_list, calg_entries(),
CRYPTO_ALG_TYPE_COMPRESS, CRYPTO_ALG_TYPE_MASK,
name, probe);
return xfrm_find_algo(&xfrm_calg_list, xfrm_alg_name_match, name,
probe);
}
EXPORT_SYMBOL_GPL(xfrm_calg_get_byname);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册