Blame view

security/root_plug.c 3.9 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  /*
   * Root Plug sample LSM module
   *
   * Originally written for a Linux Journal.
   *
   * Copyright (C) 2002 Greg Kroah-Hartman <greg@kroah.com>
   *
   * Prevents any programs running with egid == 0 if a specific USB device
   * is not present in the system.  Yes, it can be gotten around, but is a
   * nice starting point for people to play with, and learn the LSM
   * interface.
   *
   * If you want to turn this into something with a semblance of security,
   * you need to hook the task_* functions also.
   *
   * See http://www.linuxjournal.com/article.php?sid=6279 for more information
   * about this code.
   *
   *	This program is free software; you can redistribute it and/or
   *	modify it under the terms of the GNU General Public License as
   *	published by the Free Software Foundation, version 2 of the
   *	License.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
  #include <linux/module.h>
  #include <linux/kernel.h>
  #include <linux/init.h>
  #include <linux/security.h>
  #include <linux/usb.h>
  
  /* flag to keep track of how we were registered */
  static int secondary;
  
  /* default is a generic type of usb to serial converter */
  static int vendor_id = 0x0557;
  static int product_id = 0x2008;
  
  module_param(vendor_id, uint, 0400);
  MODULE_PARM_DESC(vendor_id, "USB Vendor ID of device to look for");
  
  module_param(product_id, uint, 0400);
  MODULE_PARM_DESC(product_id, "USB Product ID of device to look for");
  
  /* should we print out debug messages */
  static int debug = 0;
  
  module_param(debug, bool, 0600);
  MODULE_PARM_DESC(debug, "Debug enabled or not");
  
  #if defined(CONFIG_SECURITY_ROOTPLUG_MODULE)
  #define MY_NAME THIS_MODULE->name
  #else
  #define MY_NAME "root_plug"
  #endif
  
  #define root_dbg(fmt, arg...)					\
  	do {							\
  		if (debug)					\
  			printk(KERN_DEBUG "%s: %s: " fmt ,	\
  				MY_NAME , __FUNCTION__ , 	\
  				## arg);			\
  	} while (0)
  
  static int rootplug_bprm_check_security (struct linux_binprm *bprm)
  {
  	struct usb_device *dev;
  
  	root_dbg("file %s, e_uid = %d, e_gid = %d
  ",
  		 bprm->filename, bprm->e_uid, bprm->e_gid);
  
  	if (bprm->e_gid == 0) {
  		dev = usb_find_device(vendor_id, product_id);
  		if (!dev) {
  			root_dbg("e_gid = 0, and device not found, "
  				 "task not allowed to run...
  ");
  			return -EPERM;
  		}
  		usb_put_dev(dev);
  	}
  
  	return 0;
  }
  
  static struct security_operations rootplug_security_ops = {
  	/* Use the capability functions for some of the hooks */
  	.ptrace =			cap_ptrace,
  	.capget =			cap_capget,
  	.capset_check =			cap_capset_check,
  	.capset_set =			cap_capset_set,
  	.capable =			cap_capable,
  
  	.bprm_apply_creds =		cap_bprm_apply_creds,
  	.bprm_set_security =		cap_bprm_set_security,
  
  	.task_post_setuid =		cap_task_post_setuid,
  	.task_reparent_to_init =	cap_task_reparent_to_init,
  
  	.bprm_check_security =		rootplug_bprm_check_security,
  };
  
  static int __init rootplug_init (void)
  {
  	/* register ourselves with the security framework */
  	if (register_security (&rootplug_security_ops)) {
  		printk (KERN_INFO 
  			"Failure registering Root Plug module with the kernel
  ");
  		/* try registering with primary module */
  		if (mod_reg_security (MY_NAME, &rootplug_security_ops)) {
  			printk (KERN_INFO "Failure registering Root Plug "
  				" module with primary security module.
  ");
  			return -EINVAL;
  		}
  		secondary = 1;
  	}
  	printk (KERN_INFO "Root Plug module initialized, "
  		"vendor_id = %4.4x, product id = %4.4x
  ", vendor_id, product_id);
  	return 0;
  }
  
  static void __exit rootplug_exit (void)
  {
  	/* remove ourselves from the security framework */
  	if (secondary) {
  		if (mod_unreg_security (MY_NAME, &rootplug_security_ops))
  			printk (KERN_INFO "Failure unregistering Root Plug "
  				" module with primary module.
  ");
  	} else { 
  		if (unregister_security (&rootplug_security_ops)) {
  			printk (KERN_INFO "Failure unregistering Root Plug "
  				"module with the kernel
  ");
  		}
  	}
  	printk (KERN_INFO "Root Plug module removed
  ");
  }
  
  security_initcall (rootplug_init);
  module_exit (rootplug_exit);
  
  MODULE_DESCRIPTION("Root Plug sample LSM module, written for Linux Journal article");
  MODULE_LICENSE("GPL");