diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-21 17:00:57 (GMT) |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-21 17:00:57 (GMT) |
commit | 6044ab324ce4c180bce17aa9be00157c611d7d48 (patch) | |
tree | 8093f40d39f6e3ed818a7b5388fafced4639eb02 | |
parent | d07b3c25327c5ae3792d0ed0c135dee4727200a1 (diff) | |
parent | 9093bbb2d96d0184f037cea9b4e952a44ebe7c32 (diff) | |
download | linux-6044ab324ce4c180bce17aa9be00157c611d7d48.tar.xz |
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
-rw-r--r-- | include/linux/Kbuild | 1 | ||||
-rw-r--r-- | net/core/dev.c | 10 | ||||
-rw-r--r-- | net/core/net-sysfs.c | 8 | ||||
-rw-r--r-- | net/core/skbuff.c | 5 | ||||
-rw-r--r-- | net/ipv4/icmp.c | 5 | ||||
-rw-r--r-- | net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 2 | ||||
-rw-r--r-- | net/ipv4/tcp_input.c | 3 | ||||
-rw-r--r-- | net/key/af_key.c | 2 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_core.c | 8 | ||||
-rw-r--r-- | net/rfkill/rfkill.c | 2 | ||||
-rw-r--r-- | net/xfrm/xfrm_algo.c | 140 |
11 files changed, 103 insertions, 83 deletions
diff --git a/include/linux/Kbuild b/include/linux/Kbuild index bcd01f2..e101315 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -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 diff --git a/net/core/dev.c b/net/core/dev.c index f2b6111..5a7f20f 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -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); diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index b21307b..5c19b06 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c @@ -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. */ diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 1422573..7c6a34e 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -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)); diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index d38cbba..e238b17 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -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; diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index 0654eaa..fd62a41 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c @@ -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)) { diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 7641b27..38cb25b 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -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); } diff --git a/net/key/af_key.c b/net/key/af_key.c index a994441..d302dda 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -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); diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index e8b5c2d..483e927 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -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. diff --git a/net/rfkill/rfkill.c b/net/rfkill/rfkill.c index a973603..f3986d4 100644 --- a/net/rfkill/rfkill.c +++ b/net/rfkill/rfkill.c @@ -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); diff --git a/net/xfrm/xfrm_algo.c b/net/xfrm/xfrm_algo.c index 6249a94..8a72def 100644 --- a/net/xfrm/xfrm_algo.c +++ b/net/xfrm/xfrm_algo.c @@ -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); |