aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEvgeniy Polyakov <zbr@ioremap.net>2010-02-02 18:58:48 -0500
committerDavid S. Miller <davem@davemloft.net>2010-02-02 18:58:48 -0500
commitf98bfbd78c37c5946cc53089da32a5f741efdeb7 (patch)
tree885c756a95f28d4d00868f6eb06ab9c45f11b2e2
parenta4c89051c83693e6cd5655b90300ec23a35e04f1 (diff)
connector: Delete buggy notification code.
On Tue, Feb 02, 2010 at 02:57:14PM -0800, Greg KH (gregkh@suse.de) wrote: > > There are at least two ways to fix it: using a big cannon and a small > > one. The former way is to disable notification registration, since it is > > not used by anyone at all. Second way is to check whether calling > > process is root and its destination group is -1 (kind of priveledged > > one) before command is dispatched to workqueue. > > Well if no one is using it, removing it makes the most sense, right? > > No objection from me, care to make up a patch either way for this? Getting it is not used, let's drop support for notifications about (un)registered events from connector. Another option was to check credentials on receiving, but we can always restore it without bugs if needed, but genetlink has a wider code base and none complained, that userspace can not get notification when some other clients were (un)registered. Kudos for Sebastian Krahmer <krahmer@suse.de>, who found a bug in the code. Signed-off-by: Evgeniy Polyakov <zbr@ioremap.net> Acked-by: Greg Kroah-Hartman <gregkh@suse.de> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/connector/connector.c175
-rw-r--r--include/linux/connector.h32
2 files changed, 0 insertions, 207 deletions
diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c
index f06024668f99..537c29ac4487 100644
--- a/drivers/connector/connector.c
+++ b/drivers/connector/connector.c
@@ -36,17 +36,6 @@ MODULE_LICENSE("GPL");
36MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>"); 36MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>");
37MODULE_DESCRIPTION("Generic userspace <-> kernelspace connector."); 37MODULE_DESCRIPTION("Generic userspace <-> kernelspace connector.");
38 38
39static u32 cn_idx = CN_IDX_CONNECTOR;
40static u32 cn_val = CN_VAL_CONNECTOR;
41
42module_param(cn_idx, uint, 0);
43module_param(cn_val, uint, 0);
44MODULE_PARM_DESC(cn_idx, "Connector's main device idx.");
45MODULE_PARM_DESC(cn_val, "Connector's main device val.");
46
47static DEFINE_MUTEX(notify_lock);
48static LIST_HEAD(notify_list);
49
50static struct cn_dev cdev; 39static struct cn_dev cdev;
51 40
52static int cn_already_initialized; 41static int cn_already_initialized;
@@ -210,54 +199,6 @@ static void cn_rx_skb(struct sk_buff *__skb)
210} 199}
211 200
212/* 201/*
213 * Notification routing.
214 *
215 * Gets id and checks if there are notification request for it's idx
216 * and val. If there are such requests notify the listeners with the
217 * given notify event.
218 *
219 */
220static void cn_notify(struct cb_id *id, u32 notify_event)
221{
222 struct cn_ctl_entry *ent;
223
224 mutex_lock(&notify_lock);
225 list_for_each_entry(ent, &notify_list, notify_entry) {
226 int i;
227 struct cn_notify_req *req;
228 struct cn_ctl_msg *ctl = ent->msg;
229 int idx_found, val_found;
230
231 idx_found = val_found = 0;
232
233 req = (struct cn_notify_req *)ctl->data;
234 for (i = 0; i < ctl->idx_notify_num; ++i, ++req) {
235 if (id->idx >= req->first &&
236 id->idx < req->first + req->range) {
237 idx_found = 1;
238 break;
239 }
240 }
241
242 for (i = 0; i < ctl->val_notify_num; ++i, ++req) {
243 if (id->val >= req->first &&
244 id->val < req->first + req->range) {
245 val_found = 1;
246 break;
247 }
248 }
249
250 if (idx_found && val_found) {
251 struct cn_msg m = { .ack = notify_event, };
252
253 memcpy(&m.id, id, sizeof(m.id));
254 cn_netlink_send(&m, ctl->group, GFP_KERNEL);
255 }
256 }
257 mutex_unlock(&notify_lock);
258}
259
260/*
261 * Callback add routing - adds callback with given ID and name. 202 * Callback add routing - adds callback with given ID and name.
262 * If there is registered callback with the same ID it will not be added. 203 * If there is registered callback with the same ID it will not be added.
263 * 204 *
@@ -276,8 +217,6 @@ int cn_add_callback(struct cb_id *id, char *name,
276 if (err) 217 if (err)
277 return err; 218 return err;
278 219
279 cn_notify(id, 0);
280
281 return 0; 220 return 0;
282} 221}
283EXPORT_SYMBOL_GPL(cn_add_callback); 222EXPORT_SYMBOL_GPL(cn_add_callback);
@@ -295,111 +234,9 @@ void cn_del_callback(struct cb_id *id)
295 struct cn_dev *dev = &cdev; 234 struct cn_dev *dev = &cdev;
296 235
297 cn_queue_del_callback(dev->cbdev, id); 236 cn_queue_del_callback(dev->cbdev, id);
298 cn_notify(id, 1);
299} 237}
300EXPORT_SYMBOL_GPL(cn_del_callback); 238EXPORT_SYMBOL_GPL(cn_del_callback);
301 239
302/*
303 * Checks two connector's control messages to be the same.
304 * Returns 1 if they are the same or if the first one is corrupted.
305 */
306static int cn_ctl_msg_equals(struct cn_ctl_msg *m1, struct cn_ctl_msg *m2)
307{
308 int i;
309 struct cn_notify_req *req1, *req2;
310
311 if (m1->idx_notify_num != m2->idx_notify_num)
312 return 0;
313
314 if (m1->val_notify_num != m2->val_notify_num)
315 return 0;
316
317 if (m1->len != m2->len)
318 return 0;
319
320 if ((m1->idx_notify_num + m1->val_notify_num) * sizeof(*req1) !=
321 m1->len)
322 return 1;
323
324 req1 = (struct cn_notify_req *)m1->data;
325 req2 = (struct cn_notify_req *)m2->data;
326
327 for (i = 0; i < m1->idx_notify_num; ++i) {
328 if (req1->first != req2->first || req1->range != req2->range)
329 return 0;
330 req1++;
331 req2++;
332 }
333
334 for (i = 0; i < m1->val_notify_num; ++i) {
335 if (req1->first != req2->first || req1->range != req2->range)
336 return 0;
337 req1++;
338 req2++;
339 }
340
341 return 1;
342}
343
344/*
345 * Main connector device's callback.
346 *
347 * Used for notification of a request's processing.
348 */
349static void cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
350{
351 struct cn_ctl_msg *ctl;
352 struct cn_ctl_entry *ent;
353 u32 size;
354
355 if (msg->len < sizeof(*ctl))
356 return;
357
358 ctl = (struct cn_ctl_msg *)msg->data;
359
360 size = (sizeof(*ctl) + ((ctl->idx_notify_num +
361 ctl->val_notify_num) *
362 sizeof(struct cn_notify_req)));
363
364 if (msg->len != size)
365 return;
366
367 if (ctl->len + sizeof(*ctl) != msg->len)
368 return;
369
370 /*
371 * Remove notification.
372 */
373 if (ctl->group == 0) {
374 struct cn_ctl_entry *n;
375
376 mutex_lock(&notify_lock);
377 list_for_each_entry_safe(ent, n, &notify_list, notify_entry) {
378 if (cn_ctl_msg_equals(ent->msg, ctl)) {
379 list_del(&ent->notify_entry);
380 kfree(ent);
381 }
382 }
383 mutex_unlock(&notify_lock);
384
385 return;
386 }
387
388 size += sizeof(*ent);
389
390 ent = kzalloc(size, GFP_KERNEL);
391 if (!ent)
392 return;
393
394 ent->msg = (struct cn_ctl_msg *)(ent + 1);
395
396 memcpy(ent->msg, ctl, size - sizeof(*ent));
397
398 mutex_lock(&notify_lock);
399 list_add(&ent->notify_entry, &notify_list);
400 mutex_unlock(&notify_lock);
401}
402
403static int cn_proc_show(struct seq_file *m, void *v) 240static int cn_proc_show(struct seq_file *m, void *v)
404{ 241{
405 struct cn_queue_dev *dev = cdev.cbdev; 242 struct cn_queue_dev *dev = cdev.cbdev;
@@ -437,11 +274,8 @@ static const struct file_operations cn_file_ops = {
437static int __devinit cn_init(void) 274static int __devinit cn_init(void)
438{ 275{
439 struct cn_dev *dev = &cdev; 276 struct cn_dev *dev = &cdev;
440 int err;
441 277
442 dev->input = cn_rx_skb; 278 dev->input = cn_rx_skb;
443 dev->id.idx = cn_idx;
444 dev->id.val = cn_val;
445 279
446 dev->nls = netlink_kernel_create(&init_net, NETLINK_CONNECTOR, 280 dev->nls = netlink_kernel_create(&init_net, NETLINK_CONNECTOR,
447 CN_NETLINK_USERS + 0xf, 281 CN_NETLINK_USERS + 0xf,
@@ -457,14 +291,6 @@ static int __devinit cn_init(void)
457 291
458 cn_already_initialized = 1; 292 cn_already_initialized = 1;
459 293
460 err = cn_add_callback(&dev->id, "connector", &cn_callback);
461 if (err) {
462 cn_already_initialized = 0;
463 cn_queue_free_dev(dev->cbdev);
464 netlink_kernel_release(dev->nls);
465 return -EINVAL;
466 }
467
468 proc_net_fops_create(&init_net, "connector", S_IRUGO, &cn_file_ops); 294 proc_net_fops_create(&init_net, "connector", S_IRUGO, &cn_file_ops);
469 295
470 return 0; 296 return 0;
@@ -478,7 +304,6 @@ static void __devexit cn_fini(void)
478 304
479 proc_net_remove(&init_net, "connector"); 305 proc_net_remove(&init_net, "connector");
480 306
481 cn_del_callback(&dev->id);
482 cn_queue_free_dev(dev->cbdev); 307 cn_queue_free_dev(dev->cbdev);
483 netlink_kernel_release(dev->nls); 308 netlink_kernel_release(dev->nls);
484} 309}
diff --git a/include/linux/connector.h b/include/linux/connector.h
index 72ba63eb83c5..3a779ffba60b 100644
--- a/include/linux/connector.h
+++ b/include/linux/connector.h
@@ -24,9 +24,6 @@
24 24
25#include <linux/types.h> 25#include <linux/types.h>
26 26
27#define CN_IDX_CONNECTOR 0xffffffff
28#define CN_VAL_CONNECTOR 0xffffffff
29
30/* 27/*
31 * Process Events connector unique ids -- used for message routing 28 * Process Events connector unique ids -- used for message routing
32 */ 29 */
@@ -75,30 +72,6 @@ struct cn_msg {
75 __u8 data[0]; 72 __u8 data[0];
76}; 73};
77 74
78/*
79 * Notify structure - requests notification about
80 * registering/unregistering idx/val in range [first, first+range].
81 */
82struct cn_notify_req {
83 __u32 first;
84 __u32 range;
85};
86
87/*
88 * Main notification control message
89 * *_notify_num - number of appropriate cn_notify_req structures after
90 * this struct.
91 * group - notification receiver's idx.
92 * len - total length of the attached data.
93 */
94struct cn_ctl_msg {
95 __u32 idx_notify_num;
96 __u32 val_notify_num;
97 __u32 group;
98 __u32 len;
99 __u8 data[0];
100};
101
102#ifdef __KERNEL__ 75#ifdef __KERNEL__
103 76
104#include <asm/atomic.h> 77#include <asm/atomic.h>
@@ -151,11 +124,6 @@ struct cn_callback_entry {
151 u32 seq, group; 124 u32 seq, group;
152}; 125};
153 126
154struct cn_ctl_entry {
155 struct list_head notify_entry;
156 struct cn_ctl_msg *msg;
157};
158
159struct cn_dev { 127struct cn_dev {
160 struct cb_id id; 128 struct cb_id id;
161 129