TOMOYO: Abstract use of cred security blob

Don't use the cred->security pointer directly.
Provide helper functions that provide the security blob pointer.

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>
This commit is contained in:
Casey Schaufler 2018-09-21 17:18:07 -07:00 committed by Kees Cook
parent 69b5a44a95
commit 43fc460907
4 changed files with 64 additions and 16 deletions

View File

@ -29,6 +29,7 @@
#include <linux/in.h> #include <linux/in.h>
#include <linux/in6.h> #include <linux/in6.h>
#include <linux/un.h> #include <linux/un.h>
#include <linux/lsm_hooks.h>
#include <net/sock.h> #include <net/sock.h>
#include <net/af_unix.h> #include <net/af_unix.h>
#include <net/ip.h> #include <net/ip.h>
@ -1062,6 +1063,7 @@ void tomoyo_write_log2(struct tomoyo_request_info *r, int len, const char *fmt,
/********** External variable definitions. **********/ /********** External variable definitions. **********/
extern bool tomoyo_policy_loaded; extern bool tomoyo_policy_loaded;
extern int tomoyo_enabled;
extern const char * const tomoyo_condition_keyword extern const char * const tomoyo_condition_keyword
[TOMOYO_MAX_CONDITION_KEYWORD]; [TOMOYO_MAX_CONDITION_KEYWORD];
extern const char * const tomoyo_dif[TOMOYO_MAX_DOMAIN_INFO_FLAGS]; extern const char * const tomoyo_dif[TOMOYO_MAX_DOMAIN_INFO_FLAGS];
@ -1196,6 +1198,17 @@ static inline void tomoyo_put_group(struct tomoyo_group *group)
atomic_dec(&group->head.users); atomic_dec(&group->head.users);
} }
/**
* tomoyo_cred - Get a pointer to the tomoyo cred security blob
* @cred - the relevant cred
*
* Returns pointer to the tomoyo cred blob.
*/
static inline struct tomoyo_domain_info **tomoyo_cred(const struct cred *cred)
{
return (struct tomoyo_domain_info **)&cred->security;
}
/** /**
* tomoyo_domain - Get "struct tomoyo_domain_info" for current thread. * tomoyo_domain - Get "struct tomoyo_domain_info" for current thread.
* *
@ -1203,7 +1216,9 @@ static inline void tomoyo_put_group(struct tomoyo_group *group)
*/ */
static inline struct tomoyo_domain_info *tomoyo_domain(void) static inline struct tomoyo_domain_info *tomoyo_domain(void)
{ {
return current_cred()->security; struct tomoyo_domain_info **blob = tomoyo_cred(current_cred());
return *blob;
} }
/** /**
@ -1216,7 +1231,9 @@ static inline struct tomoyo_domain_info *tomoyo_domain(void)
static inline struct tomoyo_domain_info *tomoyo_real_domain(struct task_struct static inline struct tomoyo_domain_info *tomoyo_real_domain(struct task_struct
*task) *task)
{ {
return task_cred_xxx(task, security); struct tomoyo_domain_info **blob = tomoyo_cred(get_task_cred(task));
return *blob;
} }
/** /**

View File

@ -678,6 +678,7 @@ out:
*/ */
int tomoyo_find_next_domain(struct linux_binprm *bprm) int tomoyo_find_next_domain(struct linux_binprm *bprm)
{ {
struct tomoyo_domain_info **blob;
struct tomoyo_domain_info *old_domain = tomoyo_domain(); struct tomoyo_domain_info *old_domain = tomoyo_domain();
struct tomoyo_domain_info *domain = NULL; struct tomoyo_domain_info *domain = NULL;
const char *original_name = bprm->filename; const char *original_name = bprm->filename;
@ -843,7 +844,8 @@ force_jump_domain:
domain = old_domain; domain = old_domain;
/* Update reference count on "struct tomoyo_domain_info". */ /* Update reference count on "struct tomoyo_domain_info". */
atomic_inc(&domain->users); atomic_inc(&domain->users);
bprm->cred->security = domain; blob = tomoyo_cred(bprm->cred);
*blob = domain;
kfree(exename.name); kfree(exename.name);
if (!retval) { if (!retval) {
ee->r.domain = domain; ee->r.domain = domain;

View File

@ -71,9 +71,12 @@ static ssize_t tomoyo_write_self(struct file *file, const char __user *buf,
if (!cred) { if (!cred) {
error = -ENOMEM; error = -ENOMEM;
} else { } else {
struct tomoyo_domain_info *old_domain = struct tomoyo_domain_info **blob;
cred->security; struct tomoyo_domain_info *old_domain;
cred->security = new_domain;
blob = tomoyo_cred(cred);
old_domain = *blob;
*blob = new_domain;
atomic_inc(&new_domain->users); atomic_inc(&new_domain->users);
atomic_dec(&old_domain->users); atomic_dec(&old_domain->users);
commit_creds(cred); commit_creds(cred);
@ -234,10 +237,14 @@ static void __init tomoyo_create_entry(const char *name, const umode_t mode,
*/ */
static int __init tomoyo_initerface_init(void) static int __init tomoyo_initerface_init(void)
{ {
struct tomoyo_domain_info *domain;
struct dentry *tomoyo_dir; struct dentry *tomoyo_dir;
if (!tomoyo_enabled)
return 0;
domain = tomoyo_domain();
/* Don't create securityfs entries unless registered. */ /* Don't create securityfs entries unless registered. */
if (current_cred()->security != &tomoyo_kernel_domain) if (domain != &tomoyo_kernel_domain)
return 0; return 0;
tomoyo_dir = securityfs_create_dir("tomoyo", NULL); tomoyo_dir = securityfs_create_dir("tomoyo", NULL);

View File

@ -18,7 +18,9 @@
*/ */
static int tomoyo_cred_alloc_blank(struct cred *new, gfp_t gfp) static int tomoyo_cred_alloc_blank(struct cred *new, gfp_t gfp)
{ {
new->security = NULL; struct tomoyo_domain_info **blob = tomoyo_cred(new);
*blob = NULL;
return 0; return 0;
} }
@ -34,8 +36,13 @@ static int tomoyo_cred_alloc_blank(struct cred *new, gfp_t gfp)
static int tomoyo_cred_prepare(struct cred *new, const struct cred *old, static int tomoyo_cred_prepare(struct cred *new, const struct cred *old,
gfp_t gfp) gfp_t gfp)
{ {
struct tomoyo_domain_info *domain = old->security; struct tomoyo_domain_info **old_blob = tomoyo_cred(old);
new->security = domain; struct tomoyo_domain_info **new_blob = tomoyo_cred(new);
struct tomoyo_domain_info *domain;
domain = *old_blob;
*new_blob = domain;
if (domain) if (domain)
atomic_inc(&domain->users); atomic_inc(&domain->users);
return 0; return 0;
@ -59,7 +66,9 @@ static void tomoyo_cred_transfer(struct cred *new, const struct cred *old)
*/ */
static void tomoyo_cred_free(struct cred *cred) static void tomoyo_cred_free(struct cred *cred)
{ {
struct tomoyo_domain_info *domain = cred->security; struct tomoyo_domain_info **blob = tomoyo_cred(cred);
struct tomoyo_domain_info *domain = *blob;
if (domain) if (domain)
atomic_dec(&domain->users); atomic_dec(&domain->users);
} }
@ -73,6 +82,9 @@ static void tomoyo_cred_free(struct cred *cred)
*/ */
static int tomoyo_bprm_set_creds(struct linux_binprm *bprm) static int tomoyo_bprm_set_creds(struct linux_binprm *bprm)
{ {
struct tomoyo_domain_info **blob;
struct tomoyo_domain_info *domain;
/* /*
* Do only if this function is called for the first time of an execve * Do only if this function is called for the first time of an execve
* operation. * operation.
@ -93,13 +105,14 @@ static int tomoyo_bprm_set_creds(struct linux_binprm *bprm)
* stored inside "bprm->cred->security" will be acquired later inside * stored inside "bprm->cred->security" will be acquired later inside
* tomoyo_find_next_domain(). * tomoyo_find_next_domain().
*/ */
atomic_dec(&((struct tomoyo_domain_info *) blob = tomoyo_cred(bprm->cred);
bprm->cred->security)->users); domain = *blob;
atomic_dec(&domain->users);
/* /*
* Tell tomoyo_bprm_check_security() is called for the first time of an * Tell tomoyo_bprm_check_security() is called for the first time of an
* execve operation. * execve operation.
*/ */
bprm->cred->security = NULL; *blob = NULL;
return 0; return 0;
} }
@ -112,8 +125,11 @@ static int tomoyo_bprm_set_creds(struct linux_binprm *bprm)
*/ */
static int tomoyo_bprm_check_security(struct linux_binprm *bprm) static int tomoyo_bprm_check_security(struct linux_binprm *bprm)
{ {
struct tomoyo_domain_info *domain = bprm->cred->security; struct tomoyo_domain_info **blob;
struct tomoyo_domain_info *domain;
blob = tomoyo_cred(bprm->cred);
domain = *blob;
/* /*
* Execute permission is checked against pathname passed to do_execve() * Execute permission is checked against pathname passed to do_execve()
* using current domain. * using current domain.
@ -531,6 +547,8 @@ static struct security_hook_list tomoyo_hooks[] __lsm_ro_after_init = {
/* Lock for GC. */ /* Lock for GC. */
DEFINE_SRCU(tomoyo_ss); DEFINE_SRCU(tomoyo_ss);
int tomoyo_enabled __lsm_ro_after_init = 1;
/** /**
* tomoyo_init - Register TOMOYO Linux as a LSM module. * tomoyo_init - Register TOMOYO Linux as a LSM module.
* *
@ -539,17 +557,21 @@ DEFINE_SRCU(tomoyo_ss);
static int __init tomoyo_init(void) static int __init tomoyo_init(void)
{ {
struct cred *cred = (struct cred *) current_cred(); struct cred *cred = (struct cred *) current_cred();
struct tomoyo_domain_info **blob;
/* register ourselves with the security framework */ /* register ourselves with the security framework */
security_add_hooks(tomoyo_hooks, ARRAY_SIZE(tomoyo_hooks), "tomoyo"); security_add_hooks(tomoyo_hooks, ARRAY_SIZE(tomoyo_hooks), "tomoyo");
printk(KERN_INFO "TOMOYO Linux initialized\n"); printk(KERN_INFO "TOMOYO Linux initialized\n");
cred->security = &tomoyo_kernel_domain; blob = tomoyo_cred(cred);
*blob = &tomoyo_kernel_domain;
tomoyo_mm_init(); tomoyo_mm_init();
return 0; return 0;
} }
DEFINE_LSM(tomoyo) = { DEFINE_LSM(tomoyo) = {
.name = "tomoyo", .name = "tomoyo",
.enabled = &tomoyo_enabled,
.flags = LSM_FLAG_LEGACY_MAJOR | LSM_FLAG_EXCLUSIVE, .flags = LSM_FLAG_LEGACY_MAJOR | LSM_FLAG_EXCLUSIVE,
.init = tomoyo_init, .init = tomoyo_init,
}; };