summaryrefslogtreecommitdiffstats
path: root/security/security.c
diff options
context:
space:
mode:
authorCasey Schaufler <casey@schaufler-ca.com>2018-11-12 12:30:56 -0500
committerKees Cook <keescook@chromium.org>2019-01-08 16:18:44 -0500
commitbbd3662a834813730912a58efb44dd6df6d952e6 (patch)
treef4c0252814e717185845bde03fe88d341d5967b5 /security/security.c
parent43fc460907dc56a3450654efc6ba1dfbcd4594eb (diff)
Infrastructure management of the cred security blob
Move management of the cred security blob out of the security modules and into the security infrastructre. Instead of allocating and freeing space the security modules 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>
Diffstat (limited to 'security/security.c')
-rw-r--r--security/security.c89
1 files changed, 87 insertions, 2 deletions
diff --git a/security/security.c b/security/security.c
index 60b39db95c2f..09be8ce007a2 100644
--- a/security/security.c
+++ b/security/security.c
@@ -41,6 +41,8 @@ struct security_hook_heads security_hook_heads __lsm_ro_after_init;
41static ATOMIC_NOTIFIER_HEAD(lsm_notifier_chain); 41static ATOMIC_NOTIFIER_HEAD(lsm_notifier_chain);
42 42
43char *lsm_names; 43char *lsm_names;
44static struct lsm_blob_sizes blob_sizes __lsm_ro_after_init;
45
44/* Boot-time LSM user choice */ 46/* Boot-time LSM user choice */
45static __initdata const char *chosen_lsm_order; 47static __initdata const char *chosen_lsm_order;
46static __initdata const char *chosen_major_lsm; 48static __initdata const char *chosen_major_lsm;
@@ -139,6 +141,25 @@ static bool __init lsm_allowed(struct lsm_info *lsm)
139 return true; 141 return true;
140} 142}
141 143
144static void __init lsm_set_blob_size(int *need, int *lbs)
145{
146 int offset;
147
148 if (*need > 0) {
149 offset = *lbs;
150 *lbs += *need;
151 *need = offset;
152 }
153}
154
155static void __init lsm_set_blob_sizes(struct lsm_blob_sizes *needed)
156{
157 if (!needed)
158 return;
159
160 lsm_set_blob_size(&needed->lbs_cred, &blob_sizes.lbs_cred);
161}
162
142/* Prepare LSM for initialization. */ 163/* Prepare LSM for initialization. */
143static void __init prepare_lsm(struct lsm_info *lsm) 164static void __init prepare_lsm(struct lsm_info *lsm)
144{ 165{
@@ -153,6 +174,8 @@ static void __init prepare_lsm(struct lsm_info *lsm)
153 exclusive = lsm; 174 exclusive = lsm;
154 init_debug("exclusive chosen: %s\n", lsm->name); 175 init_debug("exclusive chosen: %s\n", lsm->name);
155 } 176 }
177
178 lsm_set_blob_sizes(lsm->blobs);
156 } 179 }
157} 180}
158 181
@@ -255,6 +278,8 @@ static void __init ordered_lsm_init(void)
255 for (lsm = ordered_lsms; *lsm; lsm++) 278 for (lsm = ordered_lsms; *lsm; lsm++)
256 prepare_lsm(*lsm); 279 prepare_lsm(*lsm);
257 280
281 init_debug("cred blob size = %d\n", blob_sizes.lbs_cred);
282
258 for (lsm = ordered_lsms; *lsm; lsm++) 283 for (lsm = ordered_lsms; *lsm; lsm++)
259 initialize_lsm(*lsm); 284 initialize_lsm(*lsm);
260 285
@@ -382,6 +407,47 @@ int unregister_lsm_notifier(struct notifier_block *nb)
382} 407}
383EXPORT_SYMBOL(unregister_lsm_notifier); 408EXPORT_SYMBOL(unregister_lsm_notifier);
384 409
410/**
411 * lsm_cred_alloc - allocate a composite cred blob
412 * @cred: the cred that needs a blob
413 * @gfp: allocation type
414 *
415 * Allocate the cred blob for all the modules
416 *
417 * Returns 0, or -ENOMEM if memory can't be allocated.
418 */
419static int lsm_cred_alloc(struct cred *cred, gfp_t gfp)
420{
421 if (blob_sizes.lbs_cred == 0) {
422 cred->security = NULL;
423 return 0;
424 }
425
426 cred->security = kzalloc(blob_sizes.lbs_cred, gfp);
427 if (cred->security == NULL)
428 return -ENOMEM;
429 return 0;
430}
431
432/**
433 * lsm_early_cred - during initialization allocate a composite cred blob
434 * @cred: the cred that needs a blob
435 *
436 * Allocate the cred blob for all the modules if it's not already there
437 */
438void __init lsm_early_cred(struct cred *cred)
439{
440 int rc;
441
442 if (cred == NULL)
443 panic("%s: NULL cred.\n", __func__);
444 if (cred->security != NULL)
445 return;
446 rc = lsm_cred_alloc(cred, GFP_KERNEL);
447 if (rc)
448 panic("%s: Early cred alloc failed.\n", __func__);
449}
450
385/* 451/*
386 * Hook list operation macros. 452 * Hook list operation macros.
387 * 453 *
@@ -1195,17 +1261,36 @@ void security_task_free(struct task_struct *task)
1195 1261
1196int security_cred_alloc_blank(struct cred *cred, gfp_t gfp) 1262int security_cred_alloc_blank(struct cred *cred, gfp_t gfp)
1197{ 1263{
1198 return call_int_hook(cred_alloc_blank, 0, cred, gfp); 1264 int rc = lsm_cred_alloc(cred, gfp);
1265
1266 if (rc)
1267 return rc;
1268
1269 rc = call_int_hook(cred_alloc_blank, 0, cred, gfp);
1270 if (rc)
1271 security_cred_free(cred);
1272 return rc;
1199} 1273}
1200 1274
1201void security_cred_free(struct cred *cred) 1275void security_cred_free(struct cred *cred)
1202{ 1276{
1203 call_void_hook(cred_free, cred); 1277 call_void_hook(cred_free, cred);
1278
1279 kfree(cred->security);
1280 cred->security = NULL;
1204} 1281}
1205 1282
1206int security_prepare_creds(struct cred *new, const struct cred *old, gfp_t gfp) 1283int security_prepare_creds(struct cred *new, const struct cred *old, gfp_t gfp)
1207{ 1284{
1208 return call_int_hook(cred_prepare, 0, new, old, gfp); 1285 int rc = lsm_cred_alloc(new, gfp);
1286
1287 if (rc)
1288 return rc;
1289
1290 rc = call_int_hook(cred_prepare, 0, new, old, gfp);
1291 if (rc)
1292 security_cred_free(new);
1293 return rc;
1209} 1294}
1210 1295
1211void security_transfer_creds(struct cred *new, const struct cred *old) 1296void security_transfer_creds(struct cred *new, const struct cred *old)