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>

authored by Evgeniy Polyakov and committed by David S. Miller f98bfbd7 a4c89051

-207
-175
drivers/connector/connector.c
··· 36 MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>"); 37 MODULE_DESCRIPTION("Generic userspace <-> kernelspace connector."); 38 39 - static u32 cn_idx = CN_IDX_CONNECTOR; 40 - static u32 cn_val = CN_VAL_CONNECTOR; 41 - 42 - module_param(cn_idx, uint, 0); 43 - module_param(cn_val, uint, 0); 44 - MODULE_PARM_DESC(cn_idx, "Connector's main device idx."); 45 - MODULE_PARM_DESC(cn_val, "Connector's main device val."); 46 - 47 - static DEFINE_MUTEX(notify_lock); 48 - static LIST_HEAD(notify_list); 49 - 50 static struct cn_dev cdev; 51 52 static int cn_already_initialized; ··· 199 } 200 201 /* 202 - * Notification routing. 203 - * 204 - * Gets id and checks if there are notification request for it's idx 205 - * and val. If there are such requests notify the listeners with the 206 - * given notify event. 207 - * 208 - */ 209 - static void cn_notify(struct cb_id *id, u32 notify_event) 210 - { 211 - struct cn_ctl_entry *ent; 212 - 213 - mutex_lock(&notify_lock); 214 - list_for_each_entry(ent, &notify_list, notify_entry) { 215 - int i; 216 - struct cn_notify_req *req; 217 - struct cn_ctl_msg *ctl = ent->msg; 218 - int idx_found, val_found; 219 - 220 - idx_found = val_found = 0; 221 - 222 - req = (struct cn_notify_req *)ctl->data; 223 - for (i = 0; i < ctl->idx_notify_num; ++i, ++req) { 224 - if (id->idx >= req->first && 225 - id->idx < req->first + req->range) { 226 - idx_found = 1; 227 - break; 228 - } 229 - } 230 - 231 - for (i = 0; i < ctl->val_notify_num; ++i, ++req) { 232 - if (id->val >= req->first && 233 - id->val < req->first + req->range) { 234 - val_found = 1; 235 - break; 236 - } 237 - } 238 - 239 - if (idx_found && val_found) { 240 - struct cn_msg m = { .ack = notify_event, }; 241 - 242 - memcpy(&m.id, id, sizeof(m.id)); 243 - cn_netlink_send(&m, ctl->group, GFP_KERNEL); 244 - } 245 - } 246 - mutex_unlock(&notify_lock); 247 - } 248 - 249 - /* 250 * Callback add routing - adds callback with given ID and name. 251 * If there is registered callback with the same ID it will not be added. 252 * ··· 217 if (err) 218 return err; 219 220 - cn_notify(id, 0); 221 - 222 return 0; 223 } 224 EXPORT_SYMBOL_GPL(cn_add_callback); ··· 234 struct cn_dev *dev = &cdev; 235 236 cn_queue_del_callback(dev->cbdev, id); 237 - cn_notify(id, 1); 238 } 239 EXPORT_SYMBOL_GPL(cn_del_callback); 240 - 241 - /* 242 - * Checks two connector's control messages to be the same. 243 - * Returns 1 if they are the same or if the first one is corrupted. 244 - */ 245 - static int cn_ctl_msg_equals(struct cn_ctl_msg *m1, struct cn_ctl_msg *m2) 246 - { 247 - int i; 248 - struct cn_notify_req *req1, *req2; 249 - 250 - if (m1->idx_notify_num != m2->idx_notify_num) 251 - return 0; 252 - 253 - if (m1->val_notify_num != m2->val_notify_num) 254 - return 0; 255 - 256 - if (m1->len != m2->len) 257 - return 0; 258 - 259 - if ((m1->idx_notify_num + m1->val_notify_num) * sizeof(*req1) != 260 - m1->len) 261 - return 1; 262 - 263 - req1 = (struct cn_notify_req *)m1->data; 264 - req2 = (struct cn_notify_req *)m2->data; 265 - 266 - for (i = 0; i < m1->idx_notify_num; ++i) { 267 - if (req1->first != req2->first || req1->range != req2->range) 268 - return 0; 269 - req1++; 270 - req2++; 271 - } 272 - 273 - for (i = 0; i < m1->val_notify_num; ++i) { 274 - if (req1->first != req2->first || req1->range != req2->range) 275 - return 0; 276 - req1++; 277 - req2++; 278 - } 279 - 280 - return 1; 281 - } 282 - 283 - /* 284 - * Main connector device's callback. 285 - * 286 - * Used for notification of a request's processing. 287 - */ 288 - static void cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp) 289 - { 290 - struct cn_ctl_msg *ctl; 291 - struct cn_ctl_entry *ent; 292 - u32 size; 293 - 294 - if (msg->len < sizeof(*ctl)) 295 - return; 296 - 297 - ctl = (struct cn_ctl_msg *)msg->data; 298 - 299 - size = (sizeof(*ctl) + ((ctl->idx_notify_num + 300 - ctl->val_notify_num) * 301 - sizeof(struct cn_notify_req))); 302 - 303 - if (msg->len != size) 304 - return; 305 - 306 - if (ctl->len + sizeof(*ctl) != msg->len) 307 - return; 308 - 309 - /* 310 - * Remove notification. 311 - */ 312 - if (ctl->group == 0) { 313 - struct cn_ctl_entry *n; 314 - 315 - mutex_lock(&notify_lock); 316 - list_for_each_entry_safe(ent, n, &notify_list, notify_entry) { 317 - if (cn_ctl_msg_equals(ent->msg, ctl)) { 318 - list_del(&ent->notify_entry); 319 - kfree(ent); 320 - } 321 - } 322 - mutex_unlock(&notify_lock); 323 - 324 - return; 325 - } 326 - 327 - size += sizeof(*ent); 328 - 329 - ent = kzalloc(size, GFP_KERNEL); 330 - if (!ent) 331 - return; 332 - 333 - ent->msg = (struct cn_ctl_msg *)(ent + 1); 334 - 335 - memcpy(ent->msg, ctl, size - sizeof(*ent)); 336 - 337 - mutex_lock(&notify_lock); 338 - list_add(&ent->notify_entry, &notify_list); 339 - mutex_unlock(&notify_lock); 340 - } 341 342 static int cn_proc_show(struct seq_file *m, void *v) 343 { ··· 274 static int __devinit cn_init(void) 275 { 276 struct cn_dev *dev = &cdev; 277 - int err; 278 279 dev->input = cn_rx_skb; 280 - dev->id.idx = cn_idx; 281 - dev->id.val = cn_val; 282 283 dev->nls = netlink_kernel_create(&init_net, NETLINK_CONNECTOR, 284 CN_NETLINK_USERS + 0xf, ··· 291 292 cn_already_initialized = 1; 293 294 - err = cn_add_callback(&dev->id, "connector", &cn_callback); 295 - if (err) { 296 - cn_already_initialized = 0; 297 - cn_queue_free_dev(dev->cbdev); 298 - netlink_kernel_release(dev->nls); 299 - return -EINVAL; 300 - } 301 - 302 proc_net_fops_create(&init_net, "connector", S_IRUGO, &cn_file_ops); 303 304 return 0; ··· 304 305 proc_net_remove(&init_net, "connector"); 306 307 - cn_del_callback(&dev->id); 308 cn_queue_free_dev(dev->cbdev); 309 netlink_kernel_release(dev->nls); 310 }
··· 36 MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>"); 37 MODULE_DESCRIPTION("Generic userspace <-> kernelspace connector."); 38 39 static struct cn_dev cdev; 40 41 static int cn_already_initialized; ··· 210 } 211 212 /* 213 * Callback add routing - adds callback with given ID and name. 214 * If there is registered callback with the same ID it will not be added. 215 * ··· 276 if (err) 277 return err; 278 279 return 0; 280 } 281 EXPORT_SYMBOL_GPL(cn_add_callback); ··· 295 struct cn_dev *dev = &cdev; 296 297 cn_queue_del_callback(dev->cbdev, id); 298 } 299 EXPORT_SYMBOL_GPL(cn_del_callback); 300 301 static int cn_proc_show(struct seq_file *m, void *v) 302 { ··· 437 static int __devinit cn_init(void) 438 { 439 struct cn_dev *dev = &cdev; 440 441 dev->input = cn_rx_skb; 442 443 dev->nls = netlink_kernel_create(&init_net, NETLINK_CONNECTOR, 444 CN_NETLINK_USERS + 0xf, ··· 457 458 cn_already_initialized = 1; 459 460 proc_net_fops_create(&init_net, "connector", S_IRUGO, &cn_file_ops); 461 462 return 0; ··· 478 479 proc_net_remove(&init_net, "connector"); 480 481 cn_queue_free_dev(dev->cbdev); 482 netlink_kernel_release(dev->nls); 483 }
-32
include/linux/connector.h
··· 24 25 #include <linux/types.h> 26 27 - #define CN_IDX_CONNECTOR 0xffffffff 28 - #define CN_VAL_CONNECTOR 0xffffffff 29 - 30 /* 31 * Process Events connector unique ids -- used for message routing 32 */ ··· 69 70 __u16 len; /* Length of the following data */ 71 __u16 flags; 72 - __u8 data[0]; 73 - }; 74 - 75 - /* 76 - * Notify structure - requests notification about 77 - * registering/unregistering idx/val in range [first, first+range]. 78 - */ 79 - struct cn_notify_req { 80 - __u32 first; 81 - __u32 range; 82 - }; 83 - 84 - /* 85 - * Main notification control message 86 - * *_notify_num - number of appropriate cn_notify_req structures after 87 - * this struct. 88 - * group - notification receiver's idx. 89 - * len - total length of the attached data. 90 - */ 91 - struct cn_ctl_msg { 92 - __u32 idx_notify_num; 93 - __u32 val_notify_num; 94 - __u32 group; 95 - __u32 len; 96 __u8 data[0]; 97 }; 98 ··· 122 struct cn_callback_data data; 123 124 u32 seq, group; 125 - }; 126 - 127 - struct cn_ctl_entry { 128 - struct list_head notify_entry; 129 - struct cn_ctl_msg *msg; 130 }; 131 132 struct cn_dev {
··· 24 25 #include <linux/types.h> 26 27 /* 28 * Process Events connector unique ids -- used for message routing 29 */ ··· 72 73 __u16 len; /* Length of the following data */ 74 __u16 flags; 75 __u8 data[0]; 76 }; 77 ··· 149 struct cn_callback_data data; 150 151 u32 seq, group; 152 }; 153 154 struct cn_dev {