]>
Commit | Line | Data |
---|---|---|
c0396172 | 1 | commit 076c54c5bcaed2081c0cba94a6f77c4d470236ad |
2 | Author: Ahmed S. Darwish <darwish.07@gmail.com> | |
3 | Date: Thu Mar 6 18:09:10 2008 +0200 | |
4 | ||
5 | Security: Introduce security= boot parameter | |
6 | ||
7 | Add the security= boot parameter. This is done to avoid LSM | |
8 | registration clashes in case of more than one bult-in module. | |
9 | ||
10 | User can choose a security module to enable at boot. If no | |
11 | security= boot parameter is specified, only the first LSM | |
12 | asking for registration will be loaded. An invalid security | |
13 | module name will be treated as if no module has been chosen. | |
14 | ||
15 | LSM modules must check now if they are allowed to register | |
16 | by calling security_module_enable(ops) first. Modify SELinux | |
17 | and SMACK to do so. | |
18 | ||
19 | Do not let SMACK register smackfs if it was not chosen on | |
20 | boot. Smackfs assumes that smack hooks are registered and | |
21 | the initial task security setup (swapper->security) is done. | |
22 | ||
23 | Signed-off-by: Ahmed S. Darwish <darwish.07@gmail.com> | |
24 | Acked-by: James Morris <jmorris@namei.org> | |
25 | ||
26 | diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt | |
27 | index 256a216..4b0f1ae 100644 | |
28 | --- a/Documentation/kernel-parameters.txt | |
29 | +++ b/Documentation/kernel-parameters.txt | |
30 | @@ -366,6 +366,12 @@ and is between 256 and 4096 characters. It is defined in the file | |
31 | possible to determine what the correct size should be. | |
32 | This option provides an override for these situations. | |
33 | ||
34 | + security= [SECURITY] Choose a security module to enable at boot. | |
35 | + If this boot parameter is not specified, only the first | |
36 | + security module asking for security registration will be | |
37 | + loaded. An invalid security module name will be treated | |
38 | + as if no module has been chosen. | |
39 | + | |
40 | capability.disable= | |
41 | [SECURITY] Disable capabilities. This would normally | |
42 | be used only if an alternative security model is to be | |
43 | diff --git a/include/linux/security.h b/include/linux/security.h | |
44 | index 697f228..f4116d6 100644 | |
45 | --- a/include/linux/security.h | |
46 | +++ b/include/linux/security.h | |
47 | @@ -36,6 +36,9 @@ | |
48 | ||
49 | extern unsigned securebits; | |
50 | ||
51 | +/* Maximum number of letters for an LSM name string */ | |
52 | +#define SECURITY_NAME_MAX 10 | |
53 | + | |
54 | struct ctl_table; | |
55 | struct audit_krule; | |
56 | ||
57 | @@ -137,6 +140,12 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) | |
58 | /** | |
59 | * struct security_operations - main security structure | |
60 | * | |
61 | + * Security module identifier. | |
62 | + * | |
63 | + * @name: | |
64 | + * A string that acts as a unique identifeir for the LSM with max number | |
65 | + * of characters = SECURITY_NAME_MAX. | |
66 | + * | |
67 | * Security hooks for program execution operations. | |
68 | * | |
69 | * @bprm_alloc_security: | |
70 | @@ -1270,6 +1279,8 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) | |
71 | * This is the main security structure. | |
72 | */ | |
73 | struct security_operations { | |
74 | + char name[SECURITY_NAME_MAX + 1]; | |
75 | + | |
76 | int (*ptrace) (struct task_struct * parent, struct task_struct * child); | |
77 | int (*capget) (struct task_struct * target, | |
78 | kernel_cap_t * effective, | |
79 | @@ -1537,6 +1548,7 @@ struct security_operations { | |
80 | ||
81 | /* prototypes */ | |
82 | extern int security_init (void); | |
83 | +extern int security_module_enable(struct security_operations *ops); | |
84 | extern int register_security (struct security_operations *ops); | |
85 | extern int mod_reg_security (const char *name, struct security_operations *ops); | |
86 | extern struct dentry *securityfs_create_file(const char *name, mode_t mode, | |
87 | diff --git a/security/dummy.c b/security/dummy.c | |
88 | index 1ac9f8e..d797a41 100644 | |
89 | --- a/security/dummy.c | |
90 | +++ b/security/dummy.c | |
91 | @@ -1017,7 +1017,9 @@ static inline void dummy_audit_rule_free(void *lsmrule) | |
92 | ||
93 | #endif /* CONFIG_AUDIT */ | |
94 | ||
95 | -struct security_operations dummy_security_ops; | |
96 | +struct security_operations dummy_security_ops = { | |
97 | + .name = "dummy", | |
98 | +}; | |
99 | ||
100 | #define set_to_dummy_if_null(ops, function) \ | |
101 | do { \ | |
102 | diff --git a/security/security.c b/security/security.c | |
103 | index 2ef593e..dd0c6ba 100644 | |
104 | --- a/security/security.c | |
105 | +++ b/security/security.c | |
106 | @@ -17,6 +17,8 @@ | |
107 | #include <linux/kernel.h> | |
108 | #include <linux/security.h> | |
109 | ||
110 | +/* Boot-time LSM user choice */ | |
111 | +static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1]; | |
112 | ||
113 | /* things that live in dummy.c */ | |
114 | extern struct security_operations dummy_security_ops; | |
115 | @@ -67,13 +69,47 @@ int __init security_init(void) | |
116 | return 0; | |
117 | } | |
118 | ||
119 | +/* Save user chosen LSM */ | |
120 | +static int __init choose_lsm(char *str) | |
121 | +{ | |
122 | + strncpy(chosen_lsm, str, SECURITY_NAME_MAX); | |
123 | + return 1; | |
124 | +} | |
125 | +__setup("security=", choose_lsm); | |
126 | + | |
127 | +/** | |
128 | + * security_module_enable - Load given security module on boot ? | |
129 | + * @ops: a pointer to the struct security_operations that is to be checked. | |
130 | + * | |
131 | + * Each LSM must pass this method before registering its own operations | |
132 | + * to avoid security registration races. This method may also be used | |
133 | + * to check if your LSM is currently loaded. | |
134 | + * | |
135 | + * Return true if: | |
136 | + * -The passed LSM is the one chosen by user at boot time, | |
137 | + * -or user didsn't specify a specific LSM and we're the first to ask | |
138 | + * for registeration permissoin, | |
139 | + * -or the passed LSM is currently loaded. | |
140 | + * Otherwise, return false. | |
141 | + */ | |
142 | +int __init security_module_enable(struct security_operations *ops) | |
143 | +{ | |
144 | + if (!*chosen_lsm) | |
145 | + strncpy(chosen_lsm, ops->name, SECURITY_NAME_MAX); | |
146 | + else if (strncmp(ops->name, chosen_lsm, SECURITY_NAME_MAX)) | |
147 | + return 0; | |
148 | + | |
149 | + return 1; | |
150 | +} | |
151 | + | |
152 | /** | |
153 | * register_security - registers a security framework with the kernel | |
154 | * @ops: a pointer to the struct security_options that is to be registered | |
155 | * | |
156 | * This function is to allow a security module to register itself with the | |
157 | * kernel security subsystem. Some rudimentary checking is done on the @ops | |
158 | - * value passed to this function. | |
159 | + * value passed to this function. You'll need to check first if your LSM | |
160 | + * is allowed to register its @ops by calling security_module_enable(@ops). | |
161 | * | |
162 | * If there is already a security module registered with the kernel, | |
163 | * an error will be returned. Otherwise 0 is returned on success. | |
164 | diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c | |
165 | index a2f7e9c..f9927f0 100644 | |
166 | --- a/security/selinux/hooks.c | |
167 | +++ b/security/selinux/hooks.c | |
168 | @@ -5295,6 +5295,8 @@ static int selinux_key_permission(key_ref_t key_ref, | |
169 | #endif | |
170 | ||
171 | static struct security_operations selinux_ops = { | |
172 | + .name = "selinux", | |
173 | + | |
174 | .ptrace = selinux_ptrace, | |
175 | .capget = selinux_capget, | |
176 | .capset_check = selinux_capset_check, | |
177 | @@ -5492,6 +5494,11 @@ static __init int selinux_init(void) | |
178 | { | |
179 | struct task_security_struct *tsec; | |
180 | ||
181 | + if (!security_module_enable(&selinux_ops)) { | |
182 | + selinux_enabled = 0; | |
183 | + return 0; | |
184 | + } | |
185 | + | |
186 | if (!selinux_enabled) { | |
187 | printk(KERN_INFO "SELinux: Disabled at boot.\n"); | |
188 | return 0; | |
189 | diff --git a/security/smack/smack.h b/security/smack/smack.h | |
190 | index 62c1e98..4a4477f 100644 | |
191 | --- a/security/smack/smack.h | |
192 | +++ b/security/smack/smack.h | |
193 | @@ -15,6 +15,7 @@ | |
194 | ||
195 | #include <linux/capability.h> | |
196 | #include <linux/spinlock.h> | |
197 | +#include <linux/security.h> | |
198 | #include <net/netlabel.h> | |
199 | ||
200 | /* | |
201 | @@ -187,6 +188,7 @@ extern struct smack_known smack_known_star; | |
202 | extern struct smack_known smack_known_unset; | |
203 | ||
204 | extern struct smk_list_entry *smack_list; | |
205 | +extern struct security_operations smack_ops; | |
206 | ||
207 | /* | |
208 | * Stricly for CIPSO level manipulation. | |
209 | diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c | |
210 | index 732ba27..904bdc0 100644 | |
211 | --- a/security/smack/smack_lsm.c | |
212 | +++ b/security/smack/smack_lsm.c | |
213 | @@ -2424,7 +2424,9 @@ static void smack_release_secctx(char *secdata, u32 seclen) | |
214 | { | |
215 | } | |
216 | ||
217 | -static struct security_operations smack_ops = { | |
218 | +struct security_operations smack_ops = { | |
219 | + .name = "smack", | |
220 | + | |
221 | .ptrace = smack_ptrace, | |
222 | .capget = cap_capget, | |
223 | .capset_check = cap_capset_check, | |
224 | @@ -2557,6 +2559,9 @@ static struct security_operations smack_ops = { | |
225 | */ | |
226 | static __init int smack_init(void) | |
227 | { | |
228 | + if (!security_module_enable(&smack_ops)) | |
229 | + return 0; | |
230 | + | |
231 | printk(KERN_INFO "Smack: Initializing.\n"); | |
232 | ||
233 | /* | |
234 | diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c | |
235 | index cfae8af..6ba2837 100644 | |
236 | --- a/security/smack/smackfs.c | |
237 | +++ b/security/smack/smackfs.c | |
238 | @@ -965,12 +965,21 @@ static struct vfsmount *smackfs_mount; | |
239 | * | |
240 | * register the smackfs | |
241 | * | |
242 | - * Returns 0 unless the registration fails. | |
243 | + * Do not register smackfs if Smack wasn't enabled | |
244 | + * on boot. We can not put this method normally under the | |
245 | + * smack_init() code path since the security subsystem get | |
246 | + * initialized before the vfs caches. | |
247 | + * | |
248 | + * Returns true if we were not chosen on boot or if | |
249 | + * we were chosen and filesystem registration succeeded. | |
250 | */ | |
251 | static int __init init_smk_fs(void) | |
252 | { | |
253 | int err; | |
254 | ||
255 | + if (!security_module_enable(&smack_ops)) | |
256 | + return 0; | |
257 | + | |
258 | err = register_filesystem(&smk_fs_type); | |
259 | if (!err) { | |
260 | smackfs_mount = kern_mount(&smk_fs_type); |