-
Notifications
You must be signed in to change notification settings - Fork 1
/
deadman.c
81 lines (69 loc) · 2.65 KB
/
deadman.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/usb.h>
#include <linux/reboot.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("pepa65 <[email protected]>, Greg Kroah-Hartman, Nate Brune");
MODULE_DESCRIPTION("Panic on removal of 'deadman' USB device (or insertion of any USB device).");
MODULE_PARM_DESC(id, "USB ID of the deadman device: 'id=0x1234abcd' (vendor 0x1234, product 0xabcd)");
MODULE_PARM_DESC(ins, "Panic on any USB device being inserted: 'ins=1'");
MODULE_PARM_DESC(off, "Don't turn the computer off on panic: 'off=0'");
MODULE_PARM_DESC(log, "No deadman messages in any logs: 'log=0'");
// Default USB device ID of trigger; override: id=0x1234abcd
static unsigned int id = 0xabcd1234;
module_param(id, int, 0644);
// Default: inserted USB devices don't trigger panic; override: ins=1
static int ins = 0;
module_param(ins, int, 0644);
// Default: computer turns off on panic; override: off=0
static int off = 1;
module_param(off, int, 0644);
// Default: messages logged on (de)activation and triggering, override: log=0
static int log = 1;
module_param(log, int, 0644);
static void start_panic(struct usb_device *dev){
struct device *mark;
for (mark = &dev->dev; mark; mark = mark->parent) mutex_unlock(&mark->mutex);
if (off){
if (log) printk("Powering off\n");
kernel_power_off();
}
if (log) pr_info("Not powering off\n");
}
static void usb_inserted(struct usb_device *dev){
unsigned int d = 0x10000*dev->descriptor.idVendor+dev->descriptor.idProduct;
if (log) pr_info("USB device 0x%08x inserted\n", d);
start_panic(dev);
}
static int usb_removed(struct usb_device *dev){
unsigned int d = 0x10000*dev->descriptor.idVendor+dev->descriptor.idProduct;
if (log) pr_info("USB device 0x%08x removed\n", d);
if (d == id) start_panic(dev);
return 0;
}
static int notify(struct notifier_block *self, unsigned long act, void *dev){
if (act == USB_DEVICE_REMOVE) usb_removed(dev);
if (ins && act == USB_DEVICE_ADD) usb_inserted(dev);
return 0;
}
static struct notifier_block usb_notify = {.notifier_call = notify};
static int __init deadman_init(void){
usb_register_notify(&usb_notify);
if (log){
if (id) pr_info("Watching removal of USB device 0x%08x\n", id);
if (ins) pr_info("Watching insertion of any USB device");
if (!ins && !id) pr_info("Loaded but not functional");
}
return 0;
}
module_init(deadman_init);
static void __exit deadman_exit(void) {
usb_unregister_notify(&usb_notify);
if (log){
if (id) pr_info("Stopped watching USB device 0x%08x\n", id);
if (ins) pr_info("Stopped watching insertion of USB devices");
if (!ins && !id) pr_info("Unloaded");
}
}
module_exit(deadman_exit);