diff options
author | David Howells <dhowells@redhat.com> | 2008-11-13 18:39:28 -0500 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2008-11-13 18:39:28 -0500 |
commit | 3a3b7ce9336952ea7b9564d976d068a238976c9d (patch) | |
tree | 3f0a3be33022492161f534636a20a4b1059f8236 /kernel/cred.c | |
parent | 1bfdc75ae077d60a01572a7781ec6264d55ab1b9 (diff) |
CRED: Allow kernel services to override LSM settings for task actions
Allow kernel services to override LSM settings appropriate to the actions
performed by a task by duplicating a set of credentials, modifying it and then
using task_struct::cred to point to it when performing operations on behalf of
a task.
This is used, for example, by CacheFiles which has to transparently access the
cache on behalf of a process that thinks it is doing, say, NFS accesses with a
potentially inappropriate (with respect to accessing the cache) set of
credentials.
This patch provides two LSM hooks for modifying a task security record:
(*) security_kernel_act_as() which allows modification of the security datum
with which a task acts on other objects (most notably files).
(*) security_kernel_create_files_as() which allows modification of the
security datum that is used to initialise the security data on a file that
a task creates.
The patch also provides four new credentials handling functions, which wrap the
LSM functions:
(1) prepare_kernel_cred()
Prepare a set of credentials for a kernel service to use, based either on
a daemon's credentials or on init_cred. All the keyrings are cleared.
(2) set_security_override()
Set the LSM security ID in a set of credentials to a specific security
context, assuming permission from the LSM policy.
(3) set_security_override_from_ctx()
As (2), but takes the security context as a string.
(4) set_create_files_as()
Set the file creation LSM security ID in a set of credentials to be the
same as that on a particular inode.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com> [Smack changes]
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'kernel/cred.c')
-rw-r--r-- | kernel/cred.c | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/kernel/cred.c b/kernel/cred.c index f3ca10660617..13697ca2bb38 100644 --- a/kernel/cred.c +++ b/kernel/cred.c | |||
@@ -462,3 +462,116 @@ void __init cred_init(void) | |||
462 | cred_jar = kmem_cache_create("cred_jar", sizeof(struct cred), | 462 | cred_jar = kmem_cache_create("cred_jar", sizeof(struct cred), |
463 | 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL); | 463 | 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL); |
464 | } | 464 | } |
465 | |||
466 | /** | ||
467 | * prepare_kernel_cred - Prepare a set of credentials for a kernel service | ||
468 | * @daemon: A userspace daemon to be used as a reference | ||
469 | * | ||
470 | * Prepare a set of credentials for a kernel service. This can then be used to | ||
471 | * override a task's own credentials so that work can be done on behalf of that | ||
472 | * task that requires a different subjective context. | ||
473 | * | ||
474 | * @daemon is used to provide a base for the security record, but can be NULL. | ||
475 | * If @daemon is supplied, then the security data will be derived from that; | ||
476 | * otherwise they'll be set to 0 and no groups, full capabilities and no keys. | ||
477 | * | ||
478 | * The caller may change these controls afterwards if desired. | ||
479 | * | ||
480 | * Returns the new credentials or NULL if out of memory. | ||
481 | * | ||
482 | * Does not take, and does not return holding current->cred_replace_mutex. | ||
483 | */ | ||
484 | struct cred *prepare_kernel_cred(struct task_struct *daemon) | ||
485 | { | ||
486 | const struct cred *old; | ||
487 | struct cred *new; | ||
488 | |||
489 | new = kmem_cache_alloc(cred_jar, GFP_KERNEL); | ||
490 | if (!new) | ||
491 | return NULL; | ||
492 | |||
493 | if (daemon) | ||
494 | old = get_task_cred(daemon); | ||
495 | else | ||
496 | old = get_cred(&init_cred); | ||
497 | |||
498 | get_uid(new->user); | ||
499 | get_group_info(new->group_info); | ||
500 | |||
501 | #ifdef CONFIG_KEYS | ||
502 | atomic_inc(&init_tgcred.usage); | ||
503 | new->tgcred = &init_tgcred; | ||
504 | new->request_key_auth = NULL; | ||
505 | new->thread_keyring = NULL; | ||
506 | new->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING; | ||
507 | #endif | ||
508 | |||
509 | #ifdef CONFIG_SECURITY | ||
510 | new->security = NULL; | ||
511 | #endif | ||
512 | if (security_prepare_creds(new, old, GFP_KERNEL) < 0) | ||
513 | goto error; | ||
514 | |||
515 | atomic_set(&new->usage, 1); | ||
516 | put_cred(old); | ||
517 | return new; | ||
518 | |||
519 | error: | ||
520 | put_cred(new); | ||
521 | return NULL; | ||
522 | } | ||
523 | EXPORT_SYMBOL(prepare_kernel_cred); | ||
524 | |||
525 | /** | ||
526 | * set_security_override - Set the security ID in a set of credentials | ||
527 | * @new: The credentials to alter | ||
528 | * @secid: The LSM security ID to set | ||
529 | * | ||
530 | * Set the LSM security ID in a set of credentials so that the subjective | ||
531 | * security is overridden when an alternative set of credentials is used. | ||
532 | */ | ||
533 | int set_security_override(struct cred *new, u32 secid) | ||
534 | { | ||
535 | return security_kernel_act_as(new, secid); | ||
536 | } | ||
537 | EXPORT_SYMBOL(set_security_override); | ||
538 | |||
539 | /** | ||
540 | * set_security_override_from_ctx - Set the security ID in a set of credentials | ||
541 | * @new: The credentials to alter | ||
542 | * @secctx: The LSM security context to generate the security ID from. | ||
543 | * | ||
544 | * Set the LSM security ID in a set of credentials so that the subjective | ||
545 | * security is overridden when an alternative set of credentials is used. The | ||
546 | * security ID is specified in string form as a security context to be | ||
547 | * interpreted by the LSM. | ||
548 | */ | ||
549 | int set_security_override_from_ctx(struct cred *new, const char *secctx) | ||
550 | { | ||
551 | u32 secid; | ||
552 | int ret; | ||
553 | |||
554 | ret = security_secctx_to_secid(secctx, strlen(secctx), &secid); | ||
555 | if (ret < 0) | ||
556 | return ret; | ||
557 | |||
558 | return set_security_override(new, secid); | ||
559 | } | ||
560 | EXPORT_SYMBOL(set_security_override_from_ctx); | ||
561 | |||
562 | /** | ||
563 | * set_create_files_as - Set the LSM file create context in a set of credentials | ||
564 | * @new: The credentials to alter | ||
565 | * @inode: The inode to take the context from | ||
566 | * | ||
567 | * Change the LSM file creation context in a set of credentials to be the same | ||
568 | * as the object context of the specified inode, so that the new inodes have | ||
569 | * the same MAC context as that inode. | ||
570 | */ | ||
571 | int set_create_files_as(struct cred *new, struct inode *inode) | ||
572 | { | ||
573 | new->fsuid = inode->i_uid; | ||
574 | new->fsgid = inode->i_gid; | ||
575 | return security_kernel_create_files_as(new, inode); | ||
576 | } | ||
577 | EXPORT_SYMBOL(set_create_files_as); | ||