Branch data Line data Source code
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 : :
21 : : static void mon_stop(struct mon_bus *mbus);
22 : : static void mon_dissolve(struct mon_bus *mbus, struct usb_bus *ubus);
23 : : static void mon_bus_drop(struct kref *r);
24 : : static void mon_bus_init(struct usb_bus *ubus);
25 : :
26 : : DEFINE_MUTEX(mon_lock);
27 : :
28 : : struct mon_bus mon_bus0; /* Pseudo bus meaning "all buses" */
29 : : static 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 : : */
36 : 0 : void mon_reader_add(struct mon_bus *mbus, struct mon_reader *r)
37 : : {
38 : 0 : unsigned long flags;
39 : 0 : struct list_head *p;
40 : :
41 : 0 : spin_lock_irqsave(&mbus->lock, flags);
42 [ # # ]: 0 : if (mbus->nreaders == 0) {
43 [ # # ]: 0 : if (mbus == &mon_bus0) {
44 [ # # ]: 0 : list_for_each (p, &mon_buses) {
45 : 0 : struct mon_bus *m1;
46 : 0 : m1 = list_entry(p, struct mon_bus, bus_link);
47 : 0 : m1->u_bus->monitored = 1;
48 : : }
49 : : } else {
50 : 0 : mbus->u_bus->monitored = 1;
51 : : }
52 : : }
53 : 0 : mbus->nreaders++;
54 : 0 : list_add_tail(&r->r_link, &mbus->r_list);
55 : 0 : spin_unlock_irqrestore(&mbus->lock, flags);
56 : :
57 : 0 : kref_get(&mbus->ref);
58 : 0 : }
59 : :
60 : : /*
61 : : * Unlink reader from the bus.
62 : : *
63 : : * This is called with mon_lock taken, so we can decrement mbus->ref.
64 : : */
65 : 0 : void mon_reader_del(struct mon_bus *mbus, struct mon_reader *r)
66 : : {
67 : 0 : unsigned long flags;
68 : :
69 : 0 : spin_lock_irqsave(&mbus->lock, flags);
70 [ # # ]: 0 : list_del(&r->r_link);
71 : 0 : --mbus->nreaders;
72 [ # # ]: 0 : if (mbus->nreaders == 0)
73 : 0 : mon_stop(mbus);
74 : 0 : spin_unlock_irqrestore(&mbus->lock, flags);
75 : :
76 : 0 : kref_put(&mbus->ref, mon_bus_drop);
77 : 0 : }
78 : :
79 : : /*
80 : : */
81 : 0 : static void mon_bus_submit(struct mon_bus *mbus, struct urb *urb)
82 : : {
83 : 0 : unsigned long flags;
84 : 0 : struct list_head *pos;
85 : 0 : struct mon_reader *r;
86 : :
87 : 0 : spin_lock_irqsave(&mbus->lock, flags);
88 : 0 : mbus->cnt_events++;
89 [ # # ]: 0 : list_for_each (pos, &mbus->r_list) {
90 : 0 : r = list_entry(pos, struct mon_reader, r_link);
91 : 0 : r->rnf_submit(r->r_data, urb);
92 : : }
93 : 0 : spin_unlock_irqrestore(&mbus->lock, flags);
94 : 0 : }
95 : :
96 : 0 : static void mon_submit(struct usb_bus *ubus, struct urb *urb)
97 : : {
98 : 0 : struct mon_bus *mbus;
99 : :
100 : 0 : mbus = ubus->mon_bus;
101 [ # # ]: 0 : if (mbus != NULL)
102 : 0 : mon_bus_submit(mbus, urb);
103 : 0 : mon_bus_submit(&mon_bus0, urb);
104 : 0 : }
105 : :
106 : : /*
107 : : */
108 : 0 : static void mon_bus_submit_error(struct mon_bus *mbus, struct urb *urb, int error)
109 : : {
110 : 0 : unsigned long flags;
111 : 0 : struct list_head *pos;
112 : 0 : struct mon_reader *r;
113 : :
114 : 0 : spin_lock_irqsave(&mbus->lock, flags);
115 : 0 : mbus->cnt_events++;
116 [ # # ]: 0 : list_for_each (pos, &mbus->r_list) {
117 : 0 : r = list_entry(pos, struct mon_reader, r_link);
118 : 0 : r->rnf_error(r->r_data, urb, error);
119 : : }
120 : 0 : spin_unlock_irqrestore(&mbus->lock, flags);
121 : 0 : }
122 : :
123 : 0 : static void mon_submit_error(struct usb_bus *ubus, struct urb *urb, int error)
124 : : {
125 : 0 : struct mon_bus *mbus;
126 : :
127 : 0 : mbus = ubus->mon_bus;
128 [ # # ]: 0 : if (mbus != NULL)
129 : 0 : mon_bus_submit_error(mbus, urb, error);
130 : 0 : mon_bus_submit_error(&mon_bus0, urb, error);
131 : 0 : }
132 : :
133 : : /*
134 : : */
135 : 0 : static void mon_bus_complete(struct mon_bus *mbus, struct urb *urb, int status)
136 : : {
137 : 0 : unsigned long flags;
138 : 0 : struct list_head *pos;
139 : 0 : struct mon_reader *r;
140 : :
141 : 0 : spin_lock_irqsave(&mbus->lock, flags);
142 : 0 : mbus->cnt_events++;
143 [ # # ]: 0 : list_for_each (pos, &mbus->r_list) {
144 : 0 : r = list_entry(pos, struct mon_reader, r_link);
145 : 0 : r->rnf_complete(r->r_data, urb, status);
146 : : }
147 : 0 : spin_unlock_irqrestore(&mbus->lock, flags);
148 : 0 : }
149 : :
150 : 0 : static void mon_complete(struct usb_bus *ubus, struct urb *urb, int status)
151 : : {
152 : 0 : struct mon_bus *mbus;
153 : :
154 : 0 : mbus = ubus->mon_bus;
155 [ # # ]: 0 : if (mbus != NULL)
156 : 0 : mon_bus_complete(mbus, urb, status);
157 : 0 : mon_bus_complete(&mon_bus0, urb, status);
158 : 0 : }
159 : :
160 : : /* int (*unlink_urb) (struct urb *urb, int status); */
161 : :
162 : : /*
163 : : * Stop monitoring.
164 : : */
165 : 0 : static void mon_stop(struct mon_bus *mbus)
166 : : {
167 : 0 : struct usb_bus *ubus;
168 : 0 : struct list_head *p;
169 : :
170 [ # # ]: 0 : if (mbus == &mon_bus0) {
171 [ # # ]: 0 : list_for_each (p, &mon_buses) {
172 : 0 : mbus = list_entry(p, struct mon_bus, bus_link);
173 : : /*
174 : : * We do not change nreaders here, so rely on mon_lock.
175 : : */
176 [ # # # # ]: 0 : if (mbus->nreaders == 0 && (ubus = mbus->u_bus) != NULL)
177 : 0 : 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 [ # # # # ]: 0 : if (mon_bus0.nreaders == 0 && (ubus = mbus->u_bus) != NULL) {
185 : 0 : ubus->monitored = 0;
186 : 0 : mb();
187 : : }
188 : : }
189 : 0 : }
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 : : */
197 : 0 : static void mon_bus_add(struct usb_bus *ubus)
198 : : {
199 : 0 : mon_bus_init(ubus);
200 : 0 : mutex_lock(&mon_lock);
201 [ # # ]: 0 : if (mon_bus0.nreaders != 0)
202 : 0 : ubus->monitored = 1;
203 : 0 : mutex_unlock(&mon_lock);
204 : 0 : }
205 : :
206 : : /*
207 : : * Remove a USB bus (either from rmmod foo-hcd or from a hot-remove event).
208 : : */
209 : 0 : static void mon_bus_remove(struct usb_bus *ubus)
210 : : {
211 : 0 : struct mon_bus *mbus = ubus->mon_bus;
212 : :
213 : 0 : mutex_lock(&mon_lock);
214 [ # # ]: 0 : list_del(&mbus->bus_link);
215 [ # # ]: 0 : if (mbus->text_inited)
216 : 0 : mon_text_del(mbus);
217 [ # # ]: 0 : if (mbus->bin_inited)
218 : 0 : mon_bin_del(mbus);
219 : :
220 : 0 : mon_dissolve(mbus, ubus);
221 : 0 : kref_put(&mbus->ref, mon_bus_drop);
222 : 0 : mutex_unlock(&mon_lock);
223 : 0 : }
224 : :
225 : 0 : static int mon_notify(struct notifier_block *self, unsigned long action,
226 : : void *dev)
227 : : {
228 [ # # # ]: 0 : switch (action) {
229 : 0 : case USB_BUS_ADD:
230 : 0 : mon_bus_add(dev);
231 : 0 : break;
232 : 0 : case USB_BUS_REMOVE:
233 : 0 : mon_bus_remove(dev);
234 : : }
235 : 0 : return NOTIFY_OK;
236 : : }
237 : :
238 : : static struct notifier_block mon_nb = {
239 : : .notifier_call = mon_notify,
240 : : };
241 : :
242 : : /*
243 : : * Ops
244 : : */
245 : : static 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 : : */
254 : 0 : static void mon_dissolve(struct mon_bus *mbus, struct usb_bus *ubus)
255 : : {
256 : :
257 [ # # ]: 0 : if (ubus->monitored) {
258 : 0 : ubus->monitored = 0;
259 : 0 : mb();
260 : : }
261 : :
262 : 0 : ubus->mon_bus = NULL;
263 : 0 : mbus->u_bus = NULL;
264 : 0 : mb();
265 : :
266 : : /* We want synchronize_irq() here, but that needs an argument. */
267 : : }
268 : :
269 : : /*
270 : : */
271 : 0 : static void mon_bus_drop(struct kref *r)
272 : : {
273 : 0 : struct mon_bus *mbus = container_of(r, struct mon_bus, ref);
274 : 0 : kfree(mbus);
275 : 0 : }
276 : :
277 : : /*
278 : : * Initialize a bus for us:
279 : : * - allocate mon_bus
280 : : * - refcount USB bus struct
281 : : * - link
282 : : */
283 : 0 : static void mon_bus_init(struct usb_bus *ubus)
284 : : {
285 : 0 : struct mon_bus *mbus;
286 : :
287 : 0 : mbus = kzalloc(sizeof(struct mon_bus), GFP_KERNEL);
288 [ # # ]: 0 : if (mbus == NULL)
289 : 0 : goto err_alloc;
290 : 0 : kref_init(&mbus->ref);
291 : 0 : spin_lock_init(&mbus->lock);
292 : 0 : 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 : 0 : mbus->u_bus = ubus;
299 : 0 : ubus->mon_bus = mbus;
300 : :
301 : 0 : mbus->text_inited = mon_text_add(mbus, ubus);
302 : 0 : mbus->bin_inited = mon_bin_add(mbus, ubus);
303 : :
304 : 0 : mutex_lock(&mon_lock);
305 : 0 : list_add_tail(&mbus->bus_link, &mon_buses);
306 : 0 : mutex_unlock(&mon_lock);
307 : 0 : return;
308 : :
309 : : err_alloc:
310 : 0 : return;
311 : : }
312 : :
313 : 21 : static void mon_bus0_init(void)
314 : : {
315 : 21 : struct mon_bus *mbus = &mon_bus0;
316 : :
317 : 21 : kref_init(&mbus->ref);
318 : 21 : spin_lock_init(&mbus->lock);
319 : 21 : INIT_LIST_HEAD(&mbus->r_list);
320 : :
321 : 21 : mbus->text_inited = mon_text_add(mbus, NULL);
322 : 21 : mbus->bin_inited = mon_bin_add(mbus, NULL);
323 : 21 : }
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 : : */
333 : 0 : struct mon_bus *mon_bus_lookup(unsigned int num)
334 : : {
335 : 0 : struct list_head *p;
336 : 0 : struct mon_bus *mbus;
337 : :
338 [ # # ]: 0 : if (num == 0) {
339 : : return &mon_bus0;
340 : : }
341 [ # # ]: 0 : list_for_each (p, &mon_buses) {
342 : 0 : mbus = list_entry(p, struct mon_bus, bus_link);
343 [ # # ]: 0 : if (mbus->u_bus->busnum == num) {
344 : 0 : return mbus;
345 : : }
346 : : }
347 : : return NULL;
348 : : }
349 : :
350 : 21 : static int __init mon_init(void)
351 : : {
352 : 21 : struct usb_bus *ubus;
353 : 21 : int rc, id;
354 : :
355 [ - + ]: 21 : if ((rc = mon_text_init()) != 0)
356 : 0 : goto err_text;
357 [ - + ]: 21 : if ((rc = mon_bin_init()) != 0)
358 : 0 : goto err_bin;
359 : :
360 : 21 : mon_bus0_init();
361 : :
362 [ - + ]: 21 : if (usb_mon_register(&mon_ops_0) != 0) {
363 : 0 : printk(KERN_NOTICE TAG ": unable to register with the core\n");
364 : 0 : rc = -ENODEV;
365 : 0 : goto err_reg;
366 : : }
367 : : // MOD_INC_USE_COUNT(which_module?);
368 : :
369 : 21 : mutex_lock(&usb_bus_idr_lock);
370 [ - + ]: 21 : idr_for_each_entry(&usb_bus_idr, ubus, id)
371 : 0 : mon_bus_init(ubus);
372 : 21 : usb_register_notify(&mon_nb);
373 : 21 : mutex_unlock(&usb_bus_idr_lock);
374 : 21 : return 0;
375 : :
376 : : err_reg:
377 : 0 : mon_bin_exit();
378 : 0 : err_bin:
379 : 0 : mon_text_exit();
380 : : err_text:
381 : : return rc;
382 : : }
383 : :
384 : 0 : static void __exit mon_exit(void)
385 : : {
386 : 0 : struct mon_bus *mbus;
387 : 0 : struct list_head *p;
388 : :
389 : 0 : usb_unregister_notify(&mon_nb);
390 : 0 : usb_mon_deregister();
391 : :
392 : 0 : mutex_lock(&mon_lock);
393 : :
394 [ # # ]: 0 : while (!list_empty(&mon_buses)) {
395 : 0 : p = mon_buses.next;
396 : 0 : mbus = list_entry(p, struct mon_bus, bus_link);
397 [ # # ]: 0 : list_del(p);
398 : :
399 [ # # ]: 0 : if (mbus->text_inited)
400 : 0 : mon_text_del(mbus);
401 [ # # ]: 0 : if (mbus->bin_inited)
402 : 0 : 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 [ # # ]: 0 : if (mbus->nreaders) {
410 : 0 : printk(KERN_ERR TAG
411 : : ": Outstanding opens (%d) on usb%d, leaking...\n",
412 : 0 : mbus->nreaders, mbus->u_bus->busnum);
413 : 0 : kref_get(&mbus->ref); /* Force leak */
414 : : }
415 : :
416 [ # # ]: 0 : mon_dissolve(mbus, mbus->u_bus);
417 : 0 : kref_put(&mbus->ref, mon_bus_drop);
418 : : }
419 : :
420 : 0 : mbus = &mon_bus0;
421 [ # # ]: 0 : if (mbus->text_inited)
422 : 0 : mon_text_del(mbus);
423 [ # # ]: 0 : if (mbus->bin_inited)
424 : 0 : mon_bin_del(mbus);
425 : :
426 : 0 : mutex_unlock(&mon_lock);
427 : :
428 : 0 : mon_text_exit();
429 : 0 : mon_bin_exit();
430 : 0 : }
431 : :
432 : : module_init(mon_init);
433 : : module_exit(mon_exit);
434 : :
435 : : MODULE_LICENSE("GPL");
|