Baby step to using labels instead of profiles. Switch from using profile refs to label refs. Note this step does not make any functional changes
Signed-off-by: John Johansen <[email protected]> --- security/apparmor/apparmorfs.c | 2 +- security/apparmor/audit.c | 2 +- security/apparmor/context.c | 88 ++++++++++++++++----------------- security/apparmor/domain.c | 79 ++++++++++++++++-------------- security/apparmor/include/context.h | 87 ++++++++++++++++----------------- security/apparmor/include/ipc.h | 4 +- security/apparmor/include/label.h | 1 + security/apparmor/include/policy.h | 5 +- security/apparmor/include/procattr.h | 2 +- security/apparmor/include/resource.h | 4 +- security/apparmor/ipc.c | 23 ++++----- security/apparmor/lsm.c | 94 ++++++++++++++++++------------------ security/apparmor/policy.c | 16 +++--- security/apparmor/policy_unpack.c | 2 +- security/apparmor/procattr.c | 16 +++--- security/apparmor/resource.c | 28 ++++++----- 16 files changed, 232 insertions(+), 221 deletions(-) diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c index 3b861e4..d97c1bd 100644 --- a/security/apparmor/apparmorfs.c +++ b/security/apparmor/apparmorfs.c @@ -641,7 +641,7 @@ static void *p_start(struct seq_file *f, loff_t *pos) __acquires(&root->lock) { struct aa_profile *profile = NULL; - struct aa_namespace *root = aa_current_profile()->ns; + struct aa_namespace *root = labels_ns(aa_current_label()); loff_t l = *pos; f->private = aa_get_namespace(root); diff --git a/security/apparmor/audit.c b/security/apparmor/audit.c index 031d2d9..7ffb818 100644 --- a/security/apparmor/audit.c +++ b/security/apparmor/audit.c @@ -205,7 +205,7 @@ int aa_audit(int type, struct aa_profile *profile, gfp_t gfp, if (KILL_MODE(profile) && type == AUDIT_APPARMOR_DENIED) type = AUDIT_APPARMOR_KILL; - if (!unconfined(profile)) + if (!profile_unconfined(profile)) sa->aad->profile = profile; aa_audit_msg(type, sa, cb); diff --git a/security/apparmor/context.c b/security/apparmor/context.c index 355c4ed..9a9a0d8 100644 --- a/security/apparmor/context.c +++ b/security/apparmor/context.c @@ -14,9 +14,9 @@ * * * 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 + * the aa_task_cxt.label, both of which are required and are not allowed * to be NULL. The aa_task_cxt is not reference counted and is unique - * to each cred (which is reference count). The profile pointed to by + * to each cred (which is reference count). The label pointed to by * the task_cxt is reference counted. * * TODO @@ -47,9 +47,9 @@ struct aa_task_cxt *aa_alloc_task_context(gfp_t flags) void aa_free_task_context(struct aa_task_cxt *cxt) { if (cxt) { - aa_put_profile(cxt->profile); - aa_put_profile(cxt->previous); - aa_put_profile(cxt->onexec); + aa_put_label(cxt->label); + aa_put_label(cxt->previous); + aa_put_label(cxt->onexec); kzfree(cxt); } @@ -63,41 +63,41 @@ 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) { *new = *old; - aa_get_profile(new->profile); - aa_get_profile(new->previous); - aa_get_profile(new->onexec); + aa_get_label(new->label); + aa_get_label(new->previous); + aa_get_label(new->onexec); } /** - * aa_get_task_profile - Get another task's profile + * aa_get_task_label - Get another task's label * @task: task to query (NOT NULL) * - * Returns: counted reference to @task's profile + * Returns: counted reference to @task's label */ -struct aa_profile *aa_get_task_profile(struct task_struct *task) +struct aa_label *aa_get_task_label(struct task_struct *task) { - struct aa_profile *p; + struct aa_label *p; rcu_read_lock(); - p = aa_get_profile(__aa_task_profile(task)); + p = aa_get_label(__aa_task_label(task)); rcu_read_unlock(); return p; } /** - * aa_replace_current_profile - replace the current tasks profiles - * @profile: new profile (NOT NULL) + * aa_replace_current_label - replace the current tasks label + * @label: new label (NOT NULL) * * Returns: 0 or error on failure */ -int aa_replace_current_profile(struct aa_profile *profile) +int aa_replace_current_label(struct aa_label *label) { struct aa_task_cxt *cxt = current_cxt(); struct cred *new; - BUG_ON(!profile); + BUG_ON(!label); - if (cxt->profile == profile) + if (cxt->label == label) return 0; new = prepare_creds(); @@ -105,19 +105,15 @@ int aa_replace_current_profile(struct aa_profile *profile) return -ENOMEM; cxt = cred_cxt(new); - if (unconfined(profile) || (cxt->profile->ns != profile->ns)) - /* if switching to unconfined or a different profile namespace + if (unconfined(label) || (labels_ns(cxt->label) != labels_ns(label))) + /* if switching to unconfined or a different label namespace * clear out context state */ aa_clear_task_cxt_trans(cxt); - /* be careful switching cxt->profile, when racing replacement it - * is possible that cxt->profile->replacedby->profile is the reference - * keeping @profile valid, so make sure to get its reference before - * dropping the reference on cxt->profile */ - aa_get_profile(profile); - aa_put_profile(cxt->profile); - cxt->profile = profile; + aa_get_label(label); + aa_put_label(cxt->label); + cxt->label = label; commit_creds(new); return 0; @@ -125,11 +121,11 @@ int aa_replace_current_profile(struct aa_profile *profile) /** * aa_set_current_onexec - set the tasks change_profile to happen onexec - * @profile: system profile to set at exec (MAYBE NULL to clear value) + * @label: system label to set at exec (MAYBE NULL to clear value) * * Returns: 0 or error on failure */ -int aa_set_current_onexec(struct aa_profile *profile) +int aa_set_current_onexec(struct aa_label *label) { struct aa_task_cxt *cxt; struct cred *new = prepare_creds(); @@ -137,9 +133,9 @@ int aa_set_current_onexec(struct aa_profile *profile) return -ENOMEM; cxt = cred_cxt(new); - aa_get_profile(profile); - aa_put_profile(cxt->onexec); - cxt->onexec = profile; + aa_get_label(label); + aa_put_label(cxt->onexec); + cxt->onexec = label; commit_creds(new); return 0; @@ -147,7 +143,7 @@ int aa_set_current_onexec(struct aa_profile *profile) /** * aa_set_current_hat - set the current tasks hat - * @profile: profile to set as the current hat (NOT NULL) + * @label: label to set as the current hat (NOT NULL) * @token: token value that must be specified to change from the hat * * Do switch of tasks hat. If the task is currently in a hat @@ -155,29 +151,29 @@ int aa_set_current_onexec(struct aa_profile *profile) * * Returns: 0 or error on failure */ -int aa_set_current_hat(struct aa_profile *profile, u64 token) +int aa_set_current_hat(struct aa_label *label, u64 token) { struct aa_task_cxt *cxt; struct cred *new = prepare_creds(); if (!new) return -ENOMEM; - BUG_ON(!profile); + BUG_ON(!label); cxt = cred_cxt(new); if (!cxt->previous) { /* transfer refcount */ - cxt->previous = cxt->profile; + cxt->previous = cxt->label; cxt->token = token; } else if (cxt->token == token) { - aa_put_profile(cxt->profile); + aa_put_label(cxt->label); } else { /* previous_profile && cxt->token != token */ abort_creds(new); return -EACCES; } - cxt->profile = labels_profile(aa_get_newest_label(&profile->label)); + cxt->label = aa_get_newest_label(label); /* clear exec on switching context */ - aa_put_profile(cxt->onexec); + aa_put_label(cxt->onexec); cxt->onexec = NULL; commit_creds(new); @@ -185,15 +181,15 @@ int aa_set_current_hat(struct aa_profile *profile, u64 token) } /** - * aa_restore_previous_profile - exit from hat context restoring the profile + * aa_restore_previous_label - exit from hat context restoring previous label * @token: the token that must be matched to exit hat context * - * Attempt to return out of a hat to the previous profile. The token + * Attempt to return out of a hat to the previous label. The token * must match the stored token value. * * Returns: 0 or error of failure */ -int aa_restore_previous_profile(u64 token) +int aa_restore_previous_label(u64 token) { struct aa_task_cxt *cxt; struct cred *new = prepare_creds(); @@ -205,15 +201,15 @@ int aa_restore_previous_profile(u64 token) abort_creds(new); return -EACCES; } - /* ignore restores when there is no saved profile */ + /* ignore restores when there is no saved label */ if (!cxt->previous) { abort_creds(new); return 0; } - aa_put_profile(cxt->profile); - cxt->profile = labels_profile(aa_get_newest_label(&cxt->previous->label)); - BUG_ON(!cxt->profile); + aa_put_label(cxt->label); + cxt->label = aa_get_newest_label(cxt->previous); + BUG_ON(!cxt->label); /* clear exec && prev information when restoring to previous context */ aa_clear_task_cxt_trans(cxt); diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c index 66454ad..6dc0367 100644 --- a/security/apparmor/domain.c +++ b/security/apparmor/domain.c @@ -62,24 +62,24 @@ static int may_change_ptraced_domain(struct task_struct *task, struct aa_profile *to_profile) { struct task_struct *tracer; - struct aa_profile *tracerp = NULL; + struct aa_label *tracerl = NULL; int error = 0; rcu_read_lock(); tracer = ptrace_parent(task); if (tracer) /* released below */ - tracerp = aa_get_task_profile(tracer); + tracerl = aa_get_task_label(tracer); /* not ptraced */ - if (!tracer || unconfined(tracerp)) + if (!tracer || unconfined(tracerl)) goto out; - error = aa_may_ptrace(tracer, tracerp, to_profile, PTRACE_MODE_ATTACH); + error = aa_may_ptrace(tracer, tracerl, &to_profile->label, PTRACE_MODE_ATTACH); out: rcu_read_unlock(); - aa_put_profile(tracerp); + aa_put_label(tracerl); return error; } @@ -103,7 +103,7 @@ static struct file_perms change_profile_perms(struct aa_profile *profile, struct path_cond cond = { }; unsigned int state; - if (unconfined(profile)) { + if (profile_unconfined(profile)) { perms.allow = AA_MAY_CHANGE_PROFILE | AA_MAY_ONEXEC; perms.audit = perms.quiet = perms.kill = 0; return perms; @@ -339,6 +339,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_label *label; struct aa_profile *profile, *new_profile = NULL; struct aa_namespace *ns; char *buffer = NULL; @@ -359,7 +360,8 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm) cxt = cred_cxt(bprm->cred); BUG_ON(!cxt); - profile = labels_profile(aa_get_newest_label(&cxt->profile->label)); + label = aa_get_newest_label(cxt->label); + profile = labels_profile(label); /* * get the namespace from the replacement profile as replacement * can change the namespace @@ -371,7 +373,7 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm) error = aa_path_name(&bprm->file->f_path, profile->path_flags, &buffer, &name, &info); if (error) { - if (unconfined(profile) || + if (profile_unconfined(profile) || (profile->label.flags & FLAG_IX_ON_NAME_ERROR)) error = 0; name = bprm->filename; @@ -381,11 +383,11 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm) /* Test for onexec first as onexec directives override other * x transitions. */ - if (unconfined(profile)) { + if (profile_unconfined(profile)) { /* unconfined task */ if (cxt->onexec) /* change_profile on exec already been granted */ - new_profile = aa_get_profile(cxt->onexec); + new_profile = labels_profile(aa_get_label(cxt->onexec)); else new_profile = find_attach(ns, &ns->base.profiles, name); if (!new_profile) @@ -411,13 +413,13 @@ 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, labels_profile(cxt->onexec)->ns, + labels_profile(cxt->onexec)->base.name, AA_MAY_ONEXEC, state); if (!(cp.allow & AA_MAY_ONEXEC)) goto audit; - new_profile = labels_profile(aa_get_newest_label(&cxt->onexec->label)); + new_profile = labels_profile(aa_get_newest_label(cxt->onexec)); goto apply; } @@ -507,9 +509,9 @@ apply: bprm->per_clear |= PER_CLEAR_ON_SETID; x_clear: - aa_put_profile(cxt->profile); + aa_put_label(cxt->label); /* transfer new profile reference will be released when cxt is freed */ - cxt->profile = new_profile; + cxt->label = &new_profile->label; /* clear out all temporary/transitional state from the context */ aa_clear_task_cxt_trans(cxt); @@ -519,7 +521,7 @@ audit: name, target, cond.uid, info, error); cleanup: - aa_put_profile(profile); + aa_put_label(label); kfree(buffer); return error; @@ -550,18 +552,18 @@ 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_label *label = __aa_current_label(); struct aa_task_cxt *new_cxt = cred_cxt(bprm->cred); /* bail out if unconfined or not changing profile */ - if ((new_cxt->profile == profile) || - (unconfined(new_cxt->profile))) + if ((new_cxt->label == label) || + (unconfined(new_cxt->label))) return; current->pdeath_signal = 0; - /* reset soft limits and set hard limits for the new profile */ - __aa_transition_rlimits(profile, new_cxt->profile); + /* reset soft limits and set hard limits for the new label */ + __aa_transition_rlimits(label, new_cxt->label); } /** @@ -611,7 +613,8 @@ int aa_change_hat(const char *hats[], int count, u64 token, bool permtest) { const struct cred *cred; struct aa_task_cxt *cxt; - struct aa_profile *profile, *previous_profile, *hat = NULL; + struct aa_label *label, *previous; + struct aa_profile *profile, *hat = NULL; char *name = NULL; int i; struct file_perms perms = {}; @@ -629,10 +632,12 @@ int aa_change_hat(const char *hats[], int count, u64 token, bool permtest) /* released below */ cred = get_current_cred(); cxt = cred_cxt(cred); - profile = aa_cred_profile(cred); - previous_profile = cxt->previous; + label = aa_cred_label(cred); + previous = cxt->previous; - if (unconfined(profile)) { + profile = labels_profile(label); + + if (unconfined(label)) { info = "unconfined"; error = -EPERM; goto audit; @@ -644,7 +649,7 @@ int aa_change_hat(const char *hats[], int count, u64 token, bool permtest) if (PROFILE_IS_HAT(profile)) root = aa_get_profile_rcu(&profile->parent); else - root = aa_get_profile(profile); + root = aa_get_profile(labels_profile(label)); /* find first matching hat */ for (i = 0; i < count && !hat; i++) @@ -698,7 +703,7 @@ int aa_change_hat(const char *hats[], int count, u64 token, bool permtest) } if (!permtest) { - error = aa_set_current_hat(hat, token); + error = aa_set_current_hat(&hat->label, token); if (error == -EACCES) /* kill task in case of brute force attacks */ perms.kill = AA_MAY_CHANGEHAT; @@ -706,12 +711,12 @@ int aa_change_hat(const char *hats[], int count, u64 token, bool permtest) /* reset error for learning of new hats */ error = -ENOENT; } - } else if (previous_profile) { - /* Return to saved profile. Kill task if restore fails + } else if (previous) { + /* Return to saved label. Kill task if restore fails * to avoid brute force attacks */ - target = previous_profile->base.hname; - error = aa_restore_previous_profile(token); + target = previous->hname; + error = aa_restore_previous_label(token); perms.kill = AA_MAY_CHANGEHAT; } else /* ignore restores when there is no saved profile */ @@ -750,6 +755,7 @@ int aa_change_profile(const char *ns_name, const char *hname, bool onexec, bool permtest) { const struct cred *cred; + struct aa_label *label; struct aa_profile *profile, *target = NULL; struct aa_namespace *ns = NULL; struct file_perms perms = {}; @@ -769,7 +775,8 @@ int aa_change_profile(const char *ns_name, const char *hname, bool onexec, } cred = get_current_cred(); - profile = aa_cred_profile(cred); + label = aa_cred_label(cred); + profile = labels_profile(label); /* * Fail explicitly requested domain transitions if no_new_privs @@ -778,7 +785,7 @@ int aa_change_profile(const char *ns_name, const char *hname, bool onexec, * no_new_privs is set because this aways results in a reduction * of permissions. */ - if (current->no_new_privs && !unconfined(profile)) { + if (current->no_new_privs && !unconfined(label)) { put_cred(cred); return -EPERM; } @@ -799,7 +806,7 @@ int aa_change_profile(const char *ns_name, const char *hname, bool onexec, /* if the name was not specified, use the name of the current profile */ if (!hname) { - if (unconfined(profile)) + if (profile_unconfined(profile)) hname = ns->unconfined->base.hname; else hname = profile->base.hname; @@ -839,9 +846,9 @@ int aa_change_profile(const char *ns_name, const char *hname, bool onexec, goto audit; if (onexec) - error = aa_set_current_onexec(target); + error = aa_set_current_onexec(&target->label); else - error = aa_replace_current_profile(target); + error = aa_replace_current_label(&target->label); audit: if (!permtest) diff --git a/security/apparmor/include/context.h b/security/apparmor/include/context.h index 10c4a30..2a6c105 100644 --- a/security/apparmor/include/context.h +++ b/security/apparmor/include/context.h @@ -19,6 +19,7 @@ #include <linux/slab.h> #include <linux/sched.h> +#include "label.h" #include "policy.h" #define cred_cxt(X) (X)->security @@ -28,7 +29,7 @@ * @perms: the permission the file was opened with * * The file_cxt could currently be directly stored in file->f_security - * as the profile reference is now stored in the f_cred. However the + * as the label reference is now stored in the f_cred. However the * cxt struct will expand in the future so we keep the struct. */ struct aa_file_cxt { @@ -58,20 +59,20 @@ static inline void aa_free_file_context(struct aa_file_cxt *cxt) /** * struct aa_task_cxt - 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) - * @token: magic value the task must know for returning to @previous_profile + * @label: the current label (NOT NULL) + * @exec: label to transition to on next exec (MAYBE NULL) + * @previous: label the task may return to (MAYBE NULL) + * @token: magic value the task must know for returning to @previous * - * Contains the task's current profile (which could change due to + * Contains the task's current label (which could change due to * change_hat). Plus the hat_magic needed during change_hat. * * TODO: make so a task can be confined by a stack of contexts */ struct aa_task_cxt { - struct aa_profile *profile; - struct aa_profile *onexec; - struct aa_profile *previous; + struct aa_label *label; + struct aa_label *onexec; + struct aa_label *previous; u64 token; }; @@ -79,39 +80,39 @@ 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); -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); -int aa_restore_previous_profile(u64 cookie); -struct aa_profile *aa_get_task_profile(struct task_struct *task); +int aa_replace_current_label(struct aa_label *label); +int aa_set_current_onexec(struct aa_label *label); +int aa_set_current_hat(struct aa_label *label, u64 token); +int aa_restore_previous_label(u64 cookie); +struct aa_label *aa_get_task_label(struct task_struct *task); /** - * aa_cred_profile - obtain cred's profiles - * @cred: cred to obtain profiles from (NOT NULL) + * aa_cred_label - obtain cred's label + * @cred: cred to obtain label from (NOT NULL) * - * Returns: confining profile + * Returns: confining label * * does NOT increment reference count */ -static inline struct aa_profile *aa_cred_profile(const struct cred *cred) +static inline struct aa_label *aa_cred_label(const struct cred *cred) { struct aa_task_cxt *cxt = cred_cxt(cred); - BUG_ON(!cxt || !cxt->profile); - return cxt->profile; + BUG_ON(!cxt || !cxt->label); + return cxt->label; } /** - * __aa_task_profile - retrieve another task's profile + * __aa_task_label - retrieve another task's label * @task: task to query (NOT NULL) * - * Returns: @task's profile without incrementing its ref count + * Returns: @task's label without incrementing its ref count * * If @task != current needs to be called in RCU safe critical section */ -static inline struct aa_profile *__aa_task_profile(struct task_struct *task) +static inline struct aa_label *__aa_task_label(struct task_struct *task) { - return aa_cred_profile(__task_cred(task)); + return aa_cred_label(__task_cred(task)); } /** @@ -122,44 +123,44 @@ static inline struct aa_profile *__aa_task_profile(struct task_struct *task) */ static inline bool __aa_task_is_confined(struct task_struct *task) { - return !unconfined(__aa_task_profile(task)); + return !unconfined(__aa_task_label(task)); } /** - * __aa_current_profile - find the current tasks confining profile + * __aa_current_label - find the current tasks confining label * - * Returns: up to date confining profile or the ns unconfined profile (NOT NULL) + * Returns: up to date confining label or the ns unconfined label (NOT NULL) * * This fn will not update the tasks cred to the most up to date version - * of the profile so it is safe to call when inside of locks. + * of the label so it is safe to call when inside of locks. */ -static inline struct aa_profile *__aa_current_profile(void) +static inline struct aa_label *__aa_current_label(void) { - return aa_cred_profile(current_cred()); + return aa_cred_label(current_cred()); } /** - * aa_current_profile - find the current tasks confining profile and do updates + * aa_current_label - find the current tasks confining label and update it * - * Returns: up to date confining profile or the ns unconfined profile (NOT NULL) + * Returns: up to date confining label or the ns unconfined label (NOT NULL) * - * This fn will update the tasks cred structure if the profile has been + * This fn will update the tasks cred structure if the label has been * replaced. Not safe to call inside locks */ -static inline struct aa_profile *aa_current_profile(void) +static inline struct aa_label *aa_current_label(void) { const struct aa_task_cxt *cxt = current_cxt(); - struct aa_profile *profile; - BUG_ON(!cxt || !cxt->profile); + struct aa_label *label; + BUG_ON(!cxt || !cxt->label); - if (PROFILE_INVALID(cxt->profile)) { - profile = labels_profile(aa_get_newest_label(&cxt->profile->label)); - aa_replace_current_profile(profile); - aa_put_profile(profile); + if (label_invalid(cxt->label)) { + label = aa_get_newest_label(cxt->label); + aa_replace_current_label(label); + aa_put_label(label); cxt = current_cxt(); } - return cxt->profile; + return cxt->label; } /** @@ -168,8 +169,8 @@ static inline struct aa_profile *aa_current_profile(void) */ static inline void aa_clear_task_cxt_trans(struct aa_task_cxt *cxt) { - aa_put_profile(cxt->previous); - aa_put_profile(cxt->onexec); + aa_put_label(cxt->previous); + aa_put_label(cxt->onexec); cxt->previous = NULL; cxt->onexec = NULL; cxt->token = 0; diff --git a/security/apparmor/include/ipc.h b/security/apparmor/include/ipc.h index aeda0fb..73d9d48 100644 --- a/security/apparmor/include/ipc.h +++ b/security/apparmor/include/ipc.h @@ -19,8 +19,8 @@ struct aa_profile; -int aa_may_ptrace(struct task_struct *tracer_task, struct aa_profile *tracer, - struct aa_profile *tracee, unsigned int mode); +int aa_may_ptrace(struct task_struct *tracer_task, struct aa_label *tracer, + struct aa_label *tracee, unsigned int mode); int aa_ptrace(struct task_struct *tracer, struct task_struct *tracee, unsigned int mode); diff --git a/security/apparmor/include/label.h b/security/apparmor/include/label.h index 2ff1eb0..7f62ede 100644 --- a/security/apparmor/include/label.h +++ b/security/apparmor/include/label.h @@ -151,6 +151,7 @@ struct aa_label { #define label_isprofile(X) ((X)->flags & FLAG_PROFILE) #define label_unconfined(X) ((X)->flags & FLAG_UNCONFINED) +#define unconfined(X) label_unconfined(X) #define label_invalid(X) ((X)->flags & FLAG_INVALID) #define __label_invalidate(X) do { \ labelsetstats_inc(labels_set(X), invalid); \ diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h index 932395d..dd007f0 100644 --- a/security/apparmor/include/policy.h +++ b/security/apparmor/include/policy.h @@ -30,6 +30,7 @@ #include "label.h" #include "resource.h" +extern const char *aa_hidden_ns_name; extern const char *const aa_profile_mode_names[]; #define APPARMOR_NAMES_MAX_INDEX 4 @@ -215,10 +216,10 @@ void aa_free_namespace_kref(struct kref *kref); struct aa_namespace *aa_find_namespace(struct aa_namespace *root, const char *name); +struct aa_label *aa_setup_default_label(void); struct aa_profile *aa_alloc_profile(const char *name); struct aa_profile *aa_new_null_profile(struct aa_profile *parent, int hat); -struct aa_profile *aa_setup_default_profile(void); void aa_free_profile(struct aa_profile *profile); void aa_free_profile_kref(struct kref *kref); struct aa_profile *aa_find_child(struct aa_profile *parent, const char *name); @@ -234,7 +235,7 @@ ssize_t aa_remove_profiles(char *name, size_t size); #define PROF_REPLACE 0 #define profile_unconfined(X) ((X)->mode == APPARMOR_UNCONFINED) -#define unconfined(X) profile_unconfined(X) + /** diff --git a/security/apparmor/include/procattr.h b/security/apparmor/include/procattr.h index 6bd5f33..e4d2618 100644 --- a/security/apparmor/include/procattr.h +++ b/security/apparmor/include/procattr.h @@ -18,7 +18,7 @@ #define AA_DO_TEST 1 #define AA_ONEXEC 1 -int aa_getprocattr(struct aa_profile *profile, char **string); +int aa_getprocattr(struct aa_label *label, char **string); int aa_setprocattr_changehat(char *args, size_t size, int test); int aa_setprocattr_changeprofile(char *fqname, bool onexec, int test); diff --git a/security/apparmor/include/resource.h b/security/apparmor/include/resource.h index d3f4cf0..69d3b8a 100644 --- a/security/apparmor/include/resource.h +++ b/security/apparmor/include/resource.h @@ -37,10 +37,10 @@ struct aa_rlimit { extern struct aa_fs_entry aa_fs_entry_rlimit[]; int aa_map_resource(int resource); -int aa_task_setrlimit(struct aa_profile *profile, struct task_struct *, +int aa_task_setrlimit(struct aa_label *label, struct task_struct *, unsigned int resource, struct rlimit *new_rlim); -void __aa_transition_rlimits(struct aa_profile *old, struct aa_profile *new); +void __aa_transition_rlimits(struct aa_label *old, struct aa_label *new); static inline void aa_free_rlimit_rules(struct aa_rlimit *rlims) { diff --git a/security/apparmor/ipc.c b/security/apparmor/ipc.c index c51d226..364a76b 100644 --- a/security/apparmor/ipc.c +++ b/security/apparmor/ipc.c @@ -55,14 +55,14 @@ static int aa_audit_ptrace(struct aa_profile *profile, /** * aa_may_ptrace - test if tracer task can trace the tracee * @tracer_task: task who will do the tracing (NOT NULL) - * @tracer: profile of the task doing the tracing (NOT NULL) + * @tracer: label of the task doing the tracing (NOT NULL) * @tracee: task to be traced * @mode: whether PTRACE_MODE_READ || PTRACE_MODE_ATTACH * * Returns: %0 else error code if permission denied or error */ -int aa_may_ptrace(struct task_struct *tracer_task, struct aa_profile *tracer, - struct aa_profile *tracee, unsigned int mode) +int aa_may_ptrace(struct task_struct *tracer_task, struct aa_label *tracer, + struct aa_label *tracee, unsigned int mode) { /* TODO: currently only based on capability, not extended ptrace * rules, @@ -72,7 +72,7 @@ int aa_may_ptrace(struct task_struct *tracer_task, struct aa_profile *tracer, if (unconfined(tracer) || tracer == tracee) return 0; /* log this capability request */ - return aa_capable(tracer_task, tracer, CAP_SYS_PTRACE, 1); + return aa_capable(tracer_task, labels_profile(tracer), CAP_SYS_PTRACE, 1); } /** @@ -95,18 +95,19 @@ int aa_ptrace(struct task_struct *tracer, struct task_struct *tracee, * - tracer profile has CAP_SYS_PTRACE */ - struct aa_profile *tracer_p = aa_get_task_profile(tracer); + struct aa_label *tracer_l = aa_get_task_label(tracer); int error = 0; - if (!unconfined(tracer_p)) { - struct aa_profile *tracee_p = aa_get_task_profile(tracee); + if (!unconfined(tracer_l)) { + struct aa_label *tracee_l = aa_get_task_label(tracee); - error = aa_may_ptrace(tracer, tracer_p, tracee_p, mode); - error = aa_audit_ptrace(tracer_p, tracee_p, error); + error = aa_may_ptrace(tracer, tracer_l, tracee_l, mode); - aa_put_profile(tracee_p); + error = aa_audit_ptrace(labels_profile(tracer_l), labels_profile(tracee_l), error); + + aa_put_label(tracee_l); } - aa_put_profile(tracer_p); + aa_put_label(tracer_l); return error; } diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index 31fb46d..55f76d9 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -44,7 +44,7 @@ int apparmor_initialized __initdata; */ /* - * free the associated aa_task_cxt and put its profiles + * free the associated aa_task_cxt and put its labels */ static void apparmor_cred_free(struct cred *cred) { @@ -116,20 +116,20 @@ static int apparmor_ptrace_traceme(struct task_struct *parent) static int apparmor_capget(struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted) { - struct aa_profile *profile; + struct aa_label *label; const struct cred *cred; rcu_read_lock(); cred = __task_cred(target); - profile = aa_cred_profile(cred); + label = aa_cred_label(cred); *effective = cred->cap_effective; *inheritable = cred->cap_inheritable; *permitted = cred->cap_permitted; - if (!unconfined(profile) && !COMPLAIN_MODE(profile)) { - *effective = cap_intersect(*effective, profile->caps.allow); - *permitted = cap_intersect(*permitted, profile->caps.allow); + if (!unconfined(label) && !COMPLAIN_MODE(labels_profile(label))) { + *effective = cap_intersect(*effective, labels_profile(label)->caps.allow); + *permitted = cap_intersect(*permitted, labels_profile(label)->caps.allow); } rcu_read_unlock(); @@ -139,13 +139,13 @@ static int apparmor_capget(struct task_struct *target, kernel_cap_t *effective, static int apparmor_capable(const struct cred *cred, struct user_namespace *ns, int cap, int audit) { - struct aa_profile *profile; + struct aa_label *label; /* cap_capable returns 0 on success, else -EPERM */ int error = cap_capable(cred, ns, cap, audit); if (!error) { - profile = aa_cred_profile(cred); - if (!unconfined(profile)) - error = aa_capable(current, profile, cap, audit); + label = aa_cred_label(cred); + if (!unconfined(label)) + error = aa_capable(current, labels_profile(label), cap, audit); } return error; } @@ -162,12 +162,12 @@ static int apparmor_capable(const struct cred *cred, struct user_namespace *ns, static int common_perm(int op, struct path *path, u32 mask, struct path_cond *cond) { - struct aa_profile *profile; + struct aa_label *label; int error = 0; - profile = __aa_current_profile(); - if (!unconfined(profile)) - error = aa_path_perm(op, profile, path, 0, mask, cond); + label = __aa_current_label(); + if (!unconfined(label)) + error = aa_path_perm(op, labels_profile(label), path, 0, mask, cond); return error; } @@ -302,41 +302,41 @@ static int apparmor_path_symlink(struct path *dir, struct dentry *dentry, static int apparmor_path_link(struct dentry *old_dentry, struct path *new_dir, struct dentry *new_dentry) { - struct aa_profile *profile; + struct aa_label *label; int error = 0; if (!mediated_filesystem(old_dentry->d_inode)) return 0; - profile = aa_current_profile(); - if (!unconfined(profile)) - error = aa_path_link(profile, old_dentry, new_dir, new_dentry); + label = aa_current_label(); + if (!unconfined(label)) + error = aa_path_link(labels_profile(label), old_dentry, new_dir, new_dentry); return error; } static int apparmor_path_rename(struct path *old_dir, struct dentry *old_dentry, struct path *new_dir, struct dentry *new_dentry) { - struct aa_profile *profile; + struct aa_label *label; int error = 0; if (!mediated_filesystem(old_dentry->d_inode)) return 0; - profile = aa_current_profile(); - if (!unconfined(profile)) { + label = aa_current_label(); + if (!unconfined(label)) { struct path old_path = { old_dir->mnt, old_dentry }; struct path new_path = { new_dir->mnt, new_dentry }; struct path_cond cond = { old_dentry->d_inode->i_uid, old_dentry->d_inode->i_mode }; - error = aa_path_perm(OP_RENAME_SRC, profile, &old_path, 0, + error = aa_path_perm(OP_RENAME_SRC, labels_profile(label), &old_path, 0, MAY_READ | AA_MAY_META_READ | MAY_WRITE | AA_MAY_META_WRITE | AA_MAY_DELETE, &cond); if (!error) - error = aa_path_perm(OP_RENAME_DEST, profile, &new_path, + error = aa_path_perm(OP_RENAME_DEST, labels_profile(label), &new_path, 0, MAY_WRITE | AA_MAY_META_WRITE | AA_MAY_CREATE, &cond); @@ -376,7 +376,7 @@ static int apparmor_inode_getattr(struct vfsmount *mnt, struct dentry *dentry) static int apparmor_file_open(struct file *file, const struct cred *cred) { struct aa_file_cxt *fcxt = file->f_security; - struct aa_profile *profile; + struct aa_label *label; int error = 0; if (!mediated_filesystem(file->f_path.dentry->d_inode)) @@ -392,12 +392,12 @@ static int apparmor_file_open(struct file *file, const struct cred *cred) return 0; } - profile = aa_cred_profile(cred); - if (!unconfined(profile)) { + label = aa_cred_label(cred); + if (!unconfined(label)) { struct inode *inode = file->f_path.dentry->d_inode; struct path_cond cond = { inode->i_uid, inode->i_mode }; - error = aa_path_perm(OP_OPEN, profile, &file->f_path, 0, + error = aa_path_perm(OP_OPEN, labels_profile(label), &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); @@ -426,16 +426,16 @@ static void apparmor_file_free_security(struct file *file) static int common_file_perm(int op, struct file *file, u32 mask) { struct aa_file_cxt *fcxt = file->f_security; - struct aa_profile *profile, *fprofile = aa_cred_profile(file->f_cred); + struct aa_label *label, *flabel = aa_cred_label(file->f_cred); int error = 0; - BUG_ON(!fprofile); + BUG_ON(!flabel); if (!file->f_path.mnt || !mediated_filesystem(file->f_path.dentry->d_inode)) return 0; - profile = __aa_current_profile(); + label = __aa_current_label(); /* revalidate access, if task is unconfined, or the cached cred * doesn't match or if the request is for more permissions than @@ -444,9 +444,9 @@ static int common_file_perm(int op, struct file *file, u32 mask) * Note: the test for !unconfined(fprofile) is to handle file * delegation from unconfined tasks */ - if (!unconfined(profile) && !unconfined(fprofile) && - ((fprofile != profile) || (mask & ~fcxt->allow))) - error = aa_file_perm(op, profile, file, mask); + if (!unconfined(label) && !unconfined(flabel) && + ((flabel != label) || (mask & ~fcxt->allow))) + error = aa_file_perm(op, labels_profile(label), file, mask); return error; } @@ -508,21 +508,21 @@ static int apparmor_getprocattr(struct task_struct *task, char *name, /* released below */ const struct cred *cred = get_task_cred(task); struct aa_task_cxt *cxt = cred_cxt(cred); - struct aa_profile *profile = NULL; + struct aa_label *label = NULL; if (strcmp(name, "current") == 0) - profile = labels_profile(aa_get_newest_label(&cxt->profile->label)); + label = aa_get_newest_label(cxt->label); else if (strcmp(name, "prev") == 0 && cxt->previous) - profile = labels_profile(aa_get_newest_label(&cxt->previous->label)); + label = aa_get_newest_label(cxt->label); else if (strcmp(name, "exec") == 0 && cxt->onexec) - profile = labels_profile(aa_get_newest_label(&cxt->onexec->label)); + label = aa_get_newest_label(cxt->onexec); else error = -EINVAL; - if (profile) - error = aa_getprocattr(profile, value); + if (label) + error = aa_getprocattr(label, value); - aa_put_profile(profile); + aa_put_label(label); put_cred(cred); return error; @@ -595,7 +595,7 @@ static int apparmor_setprocattr(struct task_struct *task, char *name, fail: sa.type = LSM_AUDIT_DATA_NONE; sa.aad = &aad; - aad.profile = aa_current_profile(); + aad.profile = labels_profile(aa_current_label()); aad.op = OP_SETPROCATTR; aad.info = name; aad.error = -EINVAL; @@ -606,11 +606,11 @@ fail: static int apparmor_task_setrlimit(struct task_struct *task, unsigned int resource, struct rlimit *new_rlim) { - struct aa_profile *profile = __aa_current_profile(); + struct aa_label *label = __aa_current_label(); int error = 0; - if (!unconfined(profile)) - error = aa_task_setrlimit(profile, task, resource, new_rlim); + if (!unconfined(label)) + error = aa_task_setrlimit(label, task, resource, new_rlim); return error; } @@ -890,14 +890,14 @@ static int __init set_init_cxt(void) return -ENOMEM; if (!aa_g_unconfined_init) { - cxt->profile = aa_setup_default_profile(); - if (!cxt->profile) { + cxt->label = aa_setup_default_label(); + if (!cxt->label) { aa_free_task_context(cxt); return -ENOMEM; } /* fs setup of default is done in aa_create_aafs() */ } else - cxt->profile = aa_get_profile(root_ns->unconfined); + cxt->label = aa_get_label(&root_ns->unconfined->label); cred_cxt(cred) = cxt; return 0; diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c index 8cf2eed..d77a5c5 100644 --- a/security/apparmor/policy.c +++ b/security/apparmor/policy.c @@ -227,7 +227,7 @@ static struct aa_policy *__policy_strn_find(struct list_head *head, * Routines for AppArmor namespaces */ -static const char *hidden_ns_name = "---"; +const char *aa_hidden_ns_name = "---"; /** * aa_ns_visible - test if @view is visible from @curr * @curr: namespace to treat as the parent (NOT NULL) @@ -269,7 +269,7 @@ const char *aa_ns_name(struct aa_namespace *curr, struct aa_namespace *view) */ return view->base.hname + strlen(curr->base.hname) + 2; } else - return hidden_ns_name; + return aa_hidden_ns_name; } /** @@ -394,7 +394,7 @@ static struct aa_namespace *aa_prepare_namespace(const char *name) { struct aa_namespace *ns, *root; - root = aa_current_profile()->ns; + root = labels_ns(aa_current_label()); mutex_lock(&root->lock); @@ -712,9 +712,9 @@ fail: } /** - * aa_setup_default_profile - create the initial default profile + * aa_setup_default_label - create the initial default label */ -struct aa_profile *aa_setup_default_profile(void) +struct aa_label *aa_setup_default_label(void) { struct aa_profile *profile = aa_alloc_profile("default"); if (!profile) @@ -734,7 +734,7 @@ struct aa_profile *aa_setup_default_profile(void) } __list_add_profile(&root_ns->base.profiles, profile); - return profile; + return &profile->label; } /* TODO: profile accounting - setup in remove */ @@ -943,7 +943,7 @@ static int audit_policy(int op, gfp_t gfp, const char *name, const char *info, aad.info = info; aad.error = error; - return aa_audit(AUDIT_APPARMOR_STATUS, __aa_current_profile(), gfp, + return aa_audit(AUDIT_APPARMOR_STATUS, labels_profile(__aa_current_label()), gfp, &sa, NULL); } @@ -1316,7 +1316,7 @@ ssize_t aa_remove_profiles(char *fqname, size_t size) goto fail; } - root = aa_current_profile()->ns; + root = labels_ns(aa_current_label()); if (fqname[0] == ':') { char *ns_name; diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c index 5035798..c48eff2 100644 --- a/security/apparmor/policy_unpack.c +++ b/security/apparmor/policy_unpack.c @@ -92,7 +92,7 @@ static void audit_cb(struct audit_buffer *ab, void *va) static int audit_iface(struct aa_profile *new, const char *name, const char *info, struct aa_ext *e, int error) { - struct aa_profile *profile = __aa_current_profile(); + struct aa_profile *profile = labels_profile(__aa_current_label()); struct common_audit_data sa; struct apparmor_audit_data aad = {0,}; sa.type = LSM_AUDIT_DATA_NONE; diff --git a/security/apparmor/procattr.c b/security/apparmor/procattr.c index 3914829..82666b0 100644 --- a/security/apparmor/procattr.c +++ b/security/apparmor/procattr.c @@ -33,14 +33,14 @@ * * Returns: size of string placed in @string else error code on failure */ -int aa_getprocattr(struct aa_profile *profile, char **string) +int aa_getprocattr(struct aa_label *label, char **string) { char *str; int len = 0, mode_len = 0, ns_len = 0, name_len; - const char *mode_str = aa_profile_mode_names[profile->mode]; + const char *mode_str = aa_profile_mode_names[labels_profile(label)->mode]; const char *ns_name = NULL; - struct aa_namespace *ns = profile->ns; - struct aa_namespace *current_ns = __aa_current_profile()->ns; + struct aa_namespace *ns = labels_ns(label); + struct aa_namespace *current_ns = labels_ns(__aa_current_label()); bool unconfined; char *s; @@ -55,11 +55,11 @@ int aa_getprocattr(struct aa_profile *profile, char **string) ns_len += 4; /* 'unconfined' profile don't have a mode string appended */ - unconfined = profile == profile->ns->unconfined; + unconfined = labels_profile(label) == labels_ns(label)->unconfined; if (!unconfined) mode_len = strlen(mode_str) + 3; /* + 3 for _() */ - name_len = strlen(profile->base.hname); + name_len = strlen(label->hname); len = mode_len + ns_len + name_len + 1; /* + 1 for \n */ s = str = kmalloc(len + 1, GFP_KERNEL); /* + 1 \0 */ if (!str) @@ -72,9 +72,9 @@ int aa_getprocattr(struct aa_profile *profile, char **string) } if (unconfined) /* mode string not being appended */ - sprintf(s, "%s\n", profile->base.hname); + sprintf(s, "%s\n", label->hname); else - sprintf(s, "%s (%s)\n", profile->base.hname, mode_str); + sprintf(s, "%s (%s)\n", label->hname, mode_str); *string = str; /* NOTE: len does not include \0 of string, not saved as part of file */ diff --git a/security/apparmor/resource.c b/security/apparmor/resource.c index 748bf0c..e0a1d39 100644 --- a/security/apparmor/resource.c +++ b/security/apparmor/resource.c @@ -79,7 +79,7 @@ int aa_map_resource(int resource) /** * aa_task_setrlimit - test permission to set an rlimit - * @profile - profile confining the task (NOT NULL) + * @label - label confining the task (NOT NULL) * @task - task the resource is being set on * @resource - the resource being set * @new_rlim - the new resource limit (NOT NULL) @@ -88,14 +88,14 @@ int aa_map_resource(int resource) * * Returns: 0 or error code if setting resource failed */ -int aa_task_setrlimit(struct aa_profile *profile, struct task_struct *task, +int aa_task_setrlimit(struct aa_label *label, struct task_struct *task, unsigned int resource, struct rlimit *new_rlim) { - struct aa_profile *task_profile; + struct aa_label *task_label; int error = 0; rcu_read_lock(); - task_profile = aa_get_profile(aa_cred_profile(__task_cred(task))); + task_label = aa_get_label(aa_cred_label(__task_cred(task))); rcu_read_unlock(); /* TODO: extend resource control to handle other (non current) @@ -103,27 +103,31 @@ int aa_task_setrlimit(struct aa_profile *profile, struct task_struct *task, * that the task is setting the resource of a task confined with * the same profile. */ - if (profile != task_profile || - (profile->rlimits.mask & (1 << resource) && - new_rlim->rlim_max > profile->rlimits.limits[resource].rlim_max)) + if (label != task_label || + (labels_profile(label)->rlimits.mask & (1 << resource) && + new_rlim->rlim_max > labels_profile(label)->rlimits.limits[resource].rlim_max)) error = -EACCES; - aa_put_profile(task_profile); + aa_put_label(task_label); - return audit_resource(profile, resource, new_rlim->rlim_max, error); + return audit_resource(labels_profile(label), resource, new_rlim->rlim_max, error); } /** * __aa_transition_rlimits - apply new profile rlimits - * @old: old profile on task (NOT NULL) - * @new: new profile with rlimits to apply (NOT NULL) + * @old_l: old label on task (NOT NULL) + * @new_l: new label with rlimits to apply (NOT NULL) */ -void __aa_transition_rlimits(struct aa_profile *old, struct aa_profile *new) +void __aa_transition_rlimits(struct aa_label *old_l, struct aa_label *new_l) { unsigned int mask = 0; struct rlimit *rlim, *initrlim; + struct aa_profile *old, *new; int i; + old = labels_profile(old_l); + new = labels_profile(new_l); + /* for any rlimits the profile controlled reset the soft limit * to the less of the tasks hard limit and the init tasks soft limit */ -- 1.8.1.2 -- AppArmor mailing list [email protected] Modify settings or unsubscribe at: https://lists.ubuntu.com/mailman/listinfo/apparmor
