aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2008-11-13 18:39:28 -0500
committerJames Morris <jmorris@namei.org>2008-11-13 18:39:28 -0500
commit3a3b7ce9336952ea7b9564d976d068a238976c9d (patch)
tree3f0a3be33022492161f534636a20a4b1059f8236 /kernel
parent1bfdc75ae077d60a01572a7781ec6264d55ab1b9 (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')
-rw-r--r--kernel/cred.c113
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 */
484struct 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
519error:
520 put_cred(new);
521 return NULL;
522}
523EXPORT_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 */
533int set_security_override(struct cred *new, u32 secid)
534{
535 return security_kernel_act_as(new, secid);
536}
537EXPORT_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 */
549int 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}
560EXPORT_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 */
571int 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}
577EXPORT_SYMBOL(set_create_files_as);