mon_main.c (9313B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * The USB Monitor, inspired by Dave Harding's USBMon. 4 * 5 * mon_main.c: Main file, module initiation and exit, registrations, etc. 6 * 7 * Copyright (C) 2005 Pete Zaitcev (zaitcev@redhat.com) 8 */ 9 10#include <linux/kernel.h> 11#include <linux/module.h> 12#include <linux/usb.h> 13#include <linux/usb/hcd.h> 14#include <linux/slab.h> 15#include <linux/notifier.h> 16#include <linux/mutex.h> 17 18#include "usb_mon.h" 19 20 21static void mon_stop(struct mon_bus *mbus); 22static void mon_dissolve(struct mon_bus *mbus, struct usb_bus *ubus); 23static void mon_bus_drop(struct kref *r); 24static void mon_bus_init(struct usb_bus *ubus); 25 26DEFINE_MUTEX(mon_lock); 27 28struct mon_bus mon_bus0; /* Pseudo bus meaning "all buses" */ 29static LIST_HEAD(mon_buses); /* All buses we know: struct mon_bus */ 30 31/* 32 * Link a reader into the bus. 33 * 34 * This must be called with mon_lock taken because of mbus->ref. 35 */ 36void mon_reader_add(struct mon_bus *mbus, struct mon_reader *r) 37{ 38 unsigned long flags; 39 struct list_head *p; 40 41 spin_lock_irqsave(&mbus->lock, flags); 42 if (mbus->nreaders == 0) { 43 if (mbus == &mon_bus0) { 44 list_for_each (p, &mon_buses) { 45 struct mon_bus *m1; 46 m1 = list_entry(p, struct mon_bus, bus_link); 47 m1->u_bus->monitored = 1; 48 } 49 } else { 50 mbus->u_bus->monitored = 1; 51 } 52 } 53 mbus->nreaders++; 54 list_add_tail(&r->r_link, &mbus->r_list); 55 spin_unlock_irqrestore(&mbus->lock, flags); 56 57 kref_get(&mbus->ref); 58} 59 60/* 61 * Unlink reader from the bus. 62 * 63 * This is called with mon_lock taken, so we can decrement mbus->ref. 64 */ 65void mon_reader_del(struct mon_bus *mbus, struct mon_reader *r) 66{ 67 unsigned long flags; 68 69 spin_lock_irqsave(&mbus->lock, flags); 70 list_del(&r->r_link); 71 --mbus->nreaders; 72 if (mbus->nreaders == 0) 73 mon_stop(mbus); 74 spin_unlock_irqrestore(&mbus->lock, flags); 75 76 kref_put(&mbus->ref, mon_bus_drop); 77} 78 79/* 80 */ 81static void mon_bus_submit(struct mon_bus *mbus, struct urb *urb) 82{ 83 unsigned long flags; 84 struct list_head *pos; 85 struct mon_reader *r; 86 87 spin_lock_irqsave(&mbus->lock, flags); 88 mbus->cnt_events++; 89 list_for_each (pos, &mbus->r_list) { 90 r = list_entry(pos, struct mon_reader, r_link); 91 r->rnf_submit(r->r_data, urb); 92 } 93 spin_unlock_irqrestore(&mbus->lock, flags); 94} 95 96static void mon_submit(struct usb_bus *ubus, struct urb *urb) 97{ 98 struct mon_bus *mbus; 99 100 mbus = ubus->mon_bus; 101 if (mbus != NULL) 102 mon_bus_submit(mbus, urb); 103 mon_bus_submit(&mon_bus0, urb); 104} 105 106/* 107 */ 108static void mon_bus_submit_error(struct mon_bus *mbus, struct urb *urb, int error) 109{ 110 unsigned long flags; 111 struct list_head *pos; 112 struct mon_reader *r; 113 114 spin_lock_irqsave(&mbus->lock, flags); 115 mbus->cnt_events++; 116 list_for_each (pos, &mbus->r_list) { 117 r = list_entry(pos, struct mon_reader, r_link); 118 r->rnf_error(r->r_data, urb, error); 119 } 120 spin_unlock_irqrestore(&mbus->lock, flags); 121} 122 123static void mon_submit_error(struct usb_bus *ubus, struct urb *urb, int error) 124{ 125 struct mon_bus *mbus; 126 127 mbus = ubus->mon_bus; 128 if (mbus != NULL) 129 mon_bus_submit_error(mbus, urb, error); 130 mon_bus_submit_error(&mon_bus0, urb, error); 131} 132 133/* 134 */ 135static void mon_bus_complete(struct mon_bus *mbus, struct urb *urb, int status) 136{ 137 unsigned long flags; 138 struct list_head *pos; 139 struct mon_reader *r; 140 141 spin_lock_irqsave(&mbus->lock, flags); 142 mbus->cnt_events++; 143 list_for_each (pos, &mbus->r_list) { 144 r = list_entry(pos, struct mon_reader, r_link); 145 r->rnf_complete(r->r_data, urb, status); 146 } 147 spin_unlock_irqrestore(&mbus->lock, flags); 148} 149 150static void mon_complete(struct usb_bus *ubus, struct urb *urb, int status) 151{ 152 struct mon_bus *mbus; 153 154 mbus = ubus->mon_bus; 155 if (mbus != NULL) 156 mon_bus_complete(mbus, urb, status); 157 mon_bus_complete(&mon_bus0, urb, status); 158} 159 160/* int (*unlink_urb) (struct urb *urb, int status); */ 161 162/* 163 * Stop monitoring. 164 */ 165static void mon_stop(struct mon_bus *mbus) 166{ 167 struct usb_bus *ubus; 168 struct list_head *p; 169 170 if (mbus == &mon_bus0) { 171 list_for_each (p, &mon_buses) { 172 mbus = list_entry(p, struct mon_bus, bus_link); 173 /* 174 * We do not change nreaders here, so rely on mon_lock. 175 */ 176 if (mbus->nreaders == 0 && (ubus = mbus->u_bus) != NULL) 177 ubus->monitored = 0; 178 } 179 } else { 180 /* 181 * A stop can be called for a dissolved mon_bus in case of 182 * a reader staying across an rmmod foo_hcd, so test ->u_bus. 183 */ 184 if (mon_bus0.nreaders == 0 && (ubus = mbus->u_bus) != NULL) { 185 ubus->monitored = 0; 186 mb(); 187 } 188 } 189} 190 191/* 192 * Add a USB bus (usually by a modprobe foo-hcd) 193 * 194 * This does not return an error code because the core cannot care less 195 * if monitoring is not established. 196 */ 197static void mon_bus_add(struct usb_bus *ubus) 198{ 199 mon_bus_init(ubus); 200 mutex_lock(&mon_lock); 201 if (mon_bus0.nreaders != 0) 202 ubus->monitored = 1; 203 mutex_unlock(&mon_lock); 204} 205 206/* 207 * Remove a USB bus (either from rmmod foo-hcd or from a hot-remove event). 208 */ 209static void mon_bus_remove(struct usb_bus *ubus) 210{ 211 struct mon_bus *mbus = ubus->mon_bus; 212 213 mutex_lock(&mon_lock); 214 list_del(&mbus->bus_link); 215 if (mbus->text_inited) 216 mon_text_del(mbus); 217 if (mbus->bin_inited) 218 mon_bin_del(mbus); 219 220 mon_dissolve(mbus, ubus); 221 kref_put(&mbus->ref, mon_bus_drop); 222 mutex_unlock(&mon_lock); 223} 224 225static int mon_notify(struct notifier_block *self, unsigned long action, 226 void *dev) 227{ 228 switch (action) { 229 case USB_BUS_ADD: 230 mon_bus_add(dev); 231 break; 232 case USB_BUS_REMOVE: 233 mon_bus_remove(dev); 234 } 235 return NOTIFY_OK; 236} 237 238static struct notifier_block mon_nb = { 239 .notifier_call = mon_notify, 240}; 241 242/* 243 * Ops 244 */ 245static const struct usb_mon_operations mon_ops_0 = { 246 .urb_submit = mon_submit, 247 .urb_submit_error = mon_submit_error, 248 .urb_complete = mon_complete, 249}; 250 251/* 252 * Tear usb_bus and mon_bus apart. 253 */ 254static void mon_dissolve(struct mon_bus *mbus, struct usb_bus *ubus) 255{ 256 257 if (ubus->monitored) { 258 ubus->monitored = 0; 259 mb(); 260 } 261 262 ubus->mon_bus = NULL; 263 mbus->u_bus = NULL; 264 mb(); 265 266 /* We want synchronize_irq() here, but that needs an argument. */ 267} 268 269/* 270 */ 271static void mon_bus_drop(struct kref *r) 272{ 273 struct mon_bus *mbus = container_of(r, struct mon_bus, ref); 274 kfree(mbus); 275} 276 277/* 278 * Initialize a bus for us: 279 * - allocate mon_bus 280 * - refcount USB bus struct 281 * - link 282 */ 283static void mon_bus_init(struct usb_bus *ubus) 284{ 285 struct mon_bus *mbus; 286 287 mbus = kzalloc(sizeof(struct mon_bus), GFP_KERNEL); 288 if (mbus == NULL) 289 goto err_alloc; 290 kref_init(&mbus->ref); 291 spin_lock_init(&mbus->lock); 292 INIT_LIST_HEAD(&mbus->r_list); 293 294 /* 295 * We don't need to take a reference to ubus, because we receive 296 * a notification if the bus is about to be removed. 297 */ 298 mbus->u_bus = ubus; 299 ubus->mon_bus = mbus; 300 301 mbus->text_inited = mon_text_add(mbus, ubus); 302 mbus->bin_inited = mon_bin_add(mbus, ubus); 303 304 mutex_lock(&mon_lock); 305 list_add_tail(&mbus->bus_link, &mon_buses); 306 mutex_unlock(&mon_lock); 307 return; 308 309err_alloc: 310 return; 311} 312 313static void mon_bus0_init(void) 314{ 315 struct mon_bus *mbus = &mon_bus0; 316 317 kref_init(&mbus->ref); 318 spin_lock_init(&mbus->lock); 319 INIT_LIST_HEAD(&mbus->r_list); 320 321 mbus->text_inited = mon_text_add(mbus, NULL); 322 mbus->bin_inited = mon_bin_add(mbus, NULL); 323} 324 325/* 326 * Search a USB bus by number. Notice that USB bus numbers start from one, 327 * which we may later use to identify "all" with zero. 328 * 329 * This function must be called with mon_lock held. 330 * 331 * This is obviously inefficient and may be revised in the future. 332 */ 333struct mon_bus *mon_bus_lookup(unsigned int num) 334{ 335 struct list_head *p; 336 struct mon_bus *mbus; 337 338 if (num == 0) { 339 return &mon_bus0; 340 } 341 list_for_each (p, &mon_buses) { 342 mbus = list_entry(p, struct mon_bus, bus_link); 343 if (mbus->u_bus->busnum == num) { 344 return mbus; 345 } 346 } 347 return NULL; 348} 349 350static int __init mon_init(void) 351{ 352 struct usb_bus *ubus; 353 int rc, id; 354 355 if ((rc = mon_text_init()) != 0) 356 goto err_text; 357 if ((rc = mon_bin_init()) != 0) 358 goto err_bin; 359 360 mon_bus0_init(); 361 362 if (usb_mon_register(&mon_ops_0) != 0) { 363 printk(KERN_NOTICE TAG ": unable to register with the core\n"); 364 rc = -ENODEV; 365 goto err_reg; 366 } 367 // MOD_INC_USE_COUNT(which_module?); 368 369 mutex_lock(&usb_bus_idr_lock); 370 idr_for_each_entry(&usb_bus_idr, ubus, id) 371 mon_bus_init(ubus); 372 usb_register_notify(&mon_nb); 373 mutex_unlock(&usb_bus_idr_lock); 374 return 0; 375 376err_reg: 377 mon_bin_exit(); 378err_bin: 379 mon_text_exit(); 380err_text: 381 return rc; 382} 383 384static void __exit mon_exit(void) 385{ 386 struct mon_bus *mbus; 387 struct list_head *p; 388 389 usb_unregister_notify(&mon_nb); 390 usb_mon_deregister(); 391 392 mutex_lock(&mon_lock); 393 394 while (!list_empty(&mon_buses)) { 395 p = mon_buses.next; 396 mbus = list_entry(p, struct mon_bus, bus_link); 397 list_del(p); 398 399 if (mbus->text_inited) 400 mon_text_del(mbus); 401 if (mbus->bin_inited) 402 mon_bin_del(mbus); 403 404 /* 405 * This never happens, because the open/close paths in 406 * file level maintain module use counters and so rmmod fails 407 * before reaching here. However, better be safe... 408 */ 409 if (mbus->nreaders) { 410 printk(KERN_ERR TAG 411 ": Outstanding opens (%d) on usb%d, leaking...\n", 412 mbus->nreaders, mbus->u_bus->busnum); 413 kref_get(&mbus->ref); /* Force leak */ 414 } 415 416 mon_dissolve(mbus, mbus->u_bus); 417 kref_put(&mbus->ref, mon_bus_drop); 418 } 419 420 mbus = &mon_bus0; 421 if (mbus->text_inited) 422 mon_text_del(mbus); 423 if (mbus->bin_inited) 424 mon_bin_del(mbus); 425 426 mutex_unlock(&mon_lock); 427 428 mon_text_exit(); 429 mon_bin_exit(); 430} 431 432module_init(mon_init); 433module_exit(mon_exit); 434 435MODULE_LICENSE("GPL");