Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

LSM: Infrastructure management of the file security

Move management of the file->f_security blob out of the
individual security modules and into the infrastructure.
The modules no longer allocate or free the data, instead
they tell the infrastructure how much space they require.

Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
Reviewed-by: Kees Cook <keescook@chromium.org>
[kees: adjusted for ordered init series]
Signed-off-by: Kees Cook <keescook@chromium.org>

authored by

Casey Schaufler and committed by
Kees Cook
33bf60ca f28952ac

+72 -51
+1
include/linux/lsm_hooks.h
··· 2032 2032 */ 2033 2033 struct lsm_blob_sizes { 2034 2034 int lbs_cred; 2035 + int lbs_file; 2035 2036 }; 2036 2037 2037 2038 /*
+4 -1
security/apparmor/include/file.h
··· 32 32 AA_MAY_CHMOD | AA_MAY_CHOWN | AA_MAY_LOCK | \ 33 33 AA_EXEC_MMAP | AA_MAY_LINK) 34 34 35 - #define file_ctx(X) ((struct aa_file_ctx *)(X)->f_security) 35 + static inline struct aa_file_ctx *file_ctx(struct file *file) 36 + { 37 + return file->f_security + apparmor_blob_sizes.lbs_file; 38 + } 36 39 37 40 /* struct aa_file_ctx - the AppArmor context the file was opened in 38 41 * @lock: lock to update the ctx
+10 -9
security/apparmor/lsm.c
··· 434 434 435 435 static int apparmor_file_alloc_security(struct file *file) 436 436 { 437 - int error = 0; 438 - 439 - /* freed by apparmor_file_free_security */ 437 + struct aa_file_ctx *ctx = file_ctx(file); 440 438 struct aa_label *label = begin_current_label_crit_section(); 441 - file->f_security = aa_alloc_file_ctx(label, GFP_KERNEL); 442 - if (!file_ctx(file)) 443 - error = -ENOMEM; 444 - end_current_label_crit_section(label); 445 439 446 - return error; 440 + spin_lock_init(&ctx->lock); 441 + rcu_assign_pointer(ctx->label, aa_get_label(label)); 442 + end_current_label_crit_section(label); 443 + return 0; 447 444 } 448 445 449 446 static void apparmor_file_free_security(struct file *file) 450 447 { 451 - aa_free_file_ctx(file_ctx(file)); 448 + struct aa_file_ctx *ctx = file_ctx(file); 449 + 450 + if (ctx) 451 + aa_put_label(rcu_access_pointer(ctx->label)); 452 452 } 453 453 454 454 static int common_file_perm(const char *op, struct file *file, u32 mask) ··· 1156 1156 */ 1157 1157 struct lsm_blob_sizes apparmor_blob_sizes __lsm_ro_after_init = { 1158 1158 .lbs_cred = sizeof(struct aa_task_ctx *), 1159 + .lbs_file = sizeof(struct aa_file_ctx), 1159 1160 }; 1160 1161 1161 1162 static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = {
+51 -3
security/security.c
··· 40 40 struct security_hook_heads security_hook_heads __lsm_ro_after_init; 41 41 static ATOMIC_NOTIFIER_HEAD(lsm_notifier_chain); 42 42 43 + static struct kmem_cache *lsm_file_cache; 44 + 43 45 char *lsm_names; 44 46 static struct lsm_blob_sizes blob_sizes __lsm_ro_after_init; 45 47 ··· 160 158 return; 161 159 162 160 lsm_set_blob_size(&needed->lbs_cred, &blob_sizes.lbs_cred); 161 + lsm_set_blob_size(&needed->lbs_file, &blob_sizes.lbs_file); 163 162 } 164 163 165 164 /* Prepare LSM for initialization. */ ··· 282 279 prepare_lsm(*lsm); 283 280 284 281 init_debug("cred blob size = %d\n", blob_sizes.lbs_cred); 282 + init_debug("file blob size = %d\n", blob_sizes.lbs_file); 283 + 284 + /* 285 + * Create any kmem_caches needed for blobs 286 + */ 287 + if (blob_sizes.lbs_file) 288 + lsm_file_cache = kmem_cache_create("lsm_file_cache", 289 + blob_sizes.lbs_file, 0, 290 + SLAB_PANIC, NULL); 285 291 286 292 for (lsm = ordered_lsms; *lsm; lsm++) 287 293 initialize_lsm(*lsm); ··· 458 446 rc = lsm_cred_alloc(cred, GFP_KERNEL); 459 447 if (rc) 460 448 panic("%s: Early cred alloc failed.\n", __func__); 449 + } 450 + 451 + /** 452 + * lsm_file_alloc - allocate a composite file blob 453 + * @file: the file that needs a blob 454 + * 455 + * Allocate the file blob for all the modules 456 + * 457 + * Returns 0, or -ENOMEM if memory can't be allocated. 458 + */ 459 + static int lsm_file_alloc(struct file *file) 460 + { 461 + if (!lsm_file_cache) { 462 + file->f_security = NULL; 463 + return 0; 464 + } 465 + 466 + file->f_security = kmem_cache_zalloc(lsm_file_cache, GFP_KERNEL); 467 + if (file->f_security == NULL) 468 + return -ENOMEM; 469 + return 0; 461 470 } 462 471 463 472 /* ··· 1177 1144 1178 1145 int security_file_alloc(struct file *file) 1179 1146 { 1180 - return call_int_hook(file_alloc_security, 0, file); 1147 + int rc = lsm_file_alloc(file); 1148 + 1149 + if (rc) 1150 + return rc; 1151 + rc = call_int_hook(file_alloc_security, 0, file); 1152 + if (unlikely(rc)) 1153 + security_file_free(file); 1154 + return rc; 1181 1155 } 1182 1156 1183 1157 void security_file_free(struct file *file) 1184 1158 { 1159 + void *blob; 1160 + 1185 1161 call_void_hook(file_free_security, file); 1162 + 1163 + blob = file->f_security; 1164 + if (blob) { 1165 + file->f_security = NULL; 1166 + kmem_cache_free(lsm_file_cache, blob); 1167 + } 1186 1168 } 1187 1169 1188 1170 int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ··· 1315 1267 return rc; 1316 1268 1317 1269 rc = call_int_hook(cred_alloc_blank, 0, cred, gfp); 1318 - if (rc) 1270 + if (unlikely(rc)) 1319 1271 security_cred_free(cred); 1320 1272 return rc; 1321 1273 } ··· 1336 1288 return rc; 1337 1289 1338 1290 rc = call_int_hook(cred_prepare, 0, new, old, gfp); 1339 - if (rc) 1291 + if (unlikely(rc)) 1340 1292 security_cred_free(new); 1341 1293 return rc; 1342 1294 }
+2 -23
security/selinux/hooks.c
··· 146 146 __setup("checkreqprot=", checkreqprot_setup); 147 147 148 148 static struct kmem_cache *sel_inode_cache; 149 - static struct kmem_cache *file_security_cache; 150 149 151 150 /** 152 151 * selinux_secmark_enabled - Check to see if SECMARK is currently enabled ··· 377 378 378 379 static int file_alloc_security(struct file *file) 379 380 { 380 - struct file_security_struct *fsec; 381 + struct file_security_struct *fsec = selinux_file(file); 381 382 u32 sid = current_sid(); 382 - 383 - fsec = kmem_cache_zalloc(file_security_cache, GFP_KERNEL); 384 - if (!fsec) 385 - return -ENOMEM; 386 383 387 384 fsec->sid = sid; 388 385 fsec->fown_sid = sid; 389 - file->f_security = fsec; 390 386 391 387 return 0; 392 - } 393 - 394 - static void file_free_security(struct file *file) 395 - { 396 - struct file_security_struct *fsec = selinux_file(file); 397 - file->f_security = NULL; 398 - kmem_cache_free(file_security_cache, fsec); 399 388 } 400 389 401 390 static int superblock_alloc_security(struct super_block *sb) ··· 3330 3343 static int selinux_file_alloc_security(struct file *file) 3331 3344 { 3332 3345 return file_alloc_security(file); 3333 - } 3334 - 3335 - static void selinux_file_free_security(struct file *file) 3336 - { 3337 - file_free_security(file); 3338 3346 } 3339 3347 3340 3348 /* ··· 6628 6646 6629 6647 struct lsm_blob_sizes selinux_blob_sizes __lsm_ro_after_init = { 6630 6648 .lbs_cred = sizeof(struct task_security_struct), 6649 + .lbs_file = sizeof(struct file_security_struct), 6631 6650 }; 6632 6651 6633 6652 static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = { ··· 6700 6717 6701 6718 LSM_HOOK_INIT(file_permission, selinux_file_permission), 6702 6719 LSM_HOOK_INIT(file_alloc_security, selinux_file_alloc_security), 6703 - LSM_HOOK_INIT(file_free_security, selinux_file_free_security), 6704 6720 LSM_HOOK_INIT(file_ioctl, selinux_file_ioctl), 6705 6721 LSM_HOOK_INIT(mmap_file, selinux_mmap_file), 6706 6722 LSM_HOOK_INIT(mmap_addr, selinux_mmap_addr), ··· 6883 6901 6884 6902 sel_inode_cache = kmem_cache_create("selinux_inode_security", 6885 6903 sizeof(struct inode_security_struct), 6886 - 0, SLAB_PANIC, NULL); 6887 - file_security_cache = kmem_cache_create("selinux_file_security", 6888 - sizeof(struct file_security_struct), 6889 6904 0, SLAB_PANIC, NULL); 6890 6905 avc_init(); 6891 6906
+1 -1
security/selinux/include/objsec.h
··· 167 167 168 168 static inline struct file_security_struct *selinux_file(const struct file *file) 169 169 { 170 - return file->f_security; 170 + return file->f_security + selinux_blob_sizes.lbs_file; 171 171 } 172 172 173 173 #endif /* _SELINUX_OBJSEC_H_ */
+2 -1
security/smack/smack.h
··· 364 364 365 365 static inline struct smack_known **smack_file(const struct file *file) 366 366 { 367 - return (struct smack_known **)&file->f_security; 367 + return (struct smack_known **)(file->f_security + 368 + smack_blob_sizes.lbs_file); 368 369 } 369 370 370 371 /*
+1 -13
security/smack/smack_lsm.c
··· 1496 1496 } 1497 1497 1498 1498 /** 1499 - * smack_file_free_security - clear a file security blob 1500 - * @file: the object 1501 - * 1502 - * The security blob for a file is a pointer to the master 1503 - * label list, so no memory is freed. 1504 - */ 1505 - static void smack_file_free_security(struct file *file) 1506 - { 1507 - file->f_security = NULL; 1508 - } 1509 - 1510 - /** 1511 1499 * smack_file_ioctl - Smack check on ioctls 1512 1500 * @file: the object 1513 1501 * @cmd: what to do ··· 4547 4559 4548 4560 struct lsm_blob_sizes smack_blob_sizes __lsm_ro_after_init = { 4549 4561 .lbs_cred = sizeof(struct task_smack), 4562 + .lbs_file = sizeof(struct smack_known *), 4550 4563 }; 4551 4564 4552 4565 static struct security_hook_list smack_hooks[] __lsm_ro_after_init = { ··· 4584 4595 LSM_HOOK_INIT(inode_getsecid, smack_inode_getsecid), 4585 4596 4586 4597 LSM_HOOK_INIT(file_alloc_security, smack_file_alloc_security), 4587 - LSM_HOOK_INIT(file_free_security, smack_file_free_security), 4588 4598 LSM_HOOK_INIT(file_ioctl, smack_file_ioctl), 4589 4599 LSM_HOOK_INIT(file_lock, smack_file_lock), 4590 4600 LSM_HOOK_INIT(file_fcntl, smack_file_fcntl),