diff options
Diffstat (limited to 'security/security.c')
| -rw-r--r-- | security/security.c | 644 |
1 files changed, 576 insertions, 68 deletions
diff --git a/security/security.c b/security/security.c index 55bc49027ba9..b6bff646d373 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,265 @@ 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 | ordered_lsm_parse(chosen_lsm_order, "cmdline"); | ||
| 293 | else | ||
| 294 | ordered_lsm_parse(builtin_lsm_order, "builtin"); | ||
| 295 | |||
| 296 | for (lsm = ordered_lsms; *lsm; lsm++) | ||
| 297 | prepare_lsm(*lsm); | ||
| 298 | |||
| 299 | init_debug("cred blob size = %d\n", blob_sizes.lbs_cred); | ||
| 300 | init_debug("file blob size = %d\n", blob_sizes.lbs_file); | ||
| 301 | init_debug("inode blob size = %d\n", blob_sizes.lbs_inode); | ||
| 302 | init_debug("ipc blob size = %d\n", blob_sizes.lbs_ipc); | ||
| 303 | init_debug("msg_msg blob size = %d\n", blob_sizes.lbs_msg_msg); | ||
| 304 | init_debug("task blob size = %d\n", blob_sizes.lbs_task); | ||
| 305 | |||
| 306 | /* | ||
| 307 | * Create any kmem_caches needed for blobs | ||
| 308 | */ | ||
| 309 | if (blob_sizes.lbs_file) | ||
| 310 | lsm_file_cache = kmem_cache_create("lsm_file_cache", | ||
| 311 | blob_sizes.lbs_file, 0, | ||
| 312 | SLAB_PANIC, NULL); | ||
| 313 | if (blob_sizes.lbs_inode) | ||
| 314 | lsm_inode_cache = kmem_cache_create("lsm_inode_cache", | ||
| 315 | blob_sizes.lbs_inode, 0, | ||
| 316 | SLAB_PANIC, NULL); | ||
| 317 | |||
| 318 | lsm_early_cred((struct cred *) current->cred); | ||
| 319 | lsm_early_task(current); | ||
| 320 | for (lsm = ordered_lsms; *lsm; lsm++) | ||
| 321 | initialize_lsm(*lsm); | ||
| 322 | |||
| 323 | kfree(ordered_lsms); | ||
| 324 | } | ||
| 325 | |||
| 67 | /** | 326 | /** |
| 68 | * security_init - initializes the security framework | 327 | * security_init - initializes the security framework |
| 69 | * | 328 | * |
| @@ -80,28 +339,27 @@ int __init security_init(void) | |||
| 80 | i++) | 339 | i++) |
| 81 | INIT_HLIST_HEAD(&list[i]); | 340 | INIT_HLIST_HEAD(&list[i]); |
| 82 | 341 | ||
| 83 | /* | 342 | /* Load LSMs in specified order. */ |
| 84 | * Load minor LSMs, with the capability module always first. | 343 | 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 | 344 | ||
| 95 | return 0; | 345 | return 0; |
| 96 | } | 346 | } |
| 97 | 347 | ||
| 98 | /* Save user chosen LSM */ | 348 | /* Save user chosen LSM */ |
| 99 | static int __init choose_lsm(char *str) | 349 | static int __init choose_major_lsm(char *str) |
| 350 | { | ||
| 351 | chosen_major_lsm = str; | ||
| 352 | return 1; | ||
| 353 | } | ||
| 354 | __setup("security=", choose_major_lsm); | ||
| 355 | |||
| 356 | /* Explicitly choose LSM initialization order. */ | ||
| 357 | static int __init choose_lsm_order(char *str) | ||
| 100 | { | 358 | { |
| 101 | strncpy(chosen_lsm, str, SECURITY_NAME_MAX); | 359 | chosen_lsm_order = str; |
| 102 | return 1; | 360 | return 1; |
| 103 | } | 361 | } |
| 104 | __setup("security=", choose_lsm); | 362 | __setup("lsm=", choose_lsm_order); |
| 105 | 363 | ||
| 106 | /* Enable LSM order debugging. */ | 364 | /* Enable LSM order debugging. */ |
| 107 | static int __init enable_debug(char *str) | 365 | static int __init enable_debug(char *str) |
| @@ -148,29 +406,6 @@ static int lsm_append(char *new, char **result) | |||
| 148 | } | 406 | } |
| 149 | 407 | ||
| 150 | /** | 408 | /** |
| 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. | 409 | * security_add_hooks - Add a modules hooks to the hook lists. |
| 175 | * @hooks: the hooks to add | 410 | * @hooks: the hooks to add |
| 176 | * @count: the number of hooks to add | 411 | * @count: the number of hooks to add |
| @@ -209,6 +444,161 @@ int unregister_lsm_notifier(struct notifier_block *nb) | |||
| 209 | } | 444 | } |
| 210 | EXPORT_SYMBOL(unregister_lsm_notifier); | 445 | EXPORT_SYMBOL(unregister_lsm_notifier); |
| 211 | 446 | ||
| 447 | /** | ||
| 448 | * lsm_cred_alloc - allocate a composite cred blob | ||
| 449 | * @cred: the cred that needs a blob | ||
| 450 | * @gfp: allocation type | ||
| 451 | * | ||
| 452 | * Allocate the cred blob for all the modules | ||
| 453 | * | ||
| 454 | * Returns 0, or -ENOMEM if memory can't be allocated. | ||
| 455 | */ | ||
| 456 | static int lsm_cred_alloc(struct cred *cred, gfp_t gfp) | ||
| 457 | { | ||
| 458 | if (blob_sizes.lbs_cred == 0) { | ||
| 459 | cred->security = NULL; | ||
| 460 | return 0; | ||
| 461 | } | ||
| 462 | |||
| 463 | cred->security = kzalloc(blob_sizes.lbs_cred, gfp); | ||
| 464 | if (cred->security == NULL) | ||
| 465 | return -ENOMEM; | ||
| 466 | return 0; | ||
| 467 | } | ||
| 468 | |||
| 469 | /** | ||
| 470 | * lsm_early_cred - during initialization allocate a composite cred blob | ||
| 471 | * @cred: the cred that needs a blob | ||
| 472 | * | ||
| 473 | * Allocate the cred blob for all the modules | ||
| 474 | */ | ||
| 475 | static void __init lsm_early_cred(struct cred *cred) | ||
| 476 | { | ||
| 477 | int rc = lsm_cred_alloc(cred, GFP_KERNEL); | ||
| 478 | |||
| 479 | if (rc) | ||
| 480 | panic("%s: Early cred alloc failed.\n", __func__); | ||
| 481 | } | ||
| 482 | |||
| 483 | /** | ||
| 484 | * lsm_file_alloc - allocate a composite file blob | ||
| 485 | * @file: the file that needs a blob | ||
| 486 | * | ||
| 487 | * Allocate the file blob for all the modules | ||
| 488 | * | ||
| 489 | * Returns 0, or -ENOMEM if memory can't be allocated. | ||
| 490 | */ | ||
| 491 | static int lsm_file_alloc(struct file *file) | ||
| 492 | { | ||
| 493 | if (!lsm_file_cache) { | ||
| 494 | file->f_security = NULL; | ||
| 495 | return 0; | ||
| 496 | } | ||
| 497 | |||
| 498 | file->f_security = kmem_cache_zalloc(lsm_file_cache, GFP_KERNEL); | ||
| 499 | if (file->f_security == NULL) | ||
| 500 | return -ENOMEM; | ||
| 501 | return 0; | ||
| 502 | } | ||
| 503 | |||
| 504 | /** | ||
| 505 | * lsm_inode_alloc - allocate a composite inode blob | ||
| 506 | * @inode: the inode that needs a blob | ||
| 507 | * | ||
| 508 | * Allocate the inode blob for all the modules | ||
| 509 | * | ||
| 510 | * Returns 0, or -ENOMEM if memory can't be allocated. | ||
| 511 | */ | ||
| 512 | int lsm_inode_alloc(struct inode *inode) | ||
| 513 | { | ||
| 514 | if (!lsm_inode_cache) { | ||
| 515 | inode->i_security = NULL; | ||
| 516 | return 0; | ||
| 517 | } | ||
| 518 | |||
| 519 | inode->i_security = kmem_cache_zalloc(lsm_inode_cache, GFP_NOFS); | ||
| 520 | if (inode->i_security == NULL) | ||
| 521 | return -ENOMEM; | ||
| 522 | return 0; | ||
| 523 | } | ||
| 524 | |||
| 525 | /** | ||
| 526 | * lsm_task_alloc - allocate a composite task blob | ||
| 527 | * @task: the task that needs a blob | ||
| 528 | * | ||
| 529 | * Allocate the task blob for all the modules | ||
| 530 | * | ||
| 531 | * Returns 0, or -ENOMEM if memory can't be allocated. | ||
| 532 | */ | ||
| 533 | static int lsm_task_alloc(struct task_struct *task) | ||
| 534 | { | ||
| 535 | if (blob_sizes.lbs_task == 0) { | ||
| 536 | task->security = NULL; | ||
| 537 | return 0; | ||
| 538 | } | ||
| 539 | |||
| 540 | task->security = kzalloc(blob_sizes.lbs_task, GFP_KERNEL); | ||
| 541 | if (task->security == NULL) | ||
| 542 | return -ENOMEM; | ||
| 543 | return 0; | ||
| 544 | } | ||
| 545 | |||
| 546 | /** | ||
| 547 | * lsm_ipc_alloc - allocate a composite ipc blob | ||
| 548 | * @kip: the ipc that needs a blob | ||
| 549 | * | ||
| 550 | * Allocate the ipc blob for all the modules | ||
| 551 | * | ||
| 552 | * Returns 0, or -ENOMEM if memory can't be allocated. | ||
| 553 | */ | ||
| 554 | static int lsm_ipc_alloc(struct kern_ipc_perm *kip) | ||
| 555 | { | ||
| 556 | if (blob_sizes.lbs_ipc == 0) { | ||
| 557 | kip->security = NULL; | ||
| 558 | return 0; | ||
| 559 | } | ||
| 560 | |||
| 561 | kip->security = kzalloc(blob_sizes.lbs_ipc, GFP_KERNEL); | ||
| 562 | if (kip->security == NULL) | ||
| 563 | return -ENOMEM; | ||
| 564 | return 0; | ||
| 565 | } | ||
| 566 | |||
| 567 | /** | ||
| 568 | * lsm_msg_msg_alloc - allocate a composite msg_msg blob | ||
| 569 | * @mp: the msg_msg that needs a blob | ||
| 570 | * | ||
| 571 | * Allocate the ipc blob for all the modules | ||
| 572 | * | ||
| 573 | * Returns 0, or -ENOMEM if memory can't be allocated. | ||
| 574 | */ | ||
| 575 | static int lsm_msg_msg_alloc(struct msg_msg *mp) | ||
| 576 | { | ||
| 577 | if (blob_sizes.lbs_msg_msg == 0) { | ||
| 578 | mp->security = NULL; | ||
| 579 | return 0; | ||
| 580 | } | ||
| 581 | |||
| 582 | mp->security = kzalloc(blob_sizes.lbs_msg_msg, GFP_KERNEL); | ||
| 583 | if (mp->security == NULL) | ||
| 584 | return -ENOMEM; | ||
| 585 | return 0; | ||
| 586 | } | ||
| 587 | |||
| 588 | /** | ||
| 589 | * lsm_early_task - during initialization allocate a composite task blob | ||
| 590 | * @task: the task that needs a blob | ||
| 591 | * | ||
| 592 | * Allocate the task blob for all the modules | ||
| 593 | */ | ||
| 594 | static void __init lsm_early_task(struct task_struct *task) | ||
| 595 | { | ||
| 596 | int rc = lsm_task_alloc(task); | ||
| 597 | |||
| 598 | if (rc) | ||
| 599 | panic("%s: Early task alloc failed.\n", __func__); | ||
| 600 | } | ||
| 601 | |||
| 212 | /* | 602 | /* |
| 213 | * Hook list operation macros. | 603 | * Hook list operation macros. |
| 214 | * | 604 | * |
| @@ -294,16 +684,12 @@ int security_capset(struct cred *new, const struct cred *old, | |||
| 294 | effective, inheritable, permitted); | 684 | effective, inheritable, permitted); |
| 295 | } | 685 | } |
| 296 | 686 | ||
| 297 | int security_capable(const struct cred *cred, struct user_namespace *ns, | 687 | int security_capable(const struct cred *cred, |
| 298 | int cap) | 688 | struct user_namespace *ns, |
| 689 | int cap, | ||
| 690 | unsigned int opts) | ||
| 299 | { | 691 | { |
| 300 | return call_int_hook(capable, 0, cred, ns, cap, SECURITY_CAP_AUDIT); | 692 | return call_int_hook(capable, 0, cred, ns, cap, opts); |
| 301 | } | ||
| 302 | |||
| 303 | int security_capable_noaudit(const struct cred *cred, struct user_namespace *ns, | ||
| 304 | int cap) | ||
| 305 | { | ||
| 306 | return call_int_hook(capable, 0, cred, ns, cap, SECURITY_CAP_NOAUDIT); | ||
| 307 | } | 693 | } |
| 308 | 694 | ||
| 309 | int security_quotactl(int cmds, int type, int id, struct super_block *sb) | 695 | int security_quotactl(int cmds, int type, int id, struct super_block *sb) |
| @@ -468,14 +854,40 @@ EXPORT_SYMBOL(security_add_mnt_opt); | |||
| 468 | 854 | ||
| 469 | int security_inode_alloc(struct inode *inode) | 855 | int security_inode_alloc(struct inode *inode) |
| 470 | { | 856 | { |
| 471 | inode->i_security = NULL; | 857 | int rc = lsm_inode_alloc(inode); |
| 472 | return call_int_hook(inode_alloc_security, 0, inode); | 858 | |
| 859 | if (unlikely(rc)) | ||
| 860 | return rc; | ||
| 861 | rc = call_int_hook(inode_alloc_security, 0, inode); | ||
| 862 | if (unlikely(rc)) | ||
| 863 | security_inode_free(inode); | ||
| 864 | return rc; | ||
| 865 | } | ||
| 866 | |||
| 867 | static void inode_free_by_rcu(struct rcu_head *head) | ||
| 868 | { | ||
| 869 | /* | ||
| 870 | * The rcu head is at the start of the inode blob | ||
| 871 | */ | ||
| 872 | kmem_cache_free(lsm_inode_cache, head); | ||
| 473 | } | 873 | } |
| 474 | 874 | ||
| 475 | void security_inode_free(struct inode *inode) | 875 | void security_inode_free(struct inode *inode) |
| 476 | { | 876 | { |
| 477 | integrity_inode_free(inode); | 877 | integrity_inode_free(inode); |
| 478 | call_void_hook(inode_free_security, inode); | 878 | call_void_hook(inode_free_security, inode); |
| 879 | /* | ||
| 880 | * The inode may still be referenced in a path walk and | ||
| 881 | * a call to security_inode_permission() can be made | ||
| 882 | * after inode_free_security() is called. Ideally, the VFS | ||
| 883 | * wouldn't do this, but fixing that is a much harder | ||
| 884 | * job. For now, simply free the i_security via RCU, and | ||
| 885 | * leave the current inode->i_security pointer intact. | ||
| 886 | * The inode will be freed after the RCU grace period too. | ||
| 887 | */ | ||
| 888 | if (inode->i_security) | ||
| 889 | call_rcu((struct rcu_head *)inode->i_security, | ||
| 890 | inode_free_by_rcu); | ||
| 479 | } | 891 | } |
| 480 | 892 | ||
| 481 | int security_dentry_init_security(struct dentry *dentry, int mode, | 893 | int security_dentry_init_security(struct dentry *dentry, int mode, |
| @@ -905,12 +1317,27 @@ int security_file_permission(struct file *file, int mask) | |||
| 905 | 1317 | ||
| 906 | int security_file_alloc(struct file *file) | 1318 | int security_file_alloc(struct file *file) |
| 907 | { | 1319 | { |
| 908 | return call_int_hook(file_alloc_security, 0, file); | 1320 | int rc = lsm_file_alloc(file); |
| 1321 | |||
| 1322 | if (rc) | ||
| 1323 | return rc; | ||
| 1324 | rc = call_int_hook(file_alloc_security, 0, file); | ||
| 1325 | if (unlikely(rc)) | ||
| 1326 | security_file_free(file); | ||
| 1327 | return rc; | ||
| 909 | } | 1328 | } |
| 910 | 1329 | ||
| 911 | void security_file_free(struct file *file) | 1330 | void security_file_free(struct file *file) |
| 912 | { | 1331 | { |
| 1332 | void *blob; | ||
| 1333 | |||
| 913 | call_void_hook(file_free_security, file); | 1334 | call_void_hook(file_free_security, file); |
| 1335 | |||
| 1336 | blob = file->f_security; | ||
| 1337 | if (blob) { | ||
| 1338 | file->f_security = NULL; | ||
| 1339 | kmem_cache_free(lsm_file_cache, blob); | ||
| 1340 | } | ||
| 914 | } | 1341 | } |
| 915 | 1342 | ||
| 916 | int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | 1343 | int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
| @@ -1012,17 +1439,35 @@ int security_file_open(struct file *file) | |||
| 1012 | 1439 | ||
| 1013 | int security_task_alloc(struct task_struct *task, unsigned long clone_flags) | 1440 | int security_task_alloc(struct task_struct *task, unsigned long clone_flags) |
| 1014 | { | 1441 | { |
| 1015 | return call_int_hook(task_alloc, 0, task, clone_flags); | 1442 | int rc = lsm_task_alloc(task); |
| 1443 | |||
| 1444 | if (rc) | ||
| 1445 | return rc; | ||
| 1446 | rc = call_int_hook(task_alloc, 0, task, clone_flags); | ||
| 1447 | if (unlikely(rc)) | ||
| 1448 | security_task_free(task); | ||
| 1449 | return rc; | ||
| 1016 | } | 1450 | } |
| 1017 | 1451 | ||
| 1018 | void security_task_free(struct task_struct *task) | 1452 | void security_task_free(struct task_struct *task) |
| 1019 | { | 1453 | { |
| 1020 | call_void_hook(task_free, task); | 1454 | call_void_hook(task_free, task); |
| 1455 | |||
| 1456 | kfree(task->security); | ||
| 1457 | task->security = NULL; | ||
| 1021 | } | 1458 | } |
| 1022 | 1459 | ||
| 1023 | int security_cred_alloc_blank(struct cred *cred, gfp_t gfp) | 1460 | int security_cred_alloc_blank(struct cred *cred, gfp_t gfp) |
| 1024 | { | 1461 | { |
| 1025 | return call_int_hook(cred_alloc_blank, 0, cred, gfp); | 1462 | int rc = lsm_cred_alloc(cred, gfp); |
| 1463 | |||
| 1464 | if (rc) | ||
| 1465 | return rc; | ||
| 1466 | |||
| 1467 | rc = call_int_hook(cred_alloc_blank, 0, cred, gfp); | ||
| 1468 | if (unlikely(rc)) | ||
| 1469 | security_cred_free(cred); | ||
| 1470 | return rc; | ||
| 1026 | } | 1471 | } |
| 1027 | 1472 | ||
| 1028 | void security_cred_free(struct cred *cred) | 1473 | void security_cred_free(struct cred *cred) |
| @@ -1035,11 +1480,22 @@ void security_cred_free(struct cred *cred) | |||
| 1035 | return; | 1480 | return; |
| 1036 | 1481 | ||
| 1037 | call_void_hook(cred_free, cred); | 1482 | call_void_hook(cred_free, cred); |
| 1483 | |||
| 1484 | kfree(cred->security); | ||
| 1485 | cred->security = NULL; | ||
| 1038 | } | 1486 | } |
| 1039 | 1487 | ||
| 1040 | int security_prepare_creds(struct cred *new, const struct cred *old, gfp_t gfp) | 1488 | int security_prepare_creds(struct cred *new, const struct cred *old, gfp_t gfp) |
| 1041 | { | 1489 | { |
| 1042 | return call_int_hook(cred_prepare, 0, new, old, gfp); | 1490 | int rc = lsm_cred_alloc(new, gfp); |
| 1491 | |||
| 1492 | if (rc) | ||
| 1493 | return rc; | ||
| 1494 | |||
| 1495 | rc = call_int_hook(cred_prepare, 0, new, old, gfp); | ||
| 1496 | if (unlikely(rc)) | ||
| 1497 | security_cred_free(new); | ||
| 1498 | return rc; | ||
| 1043 | } | 1499 | } |
| 1044 | 1500 | ||
| 1045 | void security_transfer_creds(struct cred *new, const struct cred *old) | 1501 | void security_transfer_creds(struct cred *new, const struct cred *old) |
| @@ -1220,22 +1676,40 @@ void security_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid) | |||
| 1220 | 1676 | ||
| 1221 | int security_msg_msg_alloc(struct msg_msg *msg) | 1677 | int security_msg_msg_alloc(struct msg_msg *msg) |
| 1222 | { | 1678 | { |
| 1223 | return call_int_hook(msg_msg_alloc_security, 0, msg); | 1679 | int rc = lsm_msg_msg_alloc(msg); |
| 1680 | |||
| 1681 | if (unlikely(rc)) | ||
| 1682 | return rc; | ||
| 1683 | rc = call_int_hook(msg_msg_alloc_security, 0, msg); | ||
| 1684 | if (unlikely(rc)) | ||
| 1685 | security_msg_msg_free(msg); | ||
| 1686 | return rc; | ||
| 1224 | } | 1687 | } |
| 1225 | 1688 | ||
| 1226 | void security_msg_msg_free(struct msg_msg *msg) | 1689 | void security_msg_msg_free(struct msg_msg *msg) |
| 1227 | { | 1690 | { |
| 1228 | call_void_hook(msg_msg_free_security, msg); | 1691 | call_void_hook(msg_msg_free_security, msg); |
| 1692 | kfree(msg->security); | ||
| 1693 | msg->security = NULL; | ||
| 1229 | } | 1694 | } |
| 1230 | 1695 | ||
| 1231 | int security_msg_queue_alloc(struct kern_ipc_perm *msq) | 1696 | int security_msg_queue_alloc(struct kern_ipc_perm *msq) |
| 1232 | { | 1697 | { |
| 1233 | return call_int_hook(msg_queue_alloc_security, 0, msq); | 1698 | int rc = lsm_ipc_alloc(msq); |
| 1699 | |||
| 1700 | if (unlikely(rc)) | ||
| 1701 | return rc; | ||
| 1702 | rc = call_int_hook(msg_queue_alloc_security, 0, msq); | ||
| 1703 | if (unlikely(rc)) | ||
| 1704 | security_msg_queue_free(msq); | ||
| 1705 | return rc; | ||
| 1234 | } | 1706 | } |
| 1235 | 1707 | ||
| 1236 | void security_msg_queue_free(struct kern_ipc_perm *msq) | 1708 | void security_msg_queue_free(struct kern_ipc_perm *msq) |
| 1237 | { | 1709 | { |
| 1238 | call_void_hook(msg_queue_free_security, msq); | 1710 | call_void_hook(msg_queue_free_security, msq); |
| 1711 | kfree(msq->security); | ||
| 1712 | msq->security = NULL; | ||
| 1239 | } | 1713 | } |
| 1240 | 1714 | ||
| 1241 | int security_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg) | 1715 | int security_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg) |
| @@ -1262,12 +1736,21 @@ int security_msg_queue_msgrcv(struct kern_ipc_perm *msq, struct msg_msg *msg, | |||
| 1262 | 1736 | ||
| 1263 | int security_shm_alloc(struct kern_ipc_perm *shp) | 1737 | int security_shm_alloc(struct kern_ipc_perm *shp) |
| 1264 | { | 1738 | { |
| 1265 | return call_int_hook(shm_alloc_security, 0, shp); | 1739 | int rc = lsm_ipc_alloc(shp); |
| 1740 | |||
| 1741 | if (unlikely(rc)) | ||
| 1742 | return rc; | ||
| 1743 | rc = call_int_hook(shm_alloc_security, 0, shp); | ||
| 1744 | if (unlikely(rc)) | ||
| 1745 | security_shm_free(shp); | ||
| 1746 | return rc; | ||
| 1266 | } | 1747 | } |
| 1267 | 1748 | ||
| 1268 | void security_shm_free(struct kern_ipc_perm *shp) | 1749 | void security_shm_free(struct kern_ipc_perm *shp) |
| 1269 | { | 1750 | { |
| 1270 | call_void_hook(shm_free_security, shp); | 1751 | call_void_hook(shm_free_security, shp); |
| 1752 | kfree(shp->security); | ||
| 1753 | shp->security = NULL; | ||
| 1271 | } | 1754 | } |
| 1272 | 1755 | ||
| 1273 | int security_shm_associate(struct kern_ipc_perm *shp, int shmflg) | 1756 | int security_shm_associate(struct kern_ipc_perm *shp, int shmflg) |
| @@ -1287,12 +1770,21 @@ int security_shm_shmat(struct kern_ipc_perm *shp, char __user *shmaddr, int shmf | |||
| 1287 | 1770 | ||
| 1288 | int security_sem_alloc(struct kern_ipc_perm *sma) | 1771 | int security_sem_alloc(struct kern_ipc_perm *sma) |
| 1289 | { | 1772 | { |
| 1290 | return call_int_hook(sem_alloc_security, 0, sma); | 1773 | int rc = lsm_ipc_alloc(sma); |
| 1774 | |||
| 1775 | if (unlikely(rc)) | ||
| 1776 | return rc; | ||
| 1777 | rc = call_int_hook(sem_alloc_security, 0, sma); | ||
| 1778 | if (unlikely(rc)) | ||
| 1779 | security_sem_free(sma); | ||
| 1780 | return rc; | ||
| 1291 | } | 1781 | } |
| 1292 | 1782 | ||
| 1293 | void security_sem_free(struct kern_ipc_perm *sma) | 1783 | void security_sem_free(struct kern_ipc_perm *sma) |
| 1294 | { | 1784 | { |
| 1295 | call_void_hook(sem_free_security, sma); | 1785 | call_void_hook(sem_free_security, sma); |
| 1786 | kfree(sma->security); | ||
| 1787 | sma->security = NULL; | ||
| 1296 | } | 1788 | } |
| 1297 | 1789 | ||
| 1298 | int security_sem_associate(struct kern_ipc_perm *sma, int semflg) | 1790 | int security_sem_associate(struct kern_ipc_perm *sma, int semflg) |
| @@ -1319,14 +1811,30 @@ void security_d_instantiate(struct dentry *dentry, struct inode *inode) | |||
| 1319 | } | 1811 | } |
| 1320 | EXPORT_SYMBOL(security_d_instantiate); | 1812 | EXPORT_SYMBOL(security_d_instantiate); |
| 1321 | 1813 | ||
| 1322 | int security_getprocattr(struct task_struct *p, char *name, char **value) | 1814 | int security_getprocattr(struct task_struct *p, const char *lsm, char *name, |
| 1815 | char **value) | ||
| 1323 | { | 1816 | { |
| 1324 | return call_int_hook(getprocattr, -EINVAL, p, name, value); | 1817 | struct security_hook_list *hp; |
| 1818 | |||
| 1819 | hlist_for_each_entry(hp, &security_hook_heads.getprocattr, list) { | ||
| 1820 | if (lsm != NULL && strcmp(lsm, hp->lsm)) | ||
| 1821 | continue; | ||
| 1822 | return hp->hook.getprocattr(p, name, value); | ||
| 1823 | } | ||
| 1824 | return -EINVAL; | ||
| 1325 | } | 1825 | } |
| 1326 | 1826 | ||
| 1327 | int security_setprocattr(const char *name, void *value, size_t size) | 1827 | int security_setprocattr(const char *lsm, const char *name, void *value, |
| 1828 | size_t size) | ||
| 1328 | { | 1829 | { |
| 1329 | return call_int_hook(setprocattr, -EINVAL, name, value, size); | 1830 | struct security_hook_list *hp; |
| 1831 | |||
| 1832 | hlist_for_each_entry(hp, &security_hook_heads.setprocattr, list) { | ||
| 1833 | if (lsm != NULL && strcmp(lsm, hp->lsm)) | ||
| 1834 | continue; | ||
| 1835 | return hp->hook.setprocattr(name, value, size); | ||
| 1836 | } | ||
| 1837 | return -EINVAL; | ||
| 1330 | } | 1838 | } |
| 1331 | 1839 | ||
| 1332 | int security_netlink_send(struct sock *sk, struct sk_buff *skb) | 1840 | int security_netlink_send(struct sock *sk, struct sk_buff *skb) |
