aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-09-08 18:43:44 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-09-08 18:43:44 -0400
commitbcbc713470283bc82d043fd23b02e41a9eb8dee5 (patch)
tree2cd88a1b83dad55dc9e489f151114c0717015ac5
parentb364e2f5262e972e731a576dfc6ede0689a6c19e (diff)
parent8d4698f7a54a492a1b96c505b30fe750ae3e61d5 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: bridge: don't allow setting hello time to zero netns : fix kernel panic in timewait socket destruction pkt_sched: Fix qdisc state in net_tx_action() netfilter: nf_conntrack_irc: make sure string is terminated before calling simple_strtoul netfilter: nf_conntrack_gre: nf_ct_gre_keymap_flush() fixlet netfilter: nf_conntrack_gre: more locking around keymap list netfilter: nf_conntrack_sip: de-static helper pointers
-rw-r--r--include/net/inet_timewait_sock.h3
-rw-r--r--net/bridge/br_ioctl.c8
-rw-r--r--net/bridge/br_sysfs_br.c26
-rw-r--r--net/core/dev.c7
-rw-r--r--net/ipv4/inet_timewait_sock.c35
-rw-r--r--net/ipv4/tcp_ipv4.c1
-rw-r--r--net/ipv6/tcp_ipv6.c1
-rw-r--r--net/netfilter/nf_conntrack_irc.c10
-rw-r--r--net/netfilter/nf_conntrack_proto_gre.c14
-rw-r--r--net/netfilter/nf_conntrack_sip.c6
10 files changed, 94 insertions, 17 deletions
diff --git a/include/net/inet_timewait_sock.h b/include/net/inet_timewait_sock.h
index 95c660c9719b..91324908fccd 100644
--- a/include/net/inet_timewait_sock.h
+++ b/include/net/inet_timewait_sock.h
@@ -208,6 +208,9 @@ extern void inet_twsk_schedule(struct inet_timewait_sock *tw,
208extern void inet_twsk_deschedule(struct inet_timewait_sock *tw, 208extern void inet_twsk_deschedule(struct inet_timewait_sock *tw,
209 struct inet_timewait_death_row *twdr); 209 struct inet_timewait_death_row *twdr);
210 210
211extern void inet_twsk_purge(struct net *net, struct inet_hashinfo *hashinfo,
212 struct inet_timewait_death_row *twdr, int family);
213
211static inline 214static inline
212struct net *twsk_net(const struct inet_timewait_sock *twsk) 215struct net *twsk_net(const struct inet_timewait_sock *twsk)
213{ 216{
diff --git a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c
index eeee218eed80..5bbf07362172 100644
--- a/net/bridge/br_ioctl.c
+++ b/net/bridge/br_ioctl.c
@@ -188,15 +188,21 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
188 return 0; 188 return 0;
189 189
190 case BRCTL_SET_BRIDGE_HELLO_TIME: 190 case BRCTL_SET_BRIDGE_HELLO_TIME:
191 {
192 unsigned long t = clock_t_to_jiffies(args[1]);
191 if (!capable(CAP_NET_ADMIN)) 193 if (!capable(CAP_NET_ADMIN))
192 return -EPERM; 194 return -EPERM;
193 195
196 if (t < HZ)
197 return -EINVAL;
198
194 spin_lock_bh(&br->lock); 199 spin_lock_bh(&br->lock);
195 br->bridge_hello_time = clock_t_to_jiffies(args[1]); 200 br->bridge_hello_time = t;
196 if (br_is_root_bridge(br)) 201 if (br_is_root_bridge(br))
197 br->hello_time = br->bridge_hello_time; 202 br->hello_time = br->bridge_hello_time;
198 spin_unlock_bh(&br->lock); 203 spin_unlock_bh(&br->lock);
199 return 0; 204 return 0;
205 }
200 206
201 case BRCTL_SET_BRIDGE_MAX_AGE: 207 case BRCTL_SET_BRIDGE_MAX_AGE:
202 if (!capable(CAP_NET_ADMIN)) 208 if (!capable(CAP_NET_ADMIN))
diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c
index 27d6a511c8c1..158dee8b4965 100644
--- a/net/bridge/br_sysfs_br.c
+++ b/net/bridge/br_sysfs_br.c
@@ -29,11 +29,12 @@
29 */ 29 */
30static ssize_t store_bridge_parm(struct device *d, 30static ssize_t store_bridge_parm(struct device *d,
31 const char *buf, size_t len, 31 const char *buf, size_t len,
32 void (*set)(struct net_bridge *, unsigned long)) 32 int (*set)(struct net_bridge *, unsigned long))
33{ 33{
34 struct net_bridge *br = to_bridge(d); 34 struct net_bridge *br = to_bridge(d);
35 char *endp; 35 char *endp;
36 unsigned long val; 36 unsigned long val;
37 int err;
37 38
38 if (!capable(CAP_NET_ADMIN)) 39 if (!capable(CAP_NET_ADMIN))
39 return -EPERM; 40 return -EPERM;
@@ -43,9 +44,9 @@ static ssize_t store_bridge_parm(struct device *d,
43 return -EINVAL; 44 return -EINVAL;
44 45
45 spin_lock_bh(&br->lock); 46 spin_lock_bh(&br->lock);
46 (*set)(br, val); 47 err = (*set)(br, val);
47 spin_unlock_bh(&br->lock); 48 spin_unlock_bh(&br->lock);
48 return len; 49 return err ? err : len;
49} 50}
50 51
51 52
@@ -56,12 +57,13 @@ static ssize_t show_forward_delay(struct device *d,
56 return sprintf(buf, "%lu\n", jiffies_to_clock_t(br->forward_delay)); 57 return sprintf(buf, "%lu\n", jiffies_to_clock_t(br->forward_delay));
57} 58}
58 59
59static void set_forward_delay(struct net_bridge *br, unsigned long val) 60static int set_forward_delay(struct net_bridge *br, unsigned long val)
60{ 61{
61 unsigned long delay = clock_t_to_jiffies(val); 62 unsigned long delay = clock_t_to_jiffies(val);
62 br->forward_delay = delay; 63 br->forward_delay = delay;
63 if (br_is_root_bridge(br)) 64 if (br_is_root_bridge(br))
64 br->bridge_forward_delay = delay; 65 br->bridge_forward_delay = delay;
66 return 0;
65} 67}
66 68
67static ssize_t store_forward_delay(struct device *d, 69static ssize_t store_forward_delay(struct device *d,
@@ -80,12 +82,17 @@ static ssize_t show_hello_time(struct device *d, struct device_attribute *attr,
80 jiffies_to_clock_t(to_bridge(d)->hello_time)); 82 jiffies_to_clock_t(to_bridge(d)->hello_time));
81} 83}
82 84
83static void set_hello_time(struct net_bridge *br, unsigned long val) 85static int set_hello_time(struct net_bridge *br, unsigned long val)
84{ 86{
85 unsigned long t = clock_t_to_jiffies(val); 87 unsigned long t = clock_t_to_jiffies(val);
88
89 if (t < HZ)
90 return -EINVAL;
91
86 br->hello_time = t; 92 br->hello_time = t;
87 if (br_is_root_bridge(br)) 93 if (br_is_root_bridge(br))
88 br->bridge_hello_time = t; 94 br->bridge_hello_time = t;
95 return 0;
89} 96}
90 97
91static ssize_t store_hello_time(struct device *d, 98static ssize_t store_hello_time(struct device *d,
@@ -104,12 +111,13 @@ static ssize_t show_max_age(struct device *d, struct device_attribute *attr,
104 jiffies_to_clock_t(to_bridge(d)->max_age)); 111 jiffies_to_clock_t(to_bridge(d)->max_age));
105} 112}
106 113
107static void set_max_age(struct net_bridge *br, unsigned long val) 114static int set_max_age(struct net_bridge *br, unsigned long val)
108{ 115{
109 unsigned long t = clock_t_to_jiffies(val); 116 unsigned long t = clock_t_to_jiffies(val);
110 br->max_age = t; 117 br->max_age = t;
111 if (br_is_root_bridge(br)) 118 if (br_is_root_bridge(br))
112 br->bridge_max_age = t; 119 br->bridge_max_age = t;
120 return 0;
113} 121}
114 122
115static ssize_t store_max_age(struct device *d, struct device_attribute *attr, 123static ssize_t store_max_age(struct device *d, struct device_attribute *attr,
@@ -126,9 +134,10 @@ static ssize_t show_ageing_time(struct device *d,
126 return sprintf(buf, "%lu\n", jiffies_to_clock_t(br->ageing_time)); 134 return sprintf(buf, "%lu\n", jiffies_to_clock_t(br->ageing_time));
127} 135}
128 136
129static void set_ageing_time(struct net_bridge *br, unsigned long val) 137static int set_ageing_time(struct net_bridge *br, unsigned long val)
130{ 138{
131 br->ageing_time = clock_t_to_jiffies(val); 139 br->ageing_time = clock_t_to_jiffies(val);
140 return 0;
132} 141}
133 142
134static ssize_t store_ageing_time(struct device *d, 143static ssize_t store_ageing_time(struct device *d,
@@ -180,9 +189,10 @@ static ssize_t show_priority(struct device *d, struct device_attribute *attr,
180 (br->bridge_id.prio[0] << 8) | br->bridge_id.prio[1]); 189 (br->bridge_id.prio[0] << 8) | br->bridge_id.prio[1]);
181} 190}
182 191
183static void set_priority(struct net_bridge *br, unsigned long val) 192static int set_priority(struct net_bridge *br, unsigned long val)
184{ 193{
185 br_stp_set_bridge_priority(br, (u16) val); 194 br_stp_set_bridge_priority(br, (u16) val);
195 return 0;
186} 196}
187 197
188static ssize_t store_priority(struct device *d, struct device_attribute *attr, 198static ssize_t store_priority(struct device *d, struct device_attribute *attr,
diff --git a/net/core/dev.c b/net/core/dev.c
index 60c51f765887..e719ed29310f 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1991,8 +1991,13 @@ static void net_tx_action(struct softirq_action *h)
1991 spin_unlock(root_lock); 1991 spin_unlock(root_lock);
1992 } else { 1992 } else {
1993 if (!test_bit(__QDISC_STATE_DEACTIVATED, 1993 if (!test_bit(__QDISC_STATE_DEACTIVATED,
1994 &q->state)) 1994 &q->state)) {
1995 __netif_reschedule(q); 1995 __netif_reschedule(q);
1996 } else {
1997 smp_mb__before_clear_bit();
1998 clear_bit(__QDISC_STATE_SCHED,
1999 &q->state);
2000 }
1996 } 2001 }
1997 } 2002 }
1998 } 2003 }
diff --git a/net/ipv4/inet_timewait_sock.c b/net/ipv4/inet_timewait_sock.c
index d985bd613d25..743f011b9a84 100644
--- a/net/ipv4/inet_timewait_sock.c
+++ b/net/ipv4/inet_timewait_sock.c
@@ -409,3 +409,38 @@ out:
409} 409}
410 410
411EXPORT_SYMBOL_GPL(inet_twdr_twcal_tick); 411EXPORT_SYMBOL_GPL(inet_twdr_twcal_tick);
412
413void inet_twsk_purge(struct net *net, struct inet_hashinfo *hashinfo,
414 struct inet_timewait_death_row *twdr, int family)
415{
416 struct inet_timewait_sock *tw;
417 struct sock *sk;
418 struct hlist_node *node;
419 int h;
420
421 local_bh_disable();
422 for (h = 0; h < (hashinfo->ehash_size); h++) {
423 struct inet_ehash_bucket *head =
424 inet_ehash_bucket(hashinfo, h);
425 rwlock_t *lock = inet_ehash_lockp(hashinfo, h);
426restart:
427 write_lock(lock);
428 sk_for_each(sk, node, &head->twchain) {
429
430 tw = inet_twsk(sk);
431 if (!net_eq(twsk_net(tw), net) ||
432 tw->tw_family != family)
433 continue;
434
435 atomic_inc(&tw->tw_refcnt);
436 write_unlock(lock);
437 inet_twsk_deschedule(tw, twdr);
438 inet_twsk_put(tw);
439
440 goto restart;
441 }
442 write_unlock(lock);
443 }
444 local_bh_enable();
445}
446EXPORT_SYMBOL_GPL(inet_twsk_purge);
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 44c1e934824b..1b4fee20fc93 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -2376,6 +2376,7 @@ static int __net_init tcp_sk_init(struct net *net)
2376static void __net_exit tcp_sk_exit(struct net *net) 2376static void __net_exit tcp_sk_exit(struct net *net)
2377{ 2377{
2378 inet_ctl_sock_destroy(net->ipv4.tcp_sock); 2378 inet_ctl_sock_destroy(net->ipv4.tcp_sock);
2379 inet_twsk_purge(net, &tcp_hashinfo, &tcp_death_row, AF_INET);
2379} 2380}
2380 2381
2381static struct pernet_operations __net_initdata tcp_sk_ops = { 2382static struct pernet_operations __net_initdata tcp_sk_ops = {
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 5b90b369ccb2..b585c850a89a 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -2148,6 +2148,7 @@ static int tcpv6_net_init(struct net *net)
2148static void tcpv6_net_exit(struct net *net) 2148static void tcpv6_net_exit(struct net *net)
2149{ 2149{
2150 inet_ctl_sock_destroy(net->ipv6.tcp_sk); 2150 inet_ctl_sock_destroy(net->ipv6.tcp_sk);
2151 inet_twsk_purge(net, &tcp_hashinfo, &tcp_death_row, AF_INET6);
2151} 2152}
2152 2153
2153static struct pernet_operations tcpv6_net_ops = { 2154static struct pernet_operations tcpv6_net_ops = {
diff --git a/net/netfilter/nf_conntrack_irc.c b/net/netfilter/nf_conntrack_irc.c
index 1b1226d6653f..20633fdf7e6b 100644
--- a/net/netfilter/nf_conntrack_irc.c
+++ b/net/netfilter/nf_conntrack_irc.c
@@ -68,11 +68,21 @@ static const char *const dccprotos[] = {
68static int parse_dcc(char *data, const char *data_end, u_int32_t *ip, 68static int parse_dcc(char *data, const char *data_end, u_int32_t *ip,
69 u_int16_t *port, char **ad_beg_p, char **ad_end_p) 69 u_int16_t *port, char **ad_beg_p, char **ad_end_p)
70{ 70{
71 char *tmp;
72
71 /* at least 12: "AAAAAAAA P\1\n" */ 73 /* at least 12: "AAAAAAAA P\1\n" */
72 while (*data++ != ' ') 74 while (*data++ != ' ')
73 if (data > data_end - 12) 75 if (data > data_end - 12)
74 return -1; 76 return -1;
75 77
78 /* Make sure we have a newline character within the packet boundaries
79 * because simple_strtoul parses until the first invalid character. */
80 for (tmp = data; tmp <= data_end; tmp++)
81 if (*tmp == '\n')
82 break;
83 if (tmp > data_end || *tmp != '\n')
84 return -1;
85
76 *ad_beg_p = data; 86 *ad_beg_p = data;
77 *ip = simple_strtoul(data, &data, 10); 87 *ip = simple_strtoul(data, &data, 10);
78 88
diff --git a/net/netfilter/nf_conntrack_proto_gre.c b/net/netfilter/nf_conntrack_proto_gre.c
index 654a4f7f12c6..9bd03967fea4 100644
--- a/net/netfilter/nf_conntrack_proto_gre.c
+++ b/net/netfilter/nf_conntrack_proto_gre.c
@@ -45,12 +45,12 @@ static LIST_HEAD(gre_keymap_list);
45 45
46void nf_ct_gre_keymap_flush(void) 46void nf_ct_gre_keymap_flush(void)
47{ 47{
48 struct list_head *pos, *n; 48 struct nf_ct_gre_keymap *km, *tmp;
49 49
50 write_lock_bh(&nf_ct_gre_lock); 50 write_lock_bh(&nf_ct_gre_lock);
51 list_for_each_safe(pos, n, &gre_keymap_list) { 51 list_for_each_entry_safe(km, tmp, &gre_keymap_list, list) {
52 list_del(pos); 52 list_del(&km->list);
53 kfree(pos); 53 kfree(km);
54 } 54 }
55 write_unlock_bh(&nf_ct_gre_lock); 55 write_unlock_bh(&nf_ct_gre_lock);
56} 56}
@@ -97,10 +97,14 @@ int nf_ct_gre_keymap_add(struct nf_conn *ct, enum ip_conntrack_dir dir,
97 kmp = &help->help.ct_pptp_info.keymap[dir]; 97 kmp = &help->help.ct_pptp_info.keymap[dir];
98 if (*kmp) { 98 if (*kmp) {
99 /* check whether it's a retransmission */ 99 /* check whether it's a retransmission */
100 read_lock_bh(&nf_ct_gre_lock);
100 list_for_each_entry(km, &gre_keymap_list, list) { 101 list_for_each_entry(km, &gre_keymap_list, list) {
101 if (gre_key_cmpfn(km, t) && km == *kmp) 102 if (gre_key_cmpfn(km, t) && km == *kmp) {
103 read_unlock_bh(&nf_ct_gre_lock);
102 return 0; 104 return 0;
105 }
103 } 106 }
107 read_unlock_bh(&nf_ct_gre_lock);
104 pr_debug("trying to override keymap_%s for ct %p\n", 108 pr_debug("trying to override keymap_%s for ct %p\n",
105 dir == IP_CT_DIR_REPLY ? "reply" : "orig", ct); 109 dir == IP_CT_DIR_REPLY ? "reply" : "orig", ct);
106 return -EEXIST; 110 return -EEXIST;
diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c
index 2f9bbc058b48..1fa306be60fb 100644
--- a/net/netfilter/nf_conntrack_sip.c
+++ b/net/netfilter/nf_conntrack_sip.c
@@ -1193,7 +1193,6 @@ static const struct sip_handler sip_handlers[] = {
1193static int process_sip_response(struct sk_buff *skb, 1193static int process_sip_response(struct sk_buff *skb,
1194 const char **dptr, unsigned int *datalen) 1194 const char **dptr, unsigned int *datalen)
1195{ 1195{
1196 static const struct sip_handler *handler;
1197 enum ip_conntrack_info ctinfo; 1196 enum ip_conntrack_info ctinfo;
1198 struct nf_conn *ct = nf_ct_get(skb, &ctinfo); 1197 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
1199 unsigned int matchoff, matchlen; 1198 unsigned int matchoff, matchlen;
@@ -1214,6 +1213,8 @@ static int process_sip_response(struct sk_buff *skb,
1214 dataoff = matchoff + matchlen + 1; 1213 dataoff = matchoff + matchlen + 1;
1215 1214
1216 for (i = 0; i < ARRAY_SIZE(sip_handlers); i++) { 1215 for (i = 0; i < ARRAY_SIZE(sip_handlers); i++) {
1216 const struct sip_handler *handler;
1217
1217 handler = &sip_handlers[i]; 1218 handler = &sip_handlers[i];
1218 if (handler->response == NULL) 1219 if (handler->response == NULL)
1219 continue; 1220 continue;
@@ -1228,13 +1229,14 @@ static int process_sip_response(struct sk_buff *skb,
1228static int process_sip_request(struct sk_buff *skb, 1229static int process_sip_request(struct sk_buff *skb,
1229 const char **dptr, unsigned int *datalen) 1230 const char **dptr, unsigned int *datalen)
1230{ 1231{
1231 static const struct sip_handler *handler;
1232 enum ip_conntrack_info ctinfo; 1232 enum ip_conntrack_info ctinfo;
1233 struct nf_conn *ct = nf_ct_get(skb, &ctinfo); 1233 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
1234 unsigned int matchoff, matchlen; 1234 unsigned int matchoff, matchlen;
1235 unsigned int cseq, i; 1235 unsigned int cseq, i;
1236 1236
1237 for (i = 0; i < ARRAY_SIZE(sip_handlers); i++) { 1237 for (i = 0; i < ARRAY_SIZE(sip_handlers); i++) {
1238 const struct sip_handler *handler;
1239
1238 handler = &sip_handlers[i]; 1240 handler = &sip_handlers[i];
1239 if (handler->request == NULL) 1241 if (handler->request == NULL)
1240 continue; 1242 continue;