aboutsummaryrefslogtreecommitdiffstats
path: root/net/atm/resources.c
diff options
context:
space:
mode:
authorStanislaw Gruszka <stf_xl@wp.pl>2005-11-29 19:16:21 -0500
committerDavid S. Miller <davem@davemloft.net>2005-11-29 19:16:21 -0500
commitaaaaaadbe7a663d110814db50fcbe7d320eb4c32 (patch)
tree316bdbd49e3a6ac7a78cad8797d148f79a343d45 /net/atm/resources.c
parent49693280262a149e5430d3401e263e464c88334a (diff)
[ATM]: avoid race conditions related to atm_devs list
Use semaphore to protect atm_devs list, as no one need access to it from interrupt context. Avoid race conditions between atm_dev_register(), atm_dev_lookup() and atm_dev_deregister(). Fix double spin_unlock() bug. Signed-off-by: Stanislaw Gruszka <stf_xl@wp.pl> Signed-off-by: Chas Williams <chas@cmf.nrl.navy.mil> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/atm/resources.c')
-rw-r--r--net/atm/resources.c36
1 files changed, 17 insertions, 19 deletions
diff --git a/net/atm/resources.c b/net/atm/resources.c
index 35f3ceb76868..ad533b02b84f 100644
--- a/net/atm/resources.c
+++ b/net/atm/resources.c
@@ -25,7 +25,7 @@
25 25
26 26
27LIST_HEAD(atm_devs); 27LIST_HEAD(atm_devs);
28DEFINE_SPINLOCK(atm_dev_lock); 28DECLARE_MUTEX(atm_dev_mutex);
29 29
30static struct atm_dev *__alloc_atm_dev(const char *type) 30static struct atm_dev *__alloc_atm_dev(const char *type)
31{ 31{
@@ -52,7 +52,7 @@ static struct atm_dev *__atm_dev_lookup(int number)
52 52
53 list_for_each(p, &atm_devs) { 53 list_for_each(p, &atm_devs) {
54 dev = list_entry(p, struct atm_dev, dev_list); 54 dev = list_entry(p, struct atm_dev, dev_list);
55 if ((dev->ops) && (dev->number == number)) { 55 if (dev->number == number) {
56 atm_dev_hold(dev); 56 atm_dev_hold(dev);
57 return dev; 57 return dev;
58 } 58 }
@@ -64,9 +64,9 @@ struct atm_dev *atm_dev_lookup(int number)
64{ 64{
65 struct atm_dev *dev; 65 struct atm_dev *dev;
66 66
67 spin_lock(&atm_dev_lock); 67 down(&atm_dev_mutex);
68 dev = __atm_dev_lookup(number); 68 dev = __atm_dev_lookup(number);
69 spin_unlock(&atm_dev_lock); 69 up(&atm_dev_mutex);
70 return dev; 70 return dev;
71} 71}
72 72
@@ -81,11 +81,11 @@ struct atm_dev *atm_dev_register(const char *type, const struct atmdev_ops *ops,
81 type); 81 type);
82 return NULL; 82 return NULL;
83 } 83 }
84 spin_lock(&atm_dev_lock); 84 down(&atm_dev_mutex);
85 if (number != -1) { 85 if (number != -1) {
86 if ((inuse = __atm_dev_lookup(number))) { 86 if ((inuse = __atm_dev_lookup(number))) {
87 atm_dev_put(inuse); 87 atm_dev_put(inuse);
88 spin_unlock(&atm_dev_lock); 88 up(&atm_dev_mutex);
89 kfree(dev); 89 kfree(dev);
90 return NULL; 90 return NULL;
91 } 91 }
@@ -105,19 +105,17 @@ struct atm_dev *atm_dev_register(const char *type, const struct atmdev_ops *ops,
105 memset(&dev->flags, 0, sizeof(dev->flags)); 105 memset(&dev->flags, 0, sizeof(dev->flags));
106 memset(&dev->stats, 0, sizeof(dev->stats)); 106 memset(&dev->stats, 0, sizeof(dev->stats));
107 atomic_set(&dev->refcnt, 1); 107 atomic_set(&dev->refcnt, 1);
108 list_add_tail(&dev->dev_list, &atm_devs);
109 spin_unlock(&atm_dev_lock);
110 108
111 if (atm_proc_dev_register(dev) < 0) { 109 if (atm_proc_dev_register(dev) < 0) {
112 printk(KERN_ERR "atm_dev_register: " 110 printk(KERN_ERR "atm_dev_register: "
113 "atm_proc_dev_register failed for dev %s\n", 111 "atm_proc_dev_register failed for dev %s\n",
114 type); 112 type);
115 spin_lock(&atm_dev_lock); 113 up(&atm_dev_mutex);
116 list_del(&dev->dev_list);
117 spin_unlock(&atm_dev_lock);
118 kfree(dev); 114 kfree(dev);
119 return NULL; 115 return NULL;
120 } 116 }
117 list_add_tail(&dev->dev_list, &atm_devs);
118 up(&atm_dev_mutex);
121 119
122 return dev; 120 return dev;
123} 121}
@@ -129,9 +127,9 @@ void atm_dev_deregister(struct atm_dev *dev)
129 127
130 atm_proc_dev_deregister(dev); 128 atm_proc_dev_deregister(dev);
131 129
132 spin_lock(&atm_dev_lock); 130 down(&atm_dev_mutex);
133 list_del(&dev->dev_list); 131 list_del(&dev->dev_list);
134 spin_unlock(&atm_dev_lock); 132 up(&atm_dev_mutex);
135 133
136 warning_time = jiffies; 134 warning_time = jiffies;
137 while (atomic_read(&dev->refcnt) != 1) { 135 while (atomic_read(&dev->refcnt) != 1) {
@@ -211,16 +209,16 @@ int atm_dev_ioctl(unsigned int cmd, void __user *arg)
211 return -EFAULT; 209 return -EFAULT;
212 if (get_user(len, &iobuf->length)) 210 if (get_user(len, &iobuf->length))
213 return -EFAULT; 211 return -EFAULT;
214 spin_lock(&atm_dev_lock); 212 down(&atm_dev_mutex);
215 list_for_each(p, &atm_devs) 213 list_for_each(p, &atm_devs)
216 size += sizeof(int); 214 size += sizeof(int);
217 if (size > len) { 215 if (size > len) {
218 spin_unlock(&atm_dev_lock); 216 up(&atm_dev_mutex);
219 return -E2BIG; 217 return -E2BIG;
220 } 218 }
221 tmp_buf = kmalloc(size, GFP_ATOMIC); 219 tmp_buf = kmalloc(size, GFP_ATOMIC);
222 if (!tmp_buf) { 220 if (!tmp_buf) {
223 spin_unlock(&atm_dev_lock); 221 up(&atm_dev_mutex);
224 return -ENOMEM; 222 return -ENOMEM;
225 } 223 }
226 tmp_p = tmp_buf; 224 tmp_p = tmp_buf;
@@ -228,7 +226,7 @@ int atm_dev_ioctl(unsigned int cmd, void __user *arg)
228 dev = list_entry(p, struct atm_dev, dev_list); 226 dev = list_entry(p, struct atm_dev, dev_list);
229 *tmp_p++ = dev->number; 227 *tmp_p++ = dev->number;
230 } 228 }
231 spin_unlock(&atm_dev_lock); 229 up(&atm_dev_mutex);
232 error = ((copy_to_user(buf, tmp_buf, size)) || 230 error = ((copy_to_user(buf, tmp_buf, size)) ||
233 put_user(size, &iobuf->length)) 231 put_user(size, &iobuf->length))
234 ? -EFAULT : 0; 232 ? -EFAULT : 0;
@@ -415,13 +413,13 @@ static __inline__ void *dev_get_idx(loff_t left)
415 413
416void *atm_dev_seq_start(struct seq_file *seq, loff_t *pos) 414void *atm_dev_seq_start(struct seq_file *seq, loff_t *pos)
417{ 415{
418 spin_lock(&atm_dev_lock); 416 down(&atm_dev_mutex);
419 return *pos ? dev_get_idx(*pos) : (void *) 1; 417 return *pos ? dev_get_idx(*pos) : (void *) 1;
420} 418}
421 419
422void atm_dev_seq_stop(struct seq_file *seq, void *v) 420void atm_dev_seq_stop(struct seq_file *seq, void *v)
423{ 421{
424 spin_unlock(&atm_dev_lock); 422 up(&atm_dev_mutex);
425} 423}
426 424
427void *atm_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos) 425void *atm_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos)