diff options
Diffstat (limited to 'security/security.c')
-rw-r--r-- | security/security.c | 664 |
1 files changed, 592 insertions, 72 deletions
diff --git a/security/security.c b/security/security.c index 55bc49027ba9..23cbb1a295a3 100644 --- a/security/security.c +++ b/security/security.c | |||
@@ -30,20 +30,32 @@ | |||
30 | #include <linux/personality.h> | 30 | #include <linux/personality.h> |
31 | #include <linux/backing-dev.h> | 31 | #include <linux/backing-dev.h> |
32 | #include <linux/string.h> | 32 | #include <linux/string.h> |
33 | #include <linux/msg.h> | ||
33 | #include <net/flow.h> | 34 | #include <net/flow.h> |
34 | 35 | ||
35 | #define MAX_LSM_EVM_XATTR 2 | 36 | #define MAX_LSM_EVM_XATTR 2 |
36 | 37 | ||
37 | /* Maximum number of letters for an LSM name string */ | 38 | /* How many LSMs were built into the kernel? */ |
38 | #define SECURITY_NAME_MAX 10 | 39 | #define LSM_COUNT (__end_lsm_info - __start_lsm_info) |
39 | 40 | ||
40 | struct security_hook_heads security_hook_heads __lsm_ro_after_init; | 41 | struct security_hook_heads security_hook_heads __lsm_ro_after_init; |
41 | static ATOMIC_NOTIFIER_HEAD(lsm_notifier_chain); | 42 | static ATOMIC_NOTIFIER_HEAD(lsm_notifier_chain); |
42 | 43 | ||
44 | static struct kmem_cache *lsm_file_cache; | ||
45 | static struct kmem_cache *lsm_inode_cache; | ||
46 | |||
43 | char *lsm_names; | 47 | char *lsm_names; |
48 | static struct lsm_blob_sizes blob_sizes __lsm_ro_after_init; | ||
49 | |||
44 | /* Boot-time LSM user choice */ | 50 | /* Boot-time LSM user choice */ |
45 | static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1] = | 51 | static __initdata const char *chosen_lsm_order; |
46 | CONFIG_DEFAULT_SECURITY; | 52 | static __initdata const char *chosen_major_lsm; |
53 | |||
54 | static __initconst const char * const builtin_lsm_order = CONFIG_LSM; | ||
55 | |||
56 | /* Ordered list of LSMs to initialize. */ | ||
57 | static __initdata struct lsm_info **ordered_lsms; | ||
58 | static __initdata struct lsm_info *exclusive; | ||
47 | 59 | ||
48 | static __initdata bool debug; | 60 | static __initdata bool debug; |
49 | #define init_debug(...) \ | 61 | #define init_debug(...) \ |
@@ -52,18 +64,269 @@ static __initdata bool debug; | |||
52 | pr_info(__VA_ARGS__); \ | 64 | pr_info(__VA_ARGS__); \ |
53 | } while (0) | 65 | } while (0) |
54 | 66 | ||
55 | static void __init major_lsm_init(void) | 67 | static bool __init is_enabled(struct lsm_info *lsm) |
56 | { | 68 | { |
57 | struct lsm_info *lsm; | 69 | if (!lsm->enabled) |
58 | int ret; | 70 | return false; |
71 | |||
72 | return *lsm->enabled; | ||
73 | } | ||
74 | |||
75 | /* Mark an LSM's enabled flag. */ | ||
76 | static int lsm_enabled_true __initdata = 1; | ||
77 | static int lsm_enabled_false __initdata = 0; | ||
78 | static void __init set_enabled(struct lsm_info *lsm, bool enabled) | ||
79 | { | ||
80 | /* | ||
81 | * When an LSM hasn't configured an enable variable, we can use | ||
82 | * a hard-coded location for storing the default enabled state. | ||
83 | */ | ||
84 | if (!lsm->enabled) { | ||
85 | if (enabled) | ||
86 | lsm->enabled = &lsm_enabled_true; | ||
87 | else | ||
88 | lsm->enabled = &lsm_enabled_false; | ||
89 | } else if (lsm->enabled == &lsm_enabled_true) { | ||
90 | if (!enabled) | ||
91 | lsm->enabled = &lsm_enabled_false; | ||
92 | } else if (lsm->enabled == &lsm_enabled_false) { | ||
93 | if (enabled) | ||
94 | lsm->enabled = &lsm_enabled_true; | ||
95 | } else { | ||
96 | *lsm->enabled = enabled; | ||
97 | } | ||
98 | } | ||
99 | |||
100 | /* Is an LSM already listed in the ordered LSMs list? */ | ||
101 | static bool __init exists_ordered_lsm(struct lsm_info *lsm) | ||
102 | { | ||
103 | struct lsm_info **check; | ||
104 | |||
105 | for (check = ordered_lsms; *check; check++) | ||
106 | if (*check == lsm) | ||
107 | return true; | ||
108 | |||
109 | return false; | ||
110 | } | ||
111 | |||
112 | /* Append an LSM to the list of ordered LSMs to initialize. */ | ||
113 | static int last_lsm __initdata; | ||
114 | static void __init append_ordered_lsm(struct lsm_info *lsm, const char *from) | ||
115 | { | ||
116 | /* Ignore duplicate selections. */ | ||
117 | if (exists_ordered_lsm(lsm)) | ||
118 | return; | ||
119 | |||
120 | if (WARN(last_lsm == LSM_COUNT, "%s: out of LSM slots!?\n", from)) | ||
121 | return; | ||
122 | |||
123 | /* Enable this LSM, if it is not already set. */ | ||
124 | if (!lsm->enabled) | ||
125 | lsm->enabled = &lsm_enabled_true; | ||
126 | ordered_lsms[last_lsm++] = lsm; | ||
127 | |||
128 | init_debug("%s ordering: %s (%sabled)\n", from, lsm->name, | ||
129 | is_enabled(lsm) ? "en" : "dis"); | ||
130 | } | ||
131 | |||
132 | /* Is an LSM allowed to be initialized? */ | ||
133 | static bool __init lsm_allowed(struct lsm_info *lsm) | ||
134 | { | ||
135 | /* Skip if the LSM is disabled. */ | ||
136 | if (!is_enabled(lsm)) | ||
137 | return false; | ||
138 | |||
139 | /* Not allowed if another exclusive LSM already initialized. */ | ||
140 | if ((lsm->flags & LSM_FLAG_EXCLUSIVE) && exclusive) { | ||
141 | init_debug("exclusive disabled: %s\n", lsm->name); | ||
142 | return false; | ||
143 | } | ||
144 | |||
145 | return true; | ||
146 | } | ||
147 | |||
148 | static void __init lsm_set_blob_size(int *need, int *lbs) | ||
149 | { | ||
150 | int offset; | ||
151 | |||
152 | if (*need > 0) { | ||
153 | offset = *lbs; | ||
154 | *lbs += *need; | ||
155 | *need = offset; | ||
156 | } | ||
157 | } | ||
158 | |||
159 | static void __init lsm_set_blob_sizes(struct lsm_blob_sizes *needed) | ||
160 | { | ||
161 | if (!needed) | ||
162 | return; | ||
163 | |||
164 | lsm_set_blob_size(&needed->lbs_cred, &blob_sizes.lbs_cred); | ||
165 | lsm_set_blob_size(&needed->lbs_file, &blob_sizes.lbs_file); | ||
166 | /* | ||
167 | * The inode blob gets an rcu_head in addition to | ||
168 | * what the modules might need. | ||
169 | */ | ||
170 | if (needed->lbs_inode && blob_sizes.lbs_inode == 0) | ||
171 | blob_sizes.lbs_inode = sizeof(struct rcu_head); | ||
172 | lsm_set_blob_size(&needed->lbs_inode, &blob_sizes.lbs_inode); | ||
173 | lsm_set_blob_size(&needed->lbs_ipc, &blob_sizes.lbs_ipc); | ||
174 | lsm_set_blob_size(&needed->lbs_msg_msg, &blob_sizes.lbs_msg_msg); | ||
175 | lsm_set_blob_size(&needed->lbs_task, &blob_sizes.lbs_task); | ||
176 | } | ||
177 | |||
178 | /* Prepare LSM for initialization. */ | ||
179 | static void __init prepare_lsm(struct lsm_info *lsm) | ||
180 | { | ||
181 | int enabled = lsm_allowed(lsm); | ||
182 | |||
183 | /* Record enablement (to handle any following exclusive LSMs). */ | ||
184 | set_enabled(lsm, enabled); | ||
185 | |||
186 | /* If enabled, do pre-initialization work. */ | ||
187 | if (enabled) { | ||
188 | if ((lsm->flags & LSM_FLAG_EXCLUSIVE) && !exclusive) { | ||
189 | exclusive = lsm; | ||
190 | init_debug("exclusive chosen: %s\n", lsm->name); | ||
191 | } | ||
192 | |||
193 | lsm_set_blob_sizes(lsm->blobs); | ||
194 | } | ||
195 | } | ||
196 | |||
197 | /* Initialize a given LSM, if it is enabled. */ | ||
198 | static void __init initialize_lsm(struct lsm_info *lsm) | ||
199 | { | ||
200 | if (is_enabled(lsm)) { | ||
201 | int ret; | ||
59 | 202 | ||
60 | for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) { | ||
61 | init_debug("initializing %s\n", lsm->name); | 203 | init_debug("initializing %s\n", lsm->name); |
62 | ret = lsm->init(); | 204 | ret = lsm->init(); |
63 | WARN(ret, "%s failed to initialize: %d\n", lsm->name, ret); | 205 | WARN(ret, "%s failed to initialize: %d\n", lsm->name, ret); |
64 | } | 206 | } |
65 | } | 207 | } |
66 | 208 | ||
209 | /* Populate ordered LSMs list from comma-separated LSM name list. */ | ||
210 | static void __init ordered_lsm_parse(const char *order, const char *origin) | ||
211 | { | ||
212 | struct lsm_info *lsm; | ||
213 | char *sep, *name, *next; | ||
214 | |||
215 | /* LSM_ORDER_FIRST is always first. */ | ||
216 | for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) { | ||
217 | if (lsm->order == LSM_ORDER_FIRST) | ||
218 | append_ordered_lsm(lsm, "first"); | ||
219 | } | ||
220 | |||
221 | /* Process "security=", if given. */ | ||
222 | if (chosen_major_lsm) { | ||
223 | struct lsm_info *major; | ||
224 | |||
225 | /* | ||
226 | * To match the original "security=" behavior, this | ||
227 | * explicitly does NOT fallback to another Legacy Major | ||
228 | * if the selected one was separately disabled: disable | ||
229 | * all non-matching Legacy Major LSMs. | ||
230 | */ | ||
231 | for (major = __start_lsm_info; major < __end_lsm_info; | ||
232 | major++) { | ||
233 | if ((major->flags & LSM_FLAG_LEGACY_MAJOR) && | ||
234 | strcmp(major->name, chosen_major_lsm) != 0) { | ||
235 | set_enabled(major, false); | ||
236 | init_debug("security=%s disabled: %s\n", | ||
237 | chosen_major_lsm, major->name); | ||
238 | } | ||
239 | } | ||
240 | } | ||
241 | |||
242 | sep = kstrdup(order, GFP_KERNEL); | ||
243 | next = sep; | ||
244 | /* Walk the list, looking for matching LSMs. */ | ||
245 | while ((name = strsep(&next, ",")) != NULL) { | ||
246 | bool found = false; | ||
247 | |||
248 | for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) { | ||
249 | if (lsm->order == LSM_ORDER_MUTABLE && | ||
250 | strcmp(lsm->name, name) == 0) { | ||
251 | append_ordered_lsm(lsm, origin); | ||
252 | found = true; | ||
253 | } | ||
254 | } | ||
255 | |||
256 | if (!found) | ||
257 | init_debug("%s ignored: %s\n", origin, name); | ||
258 | } | ||
259 | |||
260 | /* Process "security=", if given. */ | ||
261 | if (chosen_major_lsm) { | ||
262 | for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) { | ||
263 | if (exists_ordered_lsm(lsm)) | ||
264 | continue; | ||
265 | if (strcmp(lsm->name, chosen_major_lsm) == 0) | ||
266 | append_ordered_lsm(lsm, "security="); | ||
267 | } | ||
268 | } | ||
269 | |||
270 | /* Disable all LSMs not in the ordered list. */ | ||
271 | for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) { | ||
272 | if (exists_ordered_lsm(lsm)) | ||
273 | continue; | ||
274 | set_enabled(lsm, false); | ||
275 | init_debug("%s disabled: %s\n", origin, lsm->name); | ||
276 | } | ||
277 | |||
278 | kfree(sep); | ||
279 | } | ||
280 | |||
281 | static void __init lsm_early_cred(struct cred *cred); | ||
282 | static void __init lsm_early_task(struct task_struct *task); | ||
283 | |||
284 | static void __init ordered_lsm_init(void) | ||
285 | { | ||
286 | struct lsm_info **lsm; | ||
287 | |||
288 | ordered_lsms = kcalloc(LSM_COUNT + 1, sizeof(*ordered_lsms), | ||
289 | GFP_KERNEL); | ||
290 | |||
291 | if (chosen_lsm_order) { | ||
292 | if (chosen_major_lsm) { | ||
293 | pr_info("security= is ignored because it is superseded by lsm=\n"); | ||
294 | chosen_major_lsm = NULL; | ||
295 | } | ||
296 | ordered_lsm_parse(chosen_lsm_order, "cmdline"); | ||
297 | } else | ||
298 | ordered_lsm_parse(builtin_lsm_order, "builtin"); | ||
299 | |||
300 | for (lsm = ordered_lsms; *lsm; lsm++) | ||
301 | prepare_lsm(*lsm); | ||
302 | |||
303 | init_debug("cred blob size = %d\n", blob_sizes.lbs_cred); | ||
304 | init_debug("file blob size = %d\n", blob_sizes.lbs_file); | ||
305 | init_debug("inode blob size = %d\n", blob_sizes.lbs_inode); | ||
306 | init_debug("ipc blob size = %d\n", blob_sizes.lbs_ipc); | ||
307 | init_debug("msg_msg blob size = %d\n", blob_sizes.lbs_msg_msg); | ||
308 | init_debug("task blob size = %d\n", blob_sizes.lbs_task); | ||
309 | |||
310 | /* | ||
311 | * Create any kmem_caches needed for blobs | ||
312 | */ | ||
313 | if (blob_sizes.lbs_file) | ||
314 | lsm_file_cache = kmem_cache_create("lsm_file_cache", | ||
315 | blob_sizes.lbs_file, 0, | ||
316 | SLAB_PANIC, NULL); | ||
317 | if (blob_sizes.lbs_inode) | ||
318 | lsm_inode_cache = kmem_cache_create("lsm_inode_cache", | ||
319 | blob_sizes.lbs_inode, 0, | ||
320 | SLAB_PANIC, NULL); | ||
321 | |||
322 | lsm_early_cred((struct cred *) current->cred); | ||
323 | lsm_early_task(current); | ||
324 | for (lsm = ordered_lsms; *lsm; lsm++) | ||
325 | initialize_lsm(*lsm); | ||
326 | |||
327 | kfree(ordered_lsms); | ||
328 | } | ||
329 | |||
67 | /** | 330 | /** |
68 | * security_init - initializes the security framework | 331 | * security_init - initializes the security framework |
69 | * | 332 | * |
@@ -80,28 +343,27 @@ int __init security_init(void) | |||
80 | i++) | 343 | i++) |
81 | INIT_HLIST_HEAD(&list[i]); | 344 | INIT_HLIST_HEAD(&list[i]); |
82 | 345 | ||
83 | /* | 346 | /* Load LSMs in specified order. */ |
84 | * Load minor LSMs, with the capability module always first. | 347 | ordered_lsm_init(); |
85 | */ | ||
86 | capability_add_hooks(); | ||
87 | yama_add_hooks(); | ||
88 | loadpin_add_hooks(); | ||
89 | |||
90 | /* | ||
91 | * Load all the remaining security modules. | ||
92 | */ | ||
93 | major_lsm_init(); | ||
94 | 348 | ||
95 | return 0; | 349 | return 0; |
96 | } | 350 | } |
97 | 351 | ||
98 | /* Save user chosen LSM */ | 352 | /* Save user chosen LSM */ |
99 | static int __init choose_lsm(char *str) | 353 | static int __init choose_major_lsm(char *str) |
100 | { | 354 | { |
101 | strncpy(chosen_lsm, str, SECURITY_NAME_MAX); | 355 | chosen_major_lsm = str; |
102 | return 1; | 356 | return 1; |
103 | } | 357 | } |
104 | __setup("security=", choose_lsm); | 358 | __setup("security=", choose_major_lsm); |
359 | |||
360 | /* Explicitly choose LSM initialization order. */ | ||
361 | static int __init choose_lsm_order(char *str) | ||
362 | { | ||
363 | chosen_lsm_order = str; | ||
364 | return 1; | ||
365 | } | ||
366 | __setup("lsm=", choose_lsm_order); | ||
105 | 367 | ||
106 | /* Enable LSM order debugging. */ | 368 | /* Enable LSM order debugging. */ |
107 | static int __init enable_debug(char *str) | 369 | static int __init enable_debug(char *str) |
@@ -148,29 +410,6 @@ static int lsm_append(char *new, char **result) | |||
148 | } | 410 | } |
149 | 411 | ||
150 | /** | 412 | /** |
151 | * security_module_enable - Load given security module on boot ? | ||
152 | * @module: the name of the module | ||
153 | * | ||
154 | * Each LSM must pass this method before registering its own operations | ||
155 | * to avoid security registration races. This method may also be used | ||
156 | * to check if your LSM is currently loaded during kernel initialization. | ||
157 | * | ||
158 | * Returns: | ||
159 | * | ||
160 | * true if: | ||
161 | * | ||
162 | * - The passed LSM is the one chosen by user at boot time, | ||
163 | * - or the passed LSM is configured as the default and the user did not | ||
164 | * choose an alternate LSM at boot time. | ||
165 | * | ||
166 | * Otherwise, return false. | ||
167 | */ | ||
168 | int __init security_module_enable(const char *module) | ||
169 | { | ||
170 | return !strcmp(module, chosen_lsm); | ||
171 | } | ||
172 | |||
173 | /** | ||
174 | * security_add_hooks - Add a modules hooks to the hook lists. | 413 | * security_add_hooks - Add a modules hooks to the hook lists. |
175 | * @hooks: the hooks to add | 414 | * @hooks: the hooks to add |
176 | * @count: the number of hooks to add | 415 | * @count: the number of hooks to add |
@@ -209,6 +448,161 @@ int unregister_lsm_notifier(struct notifier_block *nb) | |||
209 | } | 448 | } |
210 | EXPORT_SYMBOL(unregister_lsm_notifier); | 449 | EXPORT_SYMBOL(unregister_lsm_notifier); |
211 | 450 | ||
451 | /** | ||
452 | * lsm_cred_alloc - allocate a composite cred blob | ||
453 | * @cred: the cred that needs a blob | ||
454 | * @gfp: allocation type | ||
455 | * | ||
456 | * Allocate the cred blob for all the modules | ||
457 | * | ||
458 | * Returns 0, or -ENOMEM if memory can't be allocated. | ||
459 | */ | ||
460 | static int lsm_cred_alloc(struct cred *cred, gfp_t gfp) | ||
461 | { | ||
462 | if (blob_sizes.lbs_cred == 0) { | ||
463 | cred->security = NULL; | ||
464 | return 0; | ||
465 | } | ||
466 | |||
467 | cred->security = kzalloc(blob_sizes.lbs_cred, gfp); | ||
468 | if (cred->security == NULL) | ||
469 | return -ENOMEM; | ||
470 | return 0; | ||
471 | } | ||
472 | |||
473 | /** | ||
474 | * lsm_early_cred - during initialization allocate a composite cred blob | ||
475 | * @cred: the cred that needs a blob | ||
476 | * | ||
477 | * Allocate the cred blob for all the modules | ||
478 | */ | ||
479 | static void __init lsm_early_cred(struct cred *cred) | ||
480 | { | ||
481 | int rc = lsm_cred_alloc(cred, GFP_KERNEL); | ||
482 | |||
483 | if (rc) | ||
484 | panic("%s: Early cred alloc failed.\n", __func__); | ||
485 | } | ||
486 | |||
487 | /** | ||
488 | * lsm_file_alloc - allocate a composite file blob | ||
489 | * @file: the file that needs a blob | ||
490 | * | ||
491 | * Allocate the file blob for all the modules | ||
492 | * | ||
493 | * Returns 0, or -ENOMEM if memory can't be allocated. | ||
494 | */ | ||
495 | static int lsm_file_alloc(struct file *file) | ||
496 | { | ||
497 | if (!lsm_file_cache) { | ||
498 | file->f_security = NULL; | ||
499 | return 0; | ||
500 | } | ||
501 | |||
502 | file->f_security = kmem_cache_zalloc(lsm_file_cache, GFP_KERNEL); | ||
503 | if (file->f_security == NULL) | ||
504 | return -ENOMEM; | ||
505 | return 0; | ||
506 | } | ||
507 | |||
508 | /** | ||
509 | * lsm_inode_alloc - allocate a composite inode blob | ||
510 | * @inode: the inode that needs a blob | ||
511 | * | ||
512 | * Allocate the inode blob for all the modules | ||
513 | * | ||
514 | * Returns 0, or -ENOMEM if memory can't be allocated. | ||
515 | */ | ||
516 | int lsm_inode_alloc(struct inode *inode) | ||
517 | { | ||
518 | if (!lsm_inode_cache) { | ||
519 | inode->i_security = NULL; | ||
520 | return 0; | ||
521 | } | ||
522 | |||
523 | inode->i_security = kmem_cache_zalloc(lsm_inode_cache, GFP_NOFS); | ||
524 | if (inode->i_security == NULL) | ||
525 | return -ENOMEM; | ||
526 | return 0; | ||
527 | } | ||
528 | |||
529 | /** | ||
530 | * lsm_task_alloc - allocate a composite task blob | ||
531 | * @task: the task that needs a blob | ||
532 | * | ||
533 | * Allocate the task blob for all the modules | ||
534 | * | ||
535 | * Returns 0, or -ENOMEM if memory can't be allocated. | ||
536 | */ | ||
537 | static int lsm_task_alloc(struct task_struct *task) | ||
538 | { | ||
539 | if (blob_sizes.lbs_task == 0) { | ||
540 | task->security = NULL; | ||
541 | return 0; | ||
542 | } | ||
543 | |||
544 | task->security = kzalloc(blob_sizes.lbs_task, GFP_KERNEL); | ||
545 | if (task->security == NULL) | ||
546 | return -ENOMEM; | ||
547 | return 0; | ||
548 | } | ||
549 | |||
550 | /** | ||
551 | * lsm_ipc_alloc - allocate a composite ipc blob | ||
552 | * @kip: the ipc that needs a blob | ||
553 | * | ||
554 | * Allocate the ipc blob for all the modules | ||
555 | * | ||
556 | * Returns 0, or -ENOMEM if memory can't be allocated. | ||
557 | */ | ||
558 | static int lsm_ipc_alloc(struct kern_ipc_perm *kip) | ||
559 | { | ||
560 | if (blob_sizes.lbs_ipc == 0) { | ||
561 | kip->security = NULL; | ||
562 | return 0; | ||
563 | } | ||
564 | |||
565 | kip->security = kzalloc(blob_sizes.lbs_ipc, GFP_KERNEL); | ||
566 | if (kip->security == NULL) | ||
567 | return -ENOMEM; | ||
568 | return 0; | ||
569 | } | ||
570 | |||
571 | /** | ||
572 | * lsm_msg_msg_alloc - allocate a composite msg_msg blob | ||
573 | * @mp: the msg_msg that needs a blob | ||
574 | * | ||
575 | * Allocate the ipc blob for all the modules | ||
576 | * | ||
577 | * Returns 0, or -ENOMEM if memory can't be allocated. | ||
578 | */ | ||
579 | static int lsm_msg_msg_alloc(struct msg_msg *mp) | ||
580 | { | ||
581 | if (blob_sizes.lbs_msg_msg == 0) { | ||
582 | mp->security = NULL; | ||
583 | return 0; | ||
584 | } | ||
585 | |||
586 | mp->security = kzalloc(blob_sizes.lbs_msg_msg, GFP_KERNEL); | ||
587 | if (mp->security == NULL) | ||
588 | return -ENOMEM; | ||
589 | return 0; | ||
590 | } | ||
591 | |||
592 | /** | ||
593 | * lsm_early_task - during initialization allocate a composite task blob | ||
594 | * @task: the task that needs a blob | ||
595 | * | ||
596 | * Allocate the task blob for all the modules | ||
597 | */ | ||
598 | static void __init lsm_early_task(struct task_struct *task) | ||
599 | { | ||
600 | int rc = lsm_task_alloc(task); | ||
601 | |||
602 | if (rc) | ||
603 | panic("%s: Early task alloc failed.\n", __func__); | ||
604 | } | ||
605 | |||
212 | /* | 606 | /* |
213 | * Hook list operation macros. | 607 | * Hook list operation macros. |
214 | * | 608 | * |
@@ -294,16 +688,12 @@ int security_capset(struct cred *new, const struct cred *old, | |||
294 | effective, inheritable, permitted); | 688 | effective, inheritable, permitted); |
295 | } | 689 | } |
296 | 690 | ||
297 | int security_capable(const struct cred *cred, struct user_namespace *ns, | 691 | int security_capable(const struct cred *cred, |
298 | int cap) | 692 | struct user_namespace *ns, |
299 | { | 693 | int cap, |
300 | return call_int_hook(capable, 0, cred, ns, cap, SECURITY_CAP_AUDIT); | 694 | unsigned int opts) |
301 | } | ||
302 | |||
303 | int security_capable_noaudit(const struct cred *cred, struct user_namespace *ns, | ||
304 | int cap) | ||
305 | { | 695 | { |
306 | return call_int_hook(capable, 0, cred, ns, cap, SECURITY_CAP_NOAUDIT); | 696 | return call_int_hook(capable, 0, cred, ns, cap, opts); |
307 | } | 697 | } |
308 | 698 | ||
309 | int security_quotactl(int cmds, int type, int id, struct super_block *sb) | 699 | int security_quotactl(int cmds, int type, int id, struct super_block *sb) |
@@ -374,6 +764,16 @@ void security_bprm_committed_creds(struct linux_binprm *bprm) | |||
374 | call_void_hook(bprm_committed_creds, bprm); | 764 | call_void_hook(bprm_committed_creds, bprm); |
375 | } | 765 | } |
376 | 766 | ||
767 | int security_fs_context_dup(struct fs_context *fc, struct fs_context *src_fc) | ||
768 | { | ||
769 | return call_int_hook(fs_context_dup, 0, fc, src_fc); | ||
770 | } | ||
771 | |||
772 | int security_fs_context_parse_param(struct fs_context *fc, struct fs_parameter *param) | ||
773 | { | ||
774 | return call_int_hook(fs_context_parse_param, -ENOPARAM, fc, param); | ||
775 | } | ||
776 | |||
377 | int security_sb_alloc(struct super_block *sb) | 777 | int security_sb_alloc(struct super_block *sb) |
378 | { | 778 | { |
379 | return call_int_hook(sb_alloc_security, 0, sb); | 779 | return call_int_hook(sb_alloc_security, 0, sb); |
@@ -468,14 +868,40 @@ EXPORT_SYMBOL(security_add_mnt_opt); | |||
468 | 868 | ||
469 | int security_inode_alloc(struct inode *inode) | 869 | int security_inode_alloc(struct inode *inode) |
470 | { | 870 | { |
471 | inode->i_security = NULL; | 871 | int rc = lsm_inode_alloc(inode); |
472 | return call_int_hook(inode_alloc_security, 0, inode); | 872 | |
873 | if (unlikely(rc)) | ||
874 | return rc; | ||
875 | rc = call_int_hook(inode_alloc_security, 0, inode); | ||
876 | if (unlikely(rc)) | ||
877 | security_inode_free(inode); | ||
878 | return rc; | ||
879 | } | ||
880 | |||
881 | static void inode_free_by_rcu(struct rcu_head *head) | ||
882 | { | ||
883 | /* | ||
884 | * The rcu head is at the start of the inode blob | ||
885 | */ | ||
886 | kmem_cache_free(lsm_inode_cache, head); | ||
473 | } | 887 | } |
474 | 888 | ||
475 | void security_inode_free(struct inode *inode) | 889 | void security_inode_free(struct inode *inode) |
476 | { | 890 | { |
477 | integrity_inode_free(inode); | 891 | integrity_inode_free(inode); |
478 | call_void_hook(inode_free_security, inode); | 892 | call_void_hook(inode_free_security, inode); |
893 | /* | ||
894 | * The inode may still be referenced in a path walk and | ||
895 | * a call to security_inode_permission() can be made | ||
896 | * after inode_free_security() is called. Ideally, the VFS | ||
897 | * wouldn't do this, but fixing that is a much harder | ||
898 | * job. For now, simply free the i_security via RCU, and | ||
899 | * leave the current inode->i_security pointer intact. | ||
900 | * The inode will be freed after the RCU grace period too. | ||
901 | */ | ||
902 | if (inode->i_security) | ||
903 | call_rcu((struct rcu_head *)inode->i_security, | ||
904 | inode_free_by_rcu); | ||
479 | } | 905 | } |
480 | 906 | ||
481 | int security_dentry_init_security(struct dentry *dentry, int mode, | 907 | int security_dentry_init_security(struct dentry *dentry, int mode, |
@@ -905,12 +1331,27 @@ int security_file_permission(struct file *file, int mask) | |||
905 | 1331 | ||
906 | int security_file_alloc(struct file *file) | 1332 | int security_file_alloc(struct file *file) |
907 | { | 1333 | { |
908 | return call_int_hook(file_alloc_security, 0, file); | 1334 | int rc = lsm_file_alloc(file); |
1335 | |||
1336 | if (rc) | ||
1337 | return rc; | ||
1338 | rc = call_int_hook(file_alloc_security, 0, file); | ||
1339 | if (unlikely(rc)) | ||
1340 | security_file_free(file); | ||
1341 | return rc; | ||
909 | } | 1342 | } |
910 | 1343 | ||
911 | void security_file_free(struct file *file) | 1344 | void security_file_free(struct file *file) |
912 | { | 1345 | { |
1346 | void *blob; | ||
1347 | |||
913 | call_void_hook(file_free_security, file); | 1348 | call_void_hook(file_free_security, file); |
1349 | |||
1350 | blob = file->f_security; | ||
1351 | if (blob) { | ||
1352 | file->f_security = NULL; | ||
1353 | kmem_cache_free(lsm_file_cache, blob); | ||
1354 | } | ||
914 | } | 1355 | } |
915 | 1356 | ||
916 | int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | 1357 | int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
@@ -1012,17 +1453,35 @@ int security_file_open(struct file *file) | |||
1012 | 1453 | ||
1013 | int security_task_alloc(struct task_struct *task, unsigned long clone_flags) | 1454 | int security_task_alloc(struct task_struct *task, unsigned long clone_flags) |
1014 | { | 1455 | { |
1015 | return call_int_hook(task_alloc, 0, task, clone_flags); | 1456 | int rc = lsm_task_alloc(task); |
1457 | |||
1458 | if (rc) | ||
1459 | return rc; | ||
1460 | rc = call_int_hook(task_alloc, 0, task, clone_flags); | ||
1461 | if (unlikely(rc)) | ||
1462 | security_task_free(task); | ||
1463 | return rc; | ||
1016 | } | 1464 | } |
1017 | 1465 | ||
1018 | void security_task_free(struct task_struct *task) | 1466 | void security_task_free(struct task_struct *task) |
1019 | { | 1467 | { |
1020 | call_void_hook(task_free, task); | 1468 | call_void_hook(task_free, task); |
1469 | |||
1470 | kfree(task->security); | ||
1471 | task->security = NULL; | ||
1021 | } | 1472 | } |
1022 | 1473 | ||
1023 | int security_cred_alloc_blank(struct cred *cred, gfp_t gfp) | 1474 | int security_cred_alloc_blank(struct cred *cred, gfp_t gfp) |
1024 | { | 1475 | { |
1025 | return call_int_hook(cred_alloc_blank, 0, cred, gfp); | 1476 | int rc = lsm_cred_alloc(cred, gfp); |
1477 | |||
1478 | if (rc) | ||
1479 | return rc; | ||
1480 | |||
1481 | rc = call_int_hook(cred_alloc_blank, 0, cred, gfp); | ||
1482 | if (unlikely(rc)) | ||
1483 | security_cred_free(cred); | ||
1484 | return rc; | ||
1026 | } | 1485 | } |
1027 | 1486 | ||
1028 | void security_cred_free(struct cred *cred) | 1487 | void security_cred_free(struct cred *cred) |
@@ -1035,11 +1494,22 @@ void security_cred_free(struct cred *cred) | |||
1035 | return; | 1494 | return; |
1036 | 1495 | ||
1037 | call_void_hook(cred_free, cred); | 1496 | call_void_hook(cred_free, cred); |
1497 | |||
1498 | kfree(cred->security); | ||
1499 | cred->security = NULL; | ||
1038 | } | 1500 | } |
1039 | 1501 | ||
1040 | int security_prepare_creds(struct cred *new, const struct cred *old, gfp_t gfp) | 1502 | int security_prepare_creds(struct cred *new, const struct cred *old, gfp_t gfp) |
1041 | { | 1503 | { |
1042 | return call_int_hook(cred_prepare, 0, new, old, gfp); | 1504 | int rc = lsm_cred_alloc(new, gfp); |
1505 | |||
1506 | if (rc) | ||
1507 | return rc; | ||
1508 | |||
1509 | rc = call_int_hook(cred_prepare, 0, new, old, gfp); | ||
1510 | if (unlikely(rc)) | ||
1511 | security_cred_free(new); | ||
1512 | return rc; | ||
1043 | } | 1513 | } |
1044 | 1514 | ||
1045 | void security_transfer_creds(struct cred *new, const struct cred *old) | 1515 | void security_transfer_creds(struct cred *new, const struct cred *old) |
@@ -1220,22 +1690,40 @@ void security_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid) | |||
1220 | 1690 | ||
1221 | int security_msg_msg_alloc(struct msg_msg *msg) | 1691 | int security_msg_msg_alloc(struct msg_msg *msg) |
1222 | { | 1692 | { |
1223 | return call_int_hook(msg_msg_alloc_security, 0, msg); | 1693 | int rc = lsm_msg_msg_alloc(msg); |
1694 | |||
1695 | if (unlikely(rc)) | ||
1696 | return rc; | ||
1697 | rc = call_int_hook(msg_msg_alloc_security, 0, msg); | ||
1698 | if (unlikely(rc)) | ||
1699 | security_msg_msg_free(msg); | ||
1700 | return rc; | ||
1224 | } | 1701 | } |
1225 | 1702 | ||
1226 | void security_msg_msg_free(struct msg_msg *msg) | 1703 | void security_msg_msg_free(struct msg_msg *msg) |
1227 | { | 1704 | { |
1228 | call_void_hook(msg_msg_free_security, msg); | 1705 | call_void_hook(msg_msg_free_security, msg); |
1706 | kfree(msg->security); | ||
1707 | msg->security = NULL; | ||
1229 | } | 1708 | } |
1230 | 1709 | ||
1231 | int security_msg_queue_alloc(struct kern_ipc_perm *msq) | 1710 | int security_msg_queue_alloc(struct kern_ipc_perm *msq) |
1232 | { | 1711 | { |
1233 | return call_int_hook(msg_queue_alloc_security, 0, msq); | 1712 | int rc = lsm_ipc_alloc(msq); |
1713 | |||
1714 | if (unlikely(rc)) | ||
1715 | return rc; | ||
1716 | rc = call_int_hook(msg_queue_alloc_security, 0, msq); | ||
1717 | if (unlikely(rc)) | ||
1718 | security_msg_queue_free(msq); | ||
1719 | return rc; | ||
1234 | } | 1720 | } |
1235 | 1721 | ||
1236 | void security_msg_queue_free(struct kern_ipc_perm *msq) | 1722 | void security_msg_queue_free(struct kern_ipc_perm *msq) |
1237 | { | 1723 | { |
1238 | call_void_hook(msg_queue_free_security, msq); | 1724 | call_void_hook(msg_queue_free_security, msq); |
1725 | kfree(msq->security); | ||
1726 | msq->security = NULL; | ||
1239 | } | 1727 | } |
1240 | 1728 | ||
1241 | int security_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg) | 1729 | int security_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg) |
@@ -1262,12 +1750,21 @@ int security_msg_queue_msgrcv(struct kern_ipc_perm *msq, struct msg_msg *msg, | |||
1262 | 1750 | ||
1263 | int security_shm_alloc(struct kern_ipc_perm *shp) | 1751 | int security_shm_alloc(struct kern_ipc_perm *shp) |
1264 | { | 1752 | { |
1265 | return call_int_hook(shm_alloc_security, 0, shp); | 1753 | int rc = lsm_ipc_alloc(shp); |
1754 | |||
1755 | if (unlikely(rc)) | ||
1756 | return rc; | ||
1757 | rc = call_int_hook(shm_alloc_security, 0, shp); | ||
1758 | if (unlikely(rc)) | ||
1759 | security_shm_free(shp); | ||
1760 | return rc; | ||
1266 | } | 1761 | } |
1267 | 1762 | ||
1268 | void security_shm_free(struct kern_ipc_perm *shp) | 1763 | void security_shm_free(struct kern_ipc_perm *shp) |
1269 | { | 1764 | { |
1270 | call_void_hook(shm_free_security, shp); | 1765 | call_void_hook(shm_free_security, shp); |
1766 | kfree(shp->security); | ||
1767 | shp->security = NULL; | ||
1271 | } | 1768 | } |
1272 | 1769 | ||
1273 | int security_shm_associate(struct kern_ipc_perm *shp, int shmflg) | 1770 | int security_shm_associate(struct kern_ipc_perm *shp, int shmflg) |
@@ -1287,12 +1784,21 @@ int security_shm_shmat(struct kern_ipc_perm *shp, char __user *shmaddr, int shmf | |||
1287 | 1784 | ||
1288 | int security_sem_alloc(struct kern_ipc_perm *sma) | 1785 | int security_sem_alloc(struct kern_ipc_perm *sma) |
1289 | { | 1786 | { |
1290 | return call_int_hook(sem_alloc_security, 0, sma); | 1787 | int rc = lsm_ipc_alloc(sma); |
1788 | |||
1789 | if (unlikely(rc)) | ||
1790 | return rc; | ||
1791 | rc = call_int_hook(sem_alloc_security, 0, sma); | ||
1792 | if (unlikely(rc)) | ||
1793 | security_sem_free(sma); | ||
1794 | return rc; | ||
1291 | } | 1795 | } |
1292 | 1796 | ||
1293 | void security_sem_free(struct kern_ipc_perm *sma) | 1797 | void security_sem_free(struct kern_ipc_perm *sma) |
1294 | { | 1798 | { |
1295 | call_void_hook(sem_free_security, sma); | 1799 | call_void_hook(sem_free_security, sma); |
1800 | kfree(sma->security); | ||
1801 | sma->security = NULL; | ||
1296 | } | 1802 | } |
1297 | 1803 | ||
1298 | int security_sem_associate(struct kern_ipc_perm *sma, int semflg) | 1804 | int security_sem_associate(struct kern_ipc_perm *sma, int semflg) |
@@ -1319,14 +1825,30 @@ void security_d_instantiate(struct dentry *dentry, struct inode *inode) | |||
1319 | } | 1825 | } |
1320 | EXPORT_SYMBOL(security_d_instantiate); | 1826 | EXPORT_SYMBOL(security_d_instantiate); |
1321 | 1827 | ||
1322 | int security_getprocattr(struct task_struct *p, char *name, char **value) | 1828 | int security_getprocattr(struct task_struct *p, const char *lsm, char *name, |
1829 | char **value) | ||
1323 | { | 1830 | { |
1324 | return call_int_hook(getprocattr, -EINVAL, p, name, value); | 1831 | struct security_hook_list *hp; |
1832 | |||
1833 | hlist_for_each_entry(hp, &security_hook_heads.getprocattr, list) { | ||
1834 | if (lsm != NULL && strcmp(lsm, hp->lsm)) | ||
1835 | continue; | ||
1836 | return hp->hook.getprocattr(p, name, value); | ||
1837 | } | ||
1838 | return -EINVAL; | ||
1325 | } | 1839 | } |
1326 | 1840 | ||
1327 | int security_setprocattr(const char *name, void *value, size_t size) | 1841 | int security_setprocattr(const char *lsm, const char *name, void *value, |
1842 | size_t size) | ||
1328 | { | 1843 | { |
1329 | return call_int_hook(setprocattr, -EINVAL, name, value, size); | 1844 | struct security_hook_list *hp; |
1845 | |||
1846 | hlist_for_each_entry(hp, &security_hook_heads.setprocattr, list) { | ||
1847 | if (lsm != NULL && strcmp(lsm, hp->lsm)) | ||
1848 | continue; | ||
1849 | return hp->hook.setprocattr(name, value, size); | ||
1850 | } | ||
1851 | return -EINVAL; | ||
1330 | } | 1852 | } |
1331 | 1853 | ||
1332 | int security_netlink_send(struct sock *sk, struct sk_buff *skb) | 1854 | int security_netlink_send(struct sock *sk, struct sk_buff *skb) |
@@ -1790,11 +2312,9 @@ void security_audit_rule_free(void *lsmrule) | |||
1790 | call_void_hook(audit_rule_free, lsmrule); | 2312 | call_void_hook(audit_rule_free, lsmrule); |
1791 | } | 2313 | } |
1792 | 2314 | ||
1793 | int security_audit_rule_match(u32 secid, u32 field, u32 op, void *lsmrule, | 2315 | int security_audit_rule_match(u32 secid, u32 field, u32 op, void *lsmrule) |
1794 | struct audit_context *actx) | ||
1795 | { | 2316 | { |
1796 | return call_int_hook(audit_rule_match, 0, secid, field, op, lsmrule, | 2317 | return call_int_hook(audit_rule_match, 0, secid, field, op, lsmrule); |
1797 | actx); | ||
1798 | } | 2318 | } |
1799 | #endif /* CONFIG_AUDIT */ | 2319 | #endif /* CONFIG_AUDIT */ |
1800 | 2320 | ||