Loading security/apparmor/context.c +51 −49 Original line number Diff line number Diff line Loading @@ -13,11 +13,11 @@ * License. * * * AppArmor sets confinement on every task, via the the aa_task_cxt and * the aa_task_cxt.profile, both of which are required and are not allowed * to be NULL. The aa_task_cxt is not reference counted and is unique * AppArmor sets confinement on every task, via the the aa_task_ctx and * the aa_task_ctx.profile, both of which are required and are not allowed * to be NULL. The aa_task_ctx is not reference counted and is unique * to each cred (which is reference count). The profile pointed to by * the task_cxt is reference counted. * the task_ctx is reference counted. * * TODO * If a task uses change_hat it currently does not return to the old Loading @@ -30,28 +30,28 @@ #include "include/policy.h" /** * aa_alloc_task_context - allocate a new task_cxt * aa_alloc_task_context - allocate a new task_ctx * @flags: gfp flags for allocation * * Returns: allocated buffer or NULL on failure */ struct aa_task_cxt *aa_alloc_task_context(gfp_t flags) struct aa_task_ctx *aa_alloc_task_context(gfp_t flags) { return kzalloc(sizeof(struct aa_task_cxt), flags); return kzalloc(sizeof(struct aa_task_ctx), flags); } /** * aa_free_task_context - free a task_cxt * @cxt: task_cxt to free (MAYBE NULL) * aa_free_task_context - free a task_ctx * @ctx: task_ctx to free (MAYBE NULL) */ void aa_free_task_context(struct aa_task_cxt *cxt) void aa_free_task_context(struct aa_task_ctx *ctx) { if (cxt) { aa_put_profile(cxt->profile); aa_put_profile(cxt->previous); aa_put_profile(cxt->onexec); if (ctx) { aa_put_profile(ctx->profile); aa_put_profile(ctx->previous); aa_put_profile(ctx->onexec); kzfree(cxt); kzfree(ctx); } } Loading @@ -60,7 +60,7 @@ void aa_free_task_context(struct aa_task_cxt *cxt) * @new: a blank task context (NOT NULL) * @old: the task context to copy (NOT NULL) */ void aa_dup_task_context(struct aa_task_cxt *new, const struct aa_task_cxt *old) void aa_dup_task_context(struct aa_task_ctx *new, const struct aa_task_ctx *old) { *new = *old; aa_get_profile(new->profile); Loading Loading @@ -93,11 +93,11 @@ struct aa_profile *aa_get_task_profile(struct task_struct *task) */ int aa_replace_current_profile(struct aa_profile *profile) { struct aa_task_cxt *cxt = current_cxt(); struct aa_task_ctx *ctx = current_ctx(); struct cred *new; BUG_ON(!profile); if (cxt->profile == profile) if (ctx->profile == profile) return 0; if (current_cred() != current_real_cred()) Loading @@ -107,20 +107,22 @@ int aa_replace_current_profile(struct aa_profile *profile) if (!new) return -ENOMEM; cxt = cred_cxt(new); if (unconfined(profile) || (cxt->profile->ns != profile->ns)) ctx = cred_ctx(new); if (unconfined(profile) || (ctx->profile->ns != profile->ns)) /* if switching to unconfined or a different profile namespace * clear out context state */ aa_clear_task_cxt_trans(cxt); aa_clear_task_ctx_trans(ctx); /* be careful switching cxt->profile, when racing replacement it * is possible that cxt->profile->proxy->profile is the reference /* * be careful switching ctx->profile, when racing replacement it * is possible that ctx->profile->proxy->profile is the reference * keeping @profile valid, so make sure to get its reference before * dropping the reference on cxt->profile */ * dropping the reference on ctx->profile */ aa_get_profile(profile); aa_put_profile(cxt->profile); cxt->profile = profile; aa_put_profile(ctx->profile); ctx->profile = profile; commit_creds(new); return 0; Loading @@ -134,15 +136,15 @@ int aa_replace_current_profile(struct aa_profile *profile) */ int aa_set_current_onexec(struct aa_profile *profile) { struct aa_task_cxt *cxt; struct aa_task_ctx *ctx; struct cred *new = prepare_creds(); if (!new) return -ENOMEM; cxt = cred_cxt(new); ctx = cred_ctx(new); aa_get_profile(profile); aa_put_profile(cxt->onexec); cxt->onexec = profile; aa_put_profile(ctx->onexec); ctx->onexec = profile; commit_creds(new); return 0; Loading @@ -160,28 +162,28 @@ int aa_set_current_onexec(struct aa_profile *profile) */ int aa_set_current_hat(struct aa_profile *profile, u64 token) { struct aa_task_cxt *cxt; struct aa_task_ctx *ctx; struct cred *new = prepare_creds(); if (!new) return -ENOMEM; BUG_ON(!profile); cxt = cred_cxt(new); if (!cxt->previous) { ctx = cred_ctx(new); if (!ctx->previous) { /* transfer refcount */ cxt->previous = cxt->profile; cxt->token = token; } else if (cxt->token == token) { aa_put_profile(cxt->profile); ctx->previous = ctx->profile; ctx->token = token; } else if (ctx->token == token) { aa_put_profile(ctx->profile); } else { /* previous_profile && cxt->token != token */ /* previous_profile && ctx->token != token */ abort_creds(new); return -EACCES; } cxt->profile = aa_get_newest_profile(profile); ctx->profile = aa_get_newest_profile(profile); /* clear exec on switching context */ aa_put_profile(cxt->onexec); cxt->onexec = NULL; aa_put_profile(ctx->onexec); ctx->onexec = NULL; commit_creds(new); return 0; Loading @@ -198,27 +200,27 @@ int aa_set_current_hat(struct aa_profile *profile, u64 token) */ int aa_restore_previous_profile(u64 token) { struct aa_task_cxt *cxt; struct aa_task_ctx *ctx; struct cred *new = prepare_creds(); if (!new) return -ENOMEM; cxt = cred_cxt(new); if (cxt->token != token) { ctx = cred_ctx(new); if (ctx->token != token) { abort_creds(new); return -EACCES; } /* ignore restores when there is no saved profile */ if (!cxt->previous) { if (!ctx->previous) { abort_creds(new); return 0; } aa_put_profile(cxt->profile); cxt->profile = aa_get_newest_profile(cxt->previous); BUG_ON(!cxt->profile); aa_put_profile(ctx->profile); ctx->profile = aa_get_newest_profile(ctx->previous); AA_BUG(!ctx->profile); /* clear exec && prev information when restoring to previous context */ aa_clear_task_cxt_trans(cxt); aa_clear_task_ctx_trans(ctx); commit_creds(new); return 0; Loading security/apparmor/domain.c +21 −21 Original line number Diff line number Diff line Loading @@ -337,7 +337,7 @@ static struct aa_profile *x_to_profile(struct aa_profile *profile, */ int apparmor_bprm_set_creds(struct linux_binprm *bprm) { struct aa_task_cxt *cxt; struct aa_task_ctx *ctx; struct aa_profile *profile, *new_profile = NULL; struct aa_ns *ns; char *buffer = NULL; Loading @@ -353,10 +353,10 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm) if (bprm->cred_prepared) return 0; cxt = cred_cxt(bprm->cred); BUG_ON(!cxt); ctx = cred_ctx(bprm->cred); AA_BUG(!ctx); profile = aa_get_newest_profile(cxt->profile); profile = aa_get_newest_profile(ctx->profile); /* * get the namespace from the replacement profile as replacement * can change the namespace Loading @@ -380,9 +380,9 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm) */ if (unconfined(profile)) { /* unconfined task */ if (cxt->onexec) if (ctx->onexec) /* change_profile on exec already been granted */ new_profile = aa_get_profile(cxt->onexec); new_profile = aa_get_profile(ctx->onexec); else new_profile = find_attach(ns, &ns->base.profiles, name); if (!new_profile) Loading @@ -397,10 +397,10 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm) /* find exec permissions for name */ state = aa_str_perms(profile->file.dfa, state, name, &cond, &perms); if (cxt->onexec) { if (ctx->onexec) { struct file_perms cp; info = "change_profile onexec"; new_profile = aa_get_newest_profile(cxt->onexec); new_profile = aa_get_newest_profile(ctx->onexec); if (!(perms.allow & AA_MAY_ONEXEC)) goto audit; Loading @@ -409,8 +409,8 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm) * exec\0change_profile */ state = aa_dfa_null_transition(profile->file.dfa, state); cp = change_profile_perms(profile, cxt->onexec->ns, cxt->onexec->base.name, cp = change_profile_perms(profile, ctx->onexec->ns, ctx->onexec->base.name, AA_MAY_ONEXEC, state); if (!(cp.allow & AA_MAY_ONEXEC)) Loading Loading @@ -499,13 +499,13 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm) bprm->per_clear |= PER_CLEAR_ON_SETID; x_clear: aa_put_profile(cxt->profile); /* transfer new profile reference will be released when cxt is freed */ cxt->profile = new_profile; aa_put_profile(ctx->profile); /* transfer new profile reference will be released when ctx is freed */ ctx->profile = new_profile; new_profile = NULL; /* clear out all temporary/transitional state from the context */ aa_clear_task_cxt_trans(cxt); aa_clear_task_ctx_trans(ctx); audit: error = aa_audit_file(profile, &perms, GFP_KERNEL, OP_EXEC, MAY_EXEC, Loading Loading @@ -545,17 +545,17 @@ int apparmor_bprm_secureexec(struct linux_binprm *bprm) void apparmor_bprm_committing_creds(struct linux_binprm *bprm) { struct aa_profile *profile = __aa_current_profile(); struct aa_task_cxt *new_cxt = cred_cxt(bprm->cred); struct aa_task_ctx *new_ctx = cred_ctx(bprm->cred); /* bail out if unconfined or not changing profile */ if ((new_cxt->profile == profile) || (unconfined(new_cxt->profile))) if ((new_ctx->profile == profile) || (unconfined(new_ctx->profile))) return; current->pdeath_signal = 0; /* reset soft limits and set hard limits for the new profile */ __aa_transition_rlimits(profile, new_cxt->profile); __aa_transition_rlimits(profile, new_ctx->profile); } /** Loading Loading @@ -604,7 +604,7 @@ static char *new_compound_name(const char *n1, const char *n2) int aa_change_hat(const char *hats[], int count, u64 token, bool permtest) { const struct cred *cred; struct aa_task_cxt *cxt; struct aa_task_ctx *ctx; struct aa_profile *profile, *previous_profile, *hat = NULL; char *name = NULL; int i; Loading @@ -622,9 +622,9 @@ int aa_change_hat(const char *hats[], int count, u64 token, bool permtest) /* released below */ cred = get_current_cred(); cxt = cred_cxt(cred); ctx = cred_ctx(cred); profile = aa_get_newest_profile(aa_cred_profile(cred)); previous_profile = aa_get_newest_profile(cxt->previous); previous_profile = aa_get_newest_profile(ctx->previous); if (unconfined(profile)) { info = "unconfined"; Loading security/apparmor/include/context.h +40 −38 Original line number Diff line number Diff line Loading @@ -22,43 +22,43 @@ #include "policy.h" #include "policy_ns.h" #define cred_cxt(X) (X)->security #define current_cxt() cred_cxt(current_cred()) #define cred_ctx(X) ((X)->security) #define current_ctx() cred_ctx(current_cred()) /* struct aa_file_cxt - the AppArmor context the file was opened in /* struct aa_file_ctx - the AppArmor context the file was opened in * @perms: the permission the file was opened with * * The file_cxt could currently be directly stored in file->f_security * The file_ctx could currently be directly stored in file->f_security * as the profile reference is now stored in the f_cred. However the * cxt struct will expand in the future so we keep the struct. * ctx struct will expand in the future so we keep the struct. */ struct aa_file_cxt { struct aa_file_ctx { u16 allow; }; /** * aa_alloc_file_context - allocate file_cxt * aa_alloc_file_context - allocate file_ctx * @gfp: gfp flags for allocation * * Returns: file_cxt or NULL on failure * Returns: file_ctx or NULL on failure */ static inline struct aa_file_cxt *aa_alloc_file_context(gfp_t gfp) static inline struct aa_file_ctx *aa_alloc_file_context(gfp_t gfp) { return kzalloc(sizeof(struct aa_file_cxt), gfp); return kzalloc(sizeof(struct aa_file_ctx), gfp); } /** * aa_free_file_context - free a file_cxt * @cxt: file_cxt to free (MAYBE_NULL) * aa_free_file_context - free a file_ctx * @ctx: file_ctx to free (MAYBE_NULL) */ static inline void aa_free_file_context(struct aa_file_cxt *cxt) static inline void aa_free_file_context(struct aa_file_ctx *ctx) { if (cxt) kzfree(cxt); if (ctx) kzfree(ctx); } /** * struct aa_task_cxt - primary label for confined tasks * struct aa_task_ctx - primary label for confined tasks * @profile: the current profile (NOT NULL) * @exec: profile to transition to on next exec (MAYBE NULL) * @previous: profile the task may return to (MAYBE NULL) Loading @@ -69,17 +69,17 @@ static inline void aa_free_file_context(struct aa_file_cxt *cxt) * * TODO: make so a task can be confined by a stack of contexts */ struct aa_task_cxt { struct aa_task_ctx { struct aa_profile *profile; struct aa_profile *onexec; struct aa_profile *previous; u64 token; }; struct aa_task_cxt *aa_alloc_task_context(gfp_t flags); void aa_free_task_context(struct aa_task_cxt *cxt); void aa_dup_task_context(struct aa_task_cxt *new, const struct aa_task_cxt *old); struct aa_task_ctx *aa_alloc_task_context(gfp_t flags); void aa_free_task_context(struct aa_task_ctx *ctx); void aa_dup_task_context(struct aa_task_ctx *new, const struct aa_task_ctx *old); int aa_replace_current_profile(struct aa_profile *profile); int aa_set_current_onexec(struct aa_profile *profile); int aa_set_current_hat(struct aa_profile *profile, u64 token); Loading @@ -97,9 +97,10 @@ struct aa_profile *aa_get_task_profile(struct task_struct *task); */ static inline struct aa_profile *aa_cred_profile(const struct cred *cred) { struct aa_task_cxt *cxt = cred_cxt(cred); BUG_ON(!cxt || !cxt->profile); return cxt->profile; struct aa_task_ctx *ctx = cred_ctx(cred); AA_BUG(!ctx || !ctx->profile); return ctx->profile; } /** Loading Loading @@ -149,18 +150,19 @@ static inline struct aa_profile *__aa_current_profile(void) */ static inline struct aa_profile *aa_current_profile(void) { const struct aa_task_cxt *cxt = current_cxt(); const struct aa_task_ctx *ctx = current_ctx(); struct aa_profile *profile; BUG_ON(!cxt || !cxt->profile); if (profile_is_stale(cxt->profile)) { profile = aa_get_newest_profile(cxt->profile); AA_BUG(!ctx || !ctx->profile); if (profile_is_stale(ctx->profile)) { profile = aa_get_newest_profile(ctx->profile); aa_replace_current_profile(profile); aa_put_profile(profile); cxt = current_cxt(); ctx = current_ctx(); } return cxt->profile; return ctx->profile; } static inline struct aa_ns *aa_get_current_ns(void) Loading @@ -169,16 +171,16 @@ static inline struct aa_ns *aa_get_current_ns(void) } /** * aa_clear_task_cxt_trans - clear transition tracking info from the cxt * @cxt: task context to clear (NOT NULL) * aa_clear_task_ctx_trans - clear transition tracking info from the ctx * @ctx: task context to clear (NOT NULL) */ static inline void aa_clear_task_cxt_trans(struct aa_task_cxt *cxt) static inline void aa_clear_task_ctx_trans(struct aa_task_ctx *ctx) { aa_put_profile(cxt->previous); aa_put_profile(cxt->onexec); cxt->previous = NULL; cxt->onexec = NULL; cxt->token = 0; aa_put_profile(ctx->previous); aa_put_profile(ctx->onexec); ctx->previous = NULL; ctx->onexec = NULL; ctx->token = 0; } #endif /* __AA_CONTEXT_H */ security/apparmor/lsm.c +37 −35 Original line number Diff line number Diff line Loading @@ -45,12 +45,12 @@ int apparmor_initialized __initdata; */ /* * free the associated aa_task_cxt and put its profiles * free the associated aa_task_ctx and put its profiles */ static void apparmor_cred_free(struct cred *cred) { aa_free_task_context(cred_cxt(cred)); cred_cxt(cred) = NULL; aa_free_task_context(cred_ctx(cred)); cred_ctx(cred) = NULL; } /* Loading @@ -59,27 +59,29 @@ static void apparmor_cred_free(struct cred *cred) static int apparmor_cred_alloc_blank(struct cred *cred, gfp_t gfp) { /* freed by apparmor_cred_free */ struct aa_task_cxt *cxt = aa_alloc_task_context(gfp); if (!cxt) struct aa_task_ctx *ctx = aa_alloc_task_context(gfp); if (!ctx) return -ENOMEM; cred_cxt(cred) = cxt; cred_ctx(cred) = ctx; return 0; } /* * prepare new aa_task_cxt for modification by prepare_cred block * prepare new aa_task_ctx for modification by prepare_cred block */ static int apparmor_cred_prepare(struct cred *new, const struct cred *old, gfp_t gfp) { /* freed by apparmor_cred_free */ struct aa_task_cxt *cxt = aa_alloc_task_context(gfp); if (!cxt) struct aa_task_ctx *ctx = aa_alloc_task_context(gfp); if (!ctx) return -ENOMEM; aa_dup_task_context(cxt, cred_cxt(old)); cred_cxt(new) = cxt; aa_dup_task_context(ctx, cred_ctx(old)); cred_ctx(new) = ctx; return 0; } Loading @@ -88,10 +90,10 @@ static int apparmor_cred_prepare(struct cred *new, const struct cred *old, */ static void apparmor_cred_transfer(struct cred *new, const struct cred *old) { const struct aa_task_cxt *old_cxt = cred_cxt(old); struct aa_task_cxt *new_cxt = cred_cxt(new); const struct aa_task_ctx *old_ctx = cred_ctx(old); struct aa_task_ctx *new_ctx = cred_ctx(new); aa_dup_task_context(new_cxt, old_cxt); aa_dup_task_context(new_ctx, old_ctx); } static int apparmor_ptrace_access_check(struct task_struct *child, Loading Loading @@ -345,7 +347,7 @@ static int apparmor_inode_getattr(const struct path *path) static int apparmor_file_open(struct file *file, const struct cred *cred) { struct aa_file_cxt *fcxt = file->f_security; struct aa_file_ctx *fctx = file->f_security; struct aa_profile *profile; int error = 0; Loading @@ -358,7 +360,7 @@ static int apparmor_file_open(struct file *file, const struct cred *cred) * actually execute the image. */ if (current->in_execve) { fcxt->allow = MAY_EXEC | MAY_READ | AA_EXEC_MMAP; fctx->allow = MAY_EXEC | MAY_READ | AA_EXEC_MMAP; return 0; } Loading @@ -370,7 +372,7 @@ static int apparmor_file_open(struct file *file, const struct cred *cred) error = aa_path_perm(OP_OPEN, profile, &file->f_path, 0, aa_map_file_to_perms(file), &cond); /* todo cache full allowed permissions set and state */ fcxt->allow = aa_map_file_to_perms(file); fctx->allow = aa_map_file_to_perms(file); } return error; Loading @@ -388,14 +390,14 @@ static int apparmor_file_alloc_security(struct file *file) static void apparmor_file_free_security(struct file *file) { struct aa_file_cxt *cxt = file->f_security; struct aa_file_ctx *ctx = file->f_security; aa_free_file_context(cxt); aa_free_file_context(ctx); } static int common_file_perm(int op, struct file *file, u32 mask) { struct aa_file_cxt *fcxt = file->f_security; struct aa_file_ctx *fctx = file->f_security; struct aa_profile *profile, *fprofile = aa_cred_profile(file->f_cred); int error = 0; Loading @@ -415,7 +417,7 @@ static int common_file_perm(int op, struct file *file, u32 mask) * delegation from unconfined tasks */ if (!unconfined(profile) && !unconfined(fprofile) && ((fprofile != profile) || (mask & ~fcxt->allow))) ((fprofile != profile) || (mask & ~fctx->allow))) error = aa_file_perm(op, profile, file, mask); return error; Loading Loading @@ -477,15 +479,15 @@ static int apparmor_getprocattr(struct task_struct *task, char *name, int error = -ENOENT; /* released below */ const struct cred *cred = get_task_cred(task); struct aa_task_cxt *cxt = cred_cxt(cred); struct aa_task_ctx *ctx = cred_ctx(cred); struct aa_profile *profile = NULL; if (strcmp(name, "current") == 0) profile = aa_get_newest_profile(cxt->profile); else if (strcmp(name, "prev") == 0 && cxt->previous) profile = aa_get_newest_profile(cxt->previous); else if (strcmp(name, "exec") == 0 && cxt->onexec) profile = aa_get_newest_profile(cxt->onexec); profile = aa_get_newest_profile(ctx->profile); else if (strcmp(name, "prev") == 0 && ctx->previous) profile = aa_get_newest_profile(ctx->previous); else if (strcmp(name, "exec") == 0 && ctx->onexec) profile = aa_get_newest_profile(ctx->onexec); else error = -EINVAL; Loading Loading @@ -849,21 +851,21 @@ static int param_set_mode(const char *val, struct kernel_param *kp) */ /** * set_init_cxt - set a task context and profile on the first task. * set_init_ctx - set a task context and profile on the first task. * * TODO: allow setting an alternate profile than unconfined */ static int __init set_init_cxt(void) static int __init set_init_ctx(void) { struct cred *cred = (struct cred *)current->real_cred; struct aa_task_cxt *cxt; struct aa_task_ctx *ctx; cxt = aa_alloc_task_context(GFP_KERNEL); if (!cxt) ctx = aa_alloc_task_context(GFP_KERNEL); if (!ctx) return -ENOMEM; cxt->profile = aa_get_profile(root_ns->unconfined); cred_cxt(cred) = cxt; ctx->profile = aa_get_profile(root_ns->unconfined); cred_ctx(cred) = ctx; return 0; } Loading @@ -890,7 +892,7 @@ static int __init apparmor_init(void) goto alloc_out; } error = set_init_cxt(); error = set_init_ctx(); if (error) { AA_ERROR("Failed to set context on init task\n"); aa_free_root_ns(); Loading security/apparmor/policy.c +1 −1 Original line number Diff line number Diff line Loading @@ -808,7 +808,7 @@ static int __lookup_replace(struct aa_ns *ns, const char *hname, * @udata: serialized data stream (NOT NULL) * * unpack and replace a profile on the profile list and uses of that profile * by any aa_task_cxt. If the profile does not exist on the profile list * by any aa_task_ctx. If the profile does not exist on the profile list * it is added. * * Returns: size of data consumed else error code on failure. Loading Loading
security/apparmor/context.c +51 −49 Original line number Diff line number Diff line Loading @@ -13,11 +13,11 @@ * License. * * * AppArmor sets confinement on every task, via the the aa_task_cxt and * the aa_task_cxt.profile, both of which are required and are not allowed * to be NULL. The aa_task_cxt is not reference counted and is unique * AppArmor sets confinement on every task, via the the aa_task_ctx and * the aa_task_ctx.profile, both of which are required and are not allowed * to be NULL. The aa_task_ctx is not reference counted and is unique * to each cred (which is reference count). The profile pointed to by * the task_cxt is reference counted. * the task_ctx is reference counted. * * TODO * If a task uses change_hat it currently does not return to the old Loading @@ -30,28 +30,28 @@ #include "include/policy.h" /** * aa_alloc_task_context - allocate a new task_cxt * aa_alloc_task_context - allocate a new task_ctx * @flags: gfp flags for allocation * * Returns: allocated buffer or NULL on failure */ struct aa_task_cxt *aa_alloc_task_context(gfp_t flags) struct aa_task_ctx *aa_alloc_task_context(gfp_t flags) { return kzalloc(sizeof(struct aa_task_cxt), flags); return kzalloc(sizeof(struct aa_task_ctx), flags); } /** * aa_free_task_context - free a task_cxt * @cxt: task_cxt to free (MAYBE NULL) * aa_free_task_context - free a task_ctx * @ctx: task_ctx to free (MAYBE NULL) */ void aa_free_task_context(struct aa_task_cxt *cxt) void aa_free_task_context(struct aa_task_ctx *ctx) { if (cxt) { aa_put_profile(cxt->profile); aa_put_profile(cxt->previous); aa_put_profile(cxt->onexec); if (ctx) { aa_put_profile(ctx->profile); aa_put_profile(ctx->previous); aa_put_profile(ctx->onexec); kzfree(cxt); kzfree(ctx); } } Loading @@ -60,7 +60,7 @@ void aa_free_task_context(struct aa_task_cxt *cxt) * @new: a blank task context (NOT NULL) * @old: the task context to copy (NOT NULL) */ void aa_dup_task_context(struct aa_task_cxt *new, const struct aa_task_cxt *old) void aa_dup_task_context(struct aa_task_ctx *new, const struct aa_task_ctx *old) { *new = *old; aa_get_profile(new->profile); Loading Loading @@ -93,11 +93,11 @@ struct aa_profile *aa_get_task_profile(struct task_struct *task) */ int aa_replace_current_profile(struct aa_profile *profile) { struct aa_task_cxt *cxt = current_cxt(); struct aa_task_ctx *ctx = current_ctx(); struct cred *new; BUG_ON(!profile); if (cxt->profile == profile) if (ctx->profile == profile) return 0; if (current_cred() != current_real_cred()) Loading @@ -107,20 +107,22 @@ int aa_replace_current_profile(struct aa_profile *profile) if (!new) return -ENOMEM; cxt = cred_cxt(new); if (unconfined(profile) || (cxt->profile->ns != profile->ns)) ctx = cred_ctx(new); if (unconfined(profile) || (ctx->profile->ns != profile->ns)) /* if switching to unconfined or a different profile namespace * clear out context state */ aa_clear_task_cxt_trans(cxt); aa_clear_task_ctx_trans(ctx); /* be careful switching cxt->profile, when racing replacement it * is possible that cxt->profile->proxy->profile is the reference /* * be careful switching ctx->profile, when racing replacement it * is possible that ctx->profile->proxy->profile is the reference * keeping @profile valid, so make sure to get its reference before * dropping the reference on cxt->profile */ * dropping the reference on ctx->profile */ aa_get_profile(profile); aa_put_profile(cxt->profile); cxt->profile = profile; aa_put_profile(ctx->profile); ctx->profile = profile; commit_creds(new); return 0; Loading @@ -134,15 +136,15 @@ int aa_replace_current_profile(struct aa_profile *profile) */ int aa_set_current_onexec(struct aa_profile *profile) { struct aa_task_cxt *cxt; struct aa_task_ctx *ctx; struct cred *new = prepare_creds(); if (!new) return -ENOMEM; cxt = cred_cxt(new); ctx = cred_ctx(new); aa_get_profile(profile); aa_put_profile(cxt->onexec); cxt->onexec = profile; aa_put_profile(ctx->onexec); ctx->onexec = profile; commit_creds(new); return 0; Loading @@ -160,28 +162,28 @@ int aa_set_current_onexec(struct aa_profile *profile) */ int aa_set_current_hat(struct aa_profile *profile, u64 token) { struct aa_task_cxt *cxt; struct aa_task_ctx *ctx; struct cred *new = prepare_creds(); if (!new) return -ENOMEM; BUG_ON(!profile); cxt = cred_cxt(new); if (!cxt->previous) { ctx = cred_ctx(new); if (!ctx->previous) { /* transfer refcount */ cxt->previous = cxt->profile; cxt->token = token; } else if (cxt->token == token) { aa_put_profile(cxt->profile); ctx->previous = ctx->profile; ctx->token = token; } else if (ctx->token == token) { aa_put_profile(ctx->profile); } else { /* previous_profile && cxt->token != token */ /* previous_profile && ctx->token != token */ abort_creds(new); return -EACCES; } cxt->profile = aa_get_newest_profile(profile); ctx->profile = aa_get_newest_profile(profile); /* clear exec on switching context */ aa_put_profile(cxt->onexec); cxt->onexec = NULL; aa_put_profile(ctx->onexec); ctx->onexec = NULL; commit_creds(new); return 0; Loading @@ -198,27 +200,27 @@ int aa_set_current_hat(struct aa_profile *profile, u64 token) */ int aa_restore_previous_profile(u64 token) { struct aa_task_cxt *cxt; struct aa_task_ctx *ctx; struct cred *new = prepare_creds(); if (!new) return -ENOMEM; cxt = cred_cxt(new); if (cxt->token != token) { ctx = cred_ctx(new); if (ctx->token != token) { abort_creds(new); return -EACCES; } /* ignore restores when there is no saved profile */ if (!cxt->previous) { if (!ctx->previous) { abort_creds(new); return 0; } aa_put_profile(cxt->profile); cxt->profile = aa_get_newest_profile(cxt->previous); BUG_ON(!cxt->profile); aa_put_profile(ctx->profile); ctx->profile = aa_get_newest_profile(ctx->previous); AA_BUG(!ctx->profile); /* clear exec && prev information when restoring to previous context */ aa_clear_task_cxt_trans(cxt); aa_clear_task_ctx_trans(ctx); commit_creds(new); return 0; Loading
security/apparmor/domain.c +21 −21 Original line number Diff line number Diff line Loading @@ -337,7 +337,7 @@ static struct aa_profile *x_to_profile(struct aa_profile *profile, */ int apparmor_bprm_set_creds(struct linux_binprm *bprm) { struct aa_task_cxt *cxt; struct aa_task_ctx *ctx; struct aa_profile *profile, *new_profile = NULL; struct aa_ns *ns; char *buffer = NULL; Loading @@ -353,10 +353,10 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm) if (bprm->cred_prepared) return 0; cxt = cred_cxt(bprm->cred); BUG_ON(!cxt); ctx = cred_ctx(bprm->cred); AA_BUG(!ctx); profile = aa_get_newest_profile(cxt->profile); profile = aa_get_newest_profile(ctx->profile); /* * get the namespace from the replacement profile as replacement * can change the namespace Loading @@ -380,9 +380,9 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm) */ if (unconfined(profile)) { /* unconfined task */ if (cxt->onexec) if (ctx->onexec) /* change_profile on exec already been granted */ new_profile = aa_get_profile(cxt->onexec); new_profile = aa_get_profile(ctx->onexec); else new_profile = find_attach(ns, &ns->base.profiles, name); if (!new_profile) Loading @@ -397,10 +397,10 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm) /* find exec permissions for name */ state = aa_str_perms(profile->file.dfa, state, name, &cond, &perms); if (cxt->onexec) { if (ctx->onexec) { struct file_perms cp; info = "change_profile onexec"; new_profile = aa_get_newest_profile(cxt->onexec); new_profile = aa_get_newest_profile(ctx->onexec); if (!(perms.allow & AA_MAY_ONEXEC)) goto audit; Loading @@ -409,8 +409,8 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm) * exec\0change_profile */ state = aa_dfa_null_transition(profile->file.dfa, state); cp = change_profile_perms(profile, cxt->onexec->ns, cxt->onexec->base.name, cp = change_profile_perms(profile, ctx->onexec->ns, ctx->onexec->base.name, AA_MAY_ONEXEC, state); if (!(cp.allow & AA_MAY_ONEXEC)) Loading Loading @@ -499,13 +499,13 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm) bprm->per_clear |= PER_CLEAR_ON_SETID; x_clear: aa_put_profile(cxt->profile); /* transfer new profile reference will be released when cxt is freed */ cxt->profile = new_profile; aa_put_profile(ctx->profile); /* transfer new profile reference will be released when ctx is freed */ ctx->profile = new_profile; new_profile = NULL; /* clear out all temporary/transitional state from the context */ aa_clear_task_cxt_trans(cxt); aa_clear_task_ctx_trans(ctx); audit: error = aa_audit_file(profile, &perms, GFP_KERNEL, OP_EXEC, MAY_EXEC, Loading Loading @@ -545,17 +545,17 @@ int apparmor_bprm_secureexec(struct linux_binprm *bprm) void apparmor_bprm_committing_creds(struct linux_binprm *bprm) { struct aa_profile *profile = __aa_current_profile(); struct aa_task_cxt *new_cxt = cred_cxt(bprm->cred); struct aa_task_ctx *new_ctx = cred_ctx(bprm->cred); /* bail out if unconfined or not changing profile */ if ((new_cxt->profile == profile) || (unconfined(new_cxt->profile))) if ((new_ctx->profile == profile) || (unconfined(new_ctx->profile))) return; current->pdeath_signal = 0; /* reset soft limits and set hard limits for the new profile */ __aa_transition_rlimits(profile, new_cxt->profile); __aa_transition_rlimits(profile, new_ctx->profile); } /** Loading Loading @@ -604,7 +604,7 @@ static char *new_compound_name(const char *n1, const char *n2) int aa_change_hat(const char *hats[], int count, u64 token, bool permtest) { const struct cred *cred; struct aa_task_cxt *cxt; struct aa_task_ctx *ctx; struct aa_profile *profile, *previous_profile, *hat = NULL; char *name = NULL; int i; Loading @@ -622,9 +622,9 @@ int aa_change_hat(const char *hats[], int count, u64 token, bool permtest) /* released below */ cred = get_current_cred(); cxt = cred_cxt(cred); ctx = cred_ctx(cred); profile = aa_get_newest_profile(aa_cred_profile(cred)); previous_profile = aa_get_newest_profile(cxt->previous); previous_profile = aa_get_newest_profile(ctx->previous); if (unconfined(profile)) { info = "unconfined"; Loading
security/apparmor/include/context.h +40 −38 Original line number Diff line number Diff line Loading @@ -22,43 +22,43 @@ #include "policy.h" #include "policy_ns.h" #define cred_cxt(X) (X)->security #define current_cxt() cred_cxt(current_cred()) #define cred_ctx(X) ((X)->security) #define current_ctx() cred_ctx(current_cred()) /* struct aa_file_cxt - the AppArmor context the file was opened in /* struct aa_file_ctx - the AppArmor context the file was opened in * @perms: the permission the file was opened with * * The file_cxt could currently be directly stored in file->f_security * The file_ctx could currently be directly stored in file->f_security * as the profile reference is now stored in the f_cred. However the * cxt struct will expand in the future so we keep the struct. * ctx struct will expand in the future so we keep the struct. */ struct aa_file_cxt { struct aa_file_ctx { u16 allow; }; /** * aa_alloc_file_context - allocate file_cxt * aa_alloc_file_context - allocate file_ctx * @gfp: gfp flags for allocation * * Returns: file_cxt or NULL on failure * Returns: file_ctx or NULL on failure */ static inline struct aa_file_cxt *aa_alloc_file_context(gfp_t gfp) static inline struct aa_file_ctx *aa_alloc_file_context(gfp_t gfp) { return kzalloc(sizeof(struct aa_file_cxt), gfp); return kzalloc(sizeof(struct aa_file_ctx), gfp); } /** * aa_free_file_context - free a file_cxt * @cxt: file_cxt to free (MAYBE_NULL) * aa_free_file_context - free a file_ctx * @ctx: file_ctx to free (MAYBE_NULL) */ static inline void aa_free_file_context(struct aa_file_cxt *cxt) static inline void aa_free_file_context(struct aa_file_ctx *ctx) { if (cxt) kzfree(cxt); if (ctx) kzfree(ctx); } /** * struct aa_task_cxt - primary label for confined tasks * struct aa_task_ctx - primary label for confined tasks * @profile: the current profile (NOT NULL) * @exec: profile to transition to on next exec (MAYBE NULL) * @previous: profile the task may return to (MAYBE NULL) Loading @@ -69,17 +69,17 @@ static inline void aa_free_file_context(struct aa_file_cxt *cxt) * * TODO: make so a task can be confined by a stack of contexts */ struct aa_task_cxt { struct aa_task_ctx { struct aa_profile *profile; struct aa_profile *onexec; struct aa_profile *previous; u64 token; }; struct aa_task_cxt *aa_alloc_task_context(gfp_t flags); void aa_free_task_context(struct aa_task_cxt *cxt); void aa_dup_task_context(struct aa_task_cxt *new, const struct aa_task_cxt *old); struct aa_task_ctx *aa_alloc_task_context(gfp_t flags); void aa_free_task_context(struct aa_task_ctx *ctx); void aa_dup_task_context(struct aa_task_ctx *new, const struct aa_task_ctx *old); int aa_replace_current_profile(struct aa_profile *profile); int aa_set_current_onexec(struct aa_profile *profile); int aa_set_current_hat(struct aa_profile *profile, u64 token); Loading @@ -97,9 +97,10 @@ struct aa_profile *aa_get_task_profile(struct task_struct *task); */ static inline struct aa_profile *aa_cred_profile(const struct cred *cred) { struct aa_task_cxt *cxt = cred_cxt(cred); BUG_ON(!cxt || !cxt->profile); return cxt->profile; struct aa_task_ctx *ctx = cred_ctx(cred); AA_BUG(!ctx || !ctx->profile); return ctx->profile; } /** Loading Loading @@ -149,18 +150,19 @@ static inline struct aa_profile *__aa_current_profile(void) */ static inline struct aa_profile *aa_current_profile(void) { const struct aa_task_cxt *cxt = current_cxt(); const struct aa_task_ctx *ctx = current_ctx(); struct aa_profile *profile; BUG_ON(!cxt || !cxt->profile); if (profile_is_stale(cxt->profile)) { profile = aa_get_newest_profile(cxt->profile); AA_BUG(!ctx || !ctx->profile); if (profile_is_stale(ctx->profile)) { profile = aa_get_newest_profile(ctx->profile); aa_replace_current_profile(profile); aa_put_profile(profile); cxt = current_cxt(); ctx = current_ctx(); } return cxt->profile; return ctx->profile; } static inline struct aa_ns *aa_get_current_ns(void) Loading @@ -169,16 +171,16 @@ static inline struct aa_ns *aa_get_current_ns(void) } /** * aa_clear_task_cxt_trans - clear transition tracking info from the cxt * @cxt: task context to clear (NOT NULL) * aa_clear_task_ctx_trans - clear transition tracking info from the ctx * @ctx: task context to clear (NOT NULL) */ static inline void aa_clear_task_cxt_trans(struct aa_task_cxt *cxt) static inline void aa_clear_task_ctx_trans(struct aa_task_ctx *ctx) { aa_put_profile(cxt->previous); aa_put_profile(cxt->onexec); cxt->previous = NULL; cxt->onexec = NULL; cxt->token = 0; aa_put_profile(ctx->previous); aa_put_profile(ctx->onexec); ctx->previous = NULL; ctx->onexec = NULL; ctx->token = 0; } #endif /* __AA_CONTEXT_H */
security/apparmor/lsm.c +37 −35 Original line number Diff line number Diff line Loading @@ -45,12 +45,12 @@ int apparmor_initialized __initdata; */ /* * free the associated aa_task_cxt and put its profiles * free the associated aa_task_ctx and put its profiles */ static void apparmor_cred_free(struct cred *cred) { aa_free_task_context(cred_cxt(cred)); cred_cxt(cred) = NULL; aa_free_task_context(cred_ctx(cred)); cred_ctx(cred) = NULL; } /* Loading @@ -59,27 +59,29 @@ static void apparmor_cred_free(struct cred *cred) static int apparmor_cred_alloc_blank(struct cred *cred, gfp_t gfp) { /* freed by apparmor_cred_free */ struct aa_task_cxt *cxt = aa_alloc_task_context(gfp); if (!cxt) struct aa_task_ctx *ctx = aa_alloc_task_context(gfp); if (!ctx) return -ENOMEM; cred_cxt(cred) = cxt; cred_ctx(cred) = ctx; return 0; } /* * prepare new aa_task_cxt for modification by prepare_cred block * prepare new aa_task_ctx for modification by prepare_cred block */ static int apparmor_cred_prepare(struct cred *new, const struct cred *old, gfp_t gfp) { /* freed by apparmor_cred_free */ struct aa_task_cxt *cxt = aa_alloc_task_context(gfp); if (!cxt) struct aa_task_ctx *ctx = aa_alloc_task_context(gfp); if (!ctx) return -ENOMEM; aa_dup_task_context(cxt, cred_cxt(old)); cred_cxt(new) = cxt; aa_dup_task_context(ctx, cred_ctx(old)); cred_ctx(new) = ctx; return 0; } Loading @@ -88,10 +90,10 @@ static int apparmor_cred_prepare(struct cred *new, const struct cred *old, */ static void apparmor_cred_transfer(struct cred *new, const struct cred *old) { const struct aa_task_cxt *old_cxt = cred_cxt(old); struct aa_task_cxt *new_cxt = cred_cxt(new); const struct aa_task_ctx *old_ctx = cred_ctx(old); struct aa_task_ctx *new_ctx = cred_ctx(new); aa_dup_task_context(new_cxt, old_cxt); aa_dup_task_context(new_ctx, old_ctx); } static int apparmor_ptrace_access_check(struct task_struct *child, Loading Loading @@ -345,7 +347,7 @@ static int apparmor_inode_getattr(const struct path *path) static int apparmor_file_open(struct file *file, const struct cred *cred) { struct aa_file_cxt *fcxt = file->f_security; struct aa_file_ctx *fctx = file->f_security; struct aa_profile *profile; int error = 0; Loading @@ -358,7 +360,7 @@ static int apparmor_file_open(struct file *file, const struct cred *cred) * actually execute the image. */ if (current->in_execve) { fcxt->allow = MAY_EXEC | MAY_READ | AA_EXEC_MMAP; fctx->allow = MAY_EXEC | MAY_READ | AA_EXEC_MMAP; return 0; } Loading @@ -370,7 +372,7 @@ static int apparmor_file_open(struct file *file, const struct cred *cred) error = aa_path_perm(OP_OPEN, profile, &file->f_path, 0, aa_map_file_to_perms(file), &cond); /* todo cache full allowed permissions set and state */ fcxt->allow = aa_map_file_to_perms(file); fctx->allow = aa_map_file_to_perms(file); } return error; Loading @@ -388,14 +390,14 @@ static int apparmor_file_alloc_security(struct file *file) static void apparmor_file_free_security(struct file *file) { struct aa_file_cxt *cxt = file->f_security; struct aa_file_ctx *ctx = file->f_security; aa_free_file_context(cxt); aa_free_file_context(ctx); } static int common_file_perm(int op, struct file *file, u32 mask) { struct aa_file_cxt *fcxt = file->f_security; struct aa_file_ctx *fctx = file->f_security; struct aa_profile *profile, *fprofile = aa_cred_profile(file->f_cred); int error = 0; Loading @@ -415,7 +417,7 @@ static int common_file_perm(int op, struct file *file, u32 mask) * delegation from unconfined tasks */ if (!unconfined(profile) && !unconfined(fprofile) && ((fprofile != profile) || (mask & ~fcxt->allow))) ((fprofile != profile) || (mask & ~fctx->allow))) error = aa_file_perm(op, profile, file, mask); return error; Loading Loading @@ -477,15 +479,15 @@ static int apparmor_getprocattr(struct task_struct *task, char *name, int error = -ENOENT; /* released below */ const struct cred *cred = get_task_cred(task); struct aa_task_cxt *cxt = cred_cxt(cred); struct aa_task_ctx *ctx = cred_ctx(cred); struct aa_profile *profile = NULL; if (strcmp(name, "current") == 0) profile = aa_get_newest_profile(cxt->profile); else if (strcmp(name, "prev") == 0 && cxt->previous) profile = aa_get_newest_profile(cxt->previous); else if (strcmp(name, "exec") == 0 && cxt->onexec) profile = aa_get_newest_profile(cxt->onexec); profile = aa_get_newest_profile(ctx->profile); else if (strcmp(name, "prev") == 0 && ctx->previous) profile = aa_get_newest_profile(ctx->previous); else if (strcmp(name, "exec") == 0 && ctx->onexec) profile = aa_get_newest_profile(ctx->onexec); else error = -EINVAL; Loading Loading @@ -849,21 +851,21 @@ static int param_set_mode(const char *val, struct kernel_param *kp) */ /** * set_init_cxt - set a task context and profile on the first task. * set_init_ctx - set a task context and profile on the first task. * * TODO: allow setting an alternate profile than unconfined */ static int __init set_init_cxt(void) static int __init set_init_ctx(void) { struct cred *cred = (struct cred *)current->real_cred; struct aa_task_cxt *cxt; struct aa_task_ctx *ctx; cxt = aa_alloc_task_context(GFP_KERNEL); if (!cxt) ctx = aa_alloc_task_context(GFP_KERNEL); if (!ctx) return -ENOMEM; cxt->profile = aa_get_profile(root_ns->unconfined); cred_cxt(cred) = cxt; ctx->profile = aa_get_profile(root_ns->unconfined); cred_ctx(cred) = ctx; return 0; } Loading @@ -890,7 +892,7 @@ static int __init apparmor_init(void) goto alloc_out; } error = set_init_cxt(); error = set_init_ctx(); if (error) { AA_ERROR("Failed to set context on init task\n"); aa_free_root_ns(); Loading
security/apparmor/policy.c +1 −1 Original line number Diff line number Diff line Loading @@ -808,7 +808,7 @@ static int __lookup_replace(struct aa_ns *ns, const char *hname, * @udata: serialized data stream (NOT NULL) * * unpack and replace a profile on the profile list and uses of that profile * by any aa_task_cxt. If the profile does not exist on the profile list * by any aa_task_ctx. If the profile does not exist on the profile list * it is added. * * Returns: size of data consumed else error code on failure. Loading