UBUNTU: SAUCE: apparmor4.0.0 [81/90]: apparmor: convert easy uses of unconfined() to label_mediates()
BugLink: http://bugs.launchpad.net/bugs/2028253 This begins the transition from doing a broad unconfined() check to a finer label_mediates() check. Not only does this allow for finer control but it simplifies some code paths, removing redundant checks, will allow us to refactor and simplify the code more, and is generally a small performance win. Note: capabilities and resource need to be converted to use pdb before they can use label_mediates Signed-off-by: John Johansen <john.johansen@canonical.com> (cherry picked from commit d9b866dc2f134a9e8dc21dbfacc935f454896c49 https://git.launchpad.net/~apparmor-dev/ubuntu-kernel-next) Signed-off-by: Paolo Pisati <paolo.pisati@canonical.com>
This commit is contained in:
committed by
Paolo Pisati
parent
bd1e2a79d2
commit
dc757a645c
@@ -828,7 +828,7 @@ static void profile_query_cb(struct aa_profile *profile, struct aa_perms *perms,
|
||||
struct aa_perms tmp = { };
|
||||
aa_state_t state = DFA_NOMATCH;
|
||||
|
||||
if (profile_unconfined(profile))
|
||||
if (!profile_mediates_safe(profile, *match_str))
|
||||
return;
|
||||
if (rules->file->dfa && *match_str == AA_CLASS_FILE) {
|
||||
state = aa_dfa_match_len(rules->file->dfa,
|
||||
|
||||
+25
-15
@@ -285,7 +285,7 @@ static int change_profile_perms(struct aa_profile *profile,
|
||||
u32 request, aa_state_t start,
|
||||
struct aa_perms *perms)
|
||||
{
|
||||
if (profile_unconfined(profile)) {
|
||||
if (!profile_mediates(profile, AA_CLASS_FILE)) {
|
||||
perms->allow = AA_MAY_CHANGE_PROFILE | AA_MAY_ONEXEC;
|
||||
perms->audit = perms->quiet = perms->kill = 0;
|
||||
return 0;
|
||||
@@ -648,7 +648,7 @@ static struct aa_label *profile_transition(const struct cred *subj_cred,
|
||||
error = aa_path_name(&bprm->file->f_path, profile->path_flags, buffer,
|
||||
&name, &info, profile->disconnected);
|
||||
if (error) {
|
||||
if (profile_unconfined(profile) ||
|
||||
if (!profile_mediates(profile, AA_CLASS_FILE) ||
|
||||
(profile->label.flags & FLAG_IX_ON_NAME_ERROR)) {
|
||||
AA_DEBUG(DEBUG_DOMAIN, "name lookup ix on error");
|
||||
error = 0;
|
||||
@@ -658,7 +658,7 @@ static struct aa_label *profile_transition(const struct cred *subj_cred,
|
||||
goto audit;
|
||||
}
|
||||
|
||||
if (profile_unconfined(profile)) {
|
||||
if (!profile_mediates(profile, AA_CLASS_FILE)) {
|
||||
new = find_attach(bprm, profile->ns,
|
||||
&profile->ns->base.profiles, name, &info);
|
||||
if (new) {
|
||||
@@ -745,7 +745,7 @@ static int profile_onexec(const struct cred *subj_cred,
|
||||
AA_BUG(!bprm);
|
||||
AA_BUG(!buffer);
|
||||
|
||||
if (profile_unconfined(profile)) {
|
||||
if (!profile_mediates(profile, AA_CLASS_FILE)) {
|
||||
/* change_profile on exec already granted */
|
||||
/*
|
||||
* NOTE: Domain transitions from unconfined are allowed
|
||||
@@ -758,7 +758,7 @@ static int profile_onexec(const struct cred *subj_cred,
|
||||
error = aa_path_name(&bprm->file->f_path, profile->path_flags, buffer,
|
||||
&xname, &info, profile->disconnected);
|
||||
if (error) {
|
||||
if (profile_unconfined(profile) ||
|
||||
if (!profile_mediates(profile, AA_CLASS_FILE) ||
|
||||
(profile->label.flags & FLAG_IX_ON_NAME_ERROR)) {
|
||||
AA_DEBUG(DEBUG_DOMAIN, "name lookup ix on error");
|
||||
error = 0;
|
||||
@@ -898,8 +898,8 @@ int apparmor_bprm_creds_for_exec(struct linux_binprm *bprm)
|
||||
*
|
||||
* Testing for unconfined must be done before the subset test
|
||||
*/
|
||||
if ((bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS) && !unconfined(label) &&
|
||||
!ctx->nnp)
|
||||
if ((bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS) &&
|
||||
label_mediates(label, AA_CLASS_FILE) && !ctx->nnp)
|
||||
ctx->nnp = aa_get_label(label);
|
||||
|
||||
/* buffer freed below, name is pointer into buffer */
|
||||
@@ -937,7 +937,7 @@ int apparmor_bprm_creds_for_exec(struct linux_binprm *bprm)
|
||||
* aways results in a further reduction of permissions.
|
||||
*/
|
||||
if ((bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS) &&
|
||||
!unconfined(label) &&
|
||||
label_mediates(label, AA_CLASS_FILE) &&
|
||||
!aa_label_is_unconfined_subset(new, ctx->nnp)) {
|
||||
error = -EPERM;
|
||||
info = "no new privs";
|
||||
@@ -1187,14 +1187,20 @@ int aa_change_hat(const char *hats[], int count, u64 token, int flags)
|
||||
label = aa_get_newest_cred_label(subj_cred);
|
||||
previous = aa_get_newest_label(ctx->previous);
|
||||
|
||||
if (!label_mediates(label, AA_CLASS_FILE)) {
|
||||
info = "unconfined can not change_hat";
|
||||
error = -EPERM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/*
|
||||
* Detect no new privs being set, and store the label it
|
||||
* occurred under. Ideally this would happen when nnp
|
||||
* is set but there isn't a good way to do that yet.
|
||||
*
|
||||
* Testing for unconfined must be done before the subset test
|
||||
* Testing for mediation must be done before the subset test
|
||||
*/
|
||||
if (task_no_new_privs(current) && !unconfined(label) && !ctx->nnp)
|
||||
if (task_no_new_privs(current) && !ctx->nnp)
|
||||
ctx->nnp = aa_get_label(label);
|
||||
|
||||
/* return -EPERM when unconfined doesn't have children to avoid
|
||||
@@ -1235,8 +1241,9 @@ int aa_change_hat(const char *hats[], int count, u64 token, int flags)
|
||||
/*
|
||||
* no new privs prevents domain transitions that would
|
||||
* reduce restrictions.
|
||||
* label_mediates(label, AA_CLASS_FILE) == true here
|
||||
*/
|
||||
if (task_no_new_privs(current) && !unconfined(label) &&
|
||||
if (task_no_new_privs(current) &&
|
||||
!aa_label_is_unconfined_subset(new, ctx->nnp)) {
|
||||
/* not an apparmor denial per se, so don't log it */
|
||||
AA_DEBUG(DEBUG_DOMAIN,
|
||||
@@ -1257,8 +1264,9 @@ int aa_change_hat(const char *hats[], int count, u64 token, int flags)
|
||||
/*
|
||||
* no new privs prevents domain transitions that would
|
||||
* reduce restrictions.
|
||||
* label_mediates(label, AA_CLASS_FILE) == true here
|
||||
*/
|
||||
if (task_no_new_privs(current) && !unconfined(label) &&
|
||||
if (task_no_new_privs(current) &&
|
||||
!aa_label_is_unconfined_subset(previous, ctx->nnp)) {
|
||||
/* not an apparmor denial per se, so don't log it */
|
||||
AA_DEBUG(DEBUG_DOMAIN,
|
||||
@@ -1363,7 +1371,8 @@ int aa_change_profile(const char *fqname, int flags)
|
||||
*
|
||||
* Testing for unconfined must be done before the subset test
|
||||
*/
|
||||
if (task_no_new_privs(current) && !unconfined(label) && !ctx->nnp)
|
||||
if (task_no_new_privs(current) &&
|
||||
label_mediates(label, AA_CLASS_FILE) && !ctx->nnp)
|
||||
ctx->nnp = aa_get_label(label);
|
||||
|
||||
if (!fqname || !*fqname) {
|
||||
@@ -1389,7 +1398,7 @@ int aa_change_profile(const char *fqname, int flags)
|
||||
/* This should move to a per profile test. Requires pushing build
|
||||
* into callback
|
||||
*/
|
||||
if (!stack && unconfined(label) &&
|
||||
if (!stack && !label_mediates(label, AA_CLASS_FILE) &&
|
||||
label == &labels_ns(label)->unconfined->label &&
|
||||
aa_unprivileged_unconfined_restricted &&
|
||||
/* TODO: refactor so this check is a fn */
|
||||
@@ -1485,7 +1494,8 @@ check:
|
||||
* no new privs prevents domain transitions that would
|
||||
* reduce restrictions.
|
||||
*/
|
||||
if (task_no_new_privs(current) && !unconfined(label) &&
|
||||
if (task_no_new_privs(current) &&
|
||||
label_mediates(label, AA_CLASS_FILE) &&
|
||||
!aa_label_is_unconfined_subset(new, ctx->nnp)) {
|
||||
/* not an apparmor denial per se, so don't log it */
|
||||
AA_DEBUG(DEBUG_DOMAIN,
|
||||
|
||||
@@ -376,7 +376,7 @@ int __aa_path_perm(const char *op, const struct cred *subj_cred,
|
||||
typeof(*rules), list);
|
||||
int e = 0;
|
||||
|
||||
if (profile_unconfined(profile) ||
|
||||
if (!profile_mediates(profile, AA_CLASS_FILE) ||
|
||||
((flags & PATH_SOCK_COND) && !RULE_MEDIATES_AF(rules, AF_UNIX)))
|
||||
return 0;
|
||||
aa_str_perms(rules->file, rules->file->start[AA_CLASS_FILE],
|
||||
@@ -398,7 +398,7 @@ static int profile_path_perm(const char *op, const struct cred *subj_cred,
|
||||
const char *name;
|
||||
int error;
|
||||
|
||||
if (profile_unconfined(profile))
|
||||
if (!profile_mediates(profile, AA_CLASS_FILE))
|
||||
return 0;
|
||||
|
||||
error = path_name(op, subj_cred, &profile->label, path,
|
||||
|
||||
@@ -88,7 +88,7 @@ static int profile_signal_perm(const struct cred *cred,
|
||||
struct aa_perms perms;
|
||||
aa_state_t state;
|
||||
|
||||
if (profile_unconfined(profile))
|
||||
if (!profile_mediates(profile, AA_CLASS_SIGNAL))
|
||||
return 0;
|
||||
|
||||
ad->subj_cred = cred;
|
||||
|
||||
@@ -203,13 +203,13 @@ static void accum_label_info(struct aa_label *new)
|
||||
long u = FLAG_UNCONFINED;
|
||||
int i;
|
||||
|
||||
AA_BUG(!new->vec);
|
||||
AA_BUG(!new || !new->vec);
|
||||
|
||||
/* size == 1 is a profile and flags must be set as part of creation */
|
||||
if (new->size == 1)
|
||||
return;
|
||||
return;
|
||||
|
||||
for (i = 0; i < new->size; i++) {
|
||||
for (i = 0; i < new->size; i++) {
|
||||
u |= new->vec[i]->label.flags & (FLAG_DEBUG1 | FLAG_DEBUG2 |
|
||||
FLAG_STALE);
|
||||
if (!(u & new->vec[i]->label.flags & FLAG_UNCONFINED))
|
||||
@@ -885,7 +885,6 @@ static struct aa_label *vec_create_and_insert_label(struct aa_profile **vec,
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
new->vec[i] = aa_get_profile(vec[i]);
|
||||
|
||||
write_lock_irqsave(&ls->lock, flags);
|
||||
label = __label_insert(ls, new, false);
|
||||
write_unlock_irqrestore(&ls->lock, flags);
|
||||
@@ -2094,6 +2093,7 @@ static struct aa_label *__label_update(struct aa_label *label)
|
||||
AA_BUG(tmp == label);
|
||||
goto remove;
|
||||
}
|
||||
|
||||
if (labels_set(label) != labels_set(new)) {
|
||||
write_unlock_irqrestore(&ls->lock, flags);
|
||||
tmp = aa_label_insert(labels_set(new), new);
|
||||
|
||||
@@ -234,7 +234,7 @@ static int common_perm(const char *op, const struct path *path, u32 mask,
|
||||
int error = 0;
|
||||
|
||||
label = __begin_current_label_crit_section();
|
||||
if (!unconfined(label))
|
||||
if (label_mediates(label, AA_CLASS_FILE))
|
||||
error = aa_path_perm(op, current_cred(), label, path, 0, mask,
|
||||
cond);
|
||||
__end_current_label_crit_section(label);
|
||||
@@ -381,7 +381,7 @@ static int apparmor_path_link(struct dentry *old_dentry, const struct path *new_
|
||||
return 0;
|
||||
|
||||
label = begin_current_label_crit_section();
|
||||
if (!unconfined(label))
|
||||
if (label_mediates(label, AA_CLASS_FILE))
|
||||
error = aa_path_link(current_cred(), label, old_dentry, new_dir,
|
||||
new_dentry);
|
||||
end_current_label_crit_section(label);
|
||||
@@ -402,7 +402,7 @@ static int apparmor_path_rename(const struct path *old_dir, struct dentry *old_d
|
||||
return 0;
|
||||
|
||||
label = begin_current_label_crit_section();
|
||||
if (!unconfined(label)) {
|
||||
if (label_mediates(label, AA_CLASS_FILE)) {
|
||||
struct mnt_idmap *idmap = mnt_idmap(old_dir->mnt);
|
||||
vfsuid_t vfsuid;
|
||||
struct path old_path = { .mnt = old_dir->mnt,
|
||||
@@ -646,7 +646,7 @@ static int apparmor_file_open(struct file *file)
|
||||
}
|
||||
|
||||
label = aa_get_newest_cred_label(file->f_cred);
|
||||
if (!unconfined(label)) {
|
||||
if (label_mediates(label, AA_CLASS_FILE)) {
|
||||
struct mnt_idmap *idmap = file_mnt_idmap(file);
|
||||
struct inode *inode = file_inode(file);
|
||||
vfsuid_t vfsuid;
|
||||
@@ -916,7 +916,7 @@ static int apparmor_sb_mount(const char *dev_name, const struct path *path,
|
||||
flags &= ~AA_MS_IGNORE_MASK;
|
||||
|
||||
label = __begin_current_label_crit_section();
|
||||
if (!unconfined(label)) {
|
||||
if (label_mediates(label, AA_CLASS_MOUNT)) {
|
||||
if (flags & MS_REMOUNT)
|
||||
error = aa_remount(current_cred(), label, path, flags,
|
||||
data);
|
||||
@@ -946,7 +946,7 @@ static int apparmor_move_mount(const struct path *from_path,
|
||||
int error = 0;
|
||||
|
||||
label = __begin_current_label_crit_section();
|
||||
if (!unconfined(label))
|
||||
if (label_mediates(label, AA_CLASS_MOUNT))
|
||||
error = aa_move_mount(current_cred(), label, from_path,
|
||||
to_path);
|
||||
__end_current_label_crit_section(label);
|
||||
@@ -960,7 +960,7 @@ static int apparmor_sb_umount(struct vfsmount *mnt, int flags)
|
||||
int error = 0;
|
||||
|
||||
label = __begin_current_label_crit_section();
|
||||
if (!unconfined(label))
|
||||
if (label_mediates(label, AA_CLASS_MOUNT))
|
||||
error = aa_umount(current_cred(), label, mnt, flags);
|
||||
__end_current_label_crit_section(label);
|
||||
|
||||
@@ -974,7 +974,7 @@ static int apparmor_sb_pivotroot(const struct path *old_path,
|
||||
int error = 0;
|
||||
|
||||
label = aa_get_current_label();
|
||||
if (!unconfined(label))
|
||||
if (label_mediates(label, AA_CLASS_MOUNT))
|
||||
error = aa_pivotroot(current_cred(), label, old_path, new_path);
|
||||
aa_put_label(label);
|
||||
|
||||
@@ -1401,7 +1401,7 @@ static int apparmor_socket_create(int family, int type, int protocol, int kern)
|
||||
AA_BUG(in_interrupt());
|
||||
|
||||
label = begin_current_label_crit_section();
|
||||
if (!(kern || unconfined(label)))
|
||||
if (!kern && label_mediates(label, AA_CLASS_NET))
|
||||
error = af_select(family,
|
||||
create_perm(label, family, type, protocol),
|
||||
aa_af_perm(current_cred(), label,
|
||||
|
||||
@@ -678,8 +678,7 @@ static struct aa_label *build_pivotroot(const struct cred *subj_cred,
|
||||
AA_BUG(!new_path);
|
||||
AA_BUG(!old_path);
|
||||
|
||||
if (profile_unconfined(profile) ||
|
||||
!RULE_MEDIATES(rules, AA_CLASS_MOUNT))
|
||||
if (!RULE_MEDIATES(rules, AA_CLASS_MOUNT))
|
||||
return aa_get_newest_label(&profile->label);
|
||||
|
||||
error = aa_path_name(old_path, path_flags(profile, old_path),
|
||||
|
||||
@@ -221,7 +221,7 @@ static int aa_label_sk_perm(const struct cred *subj_cred,
|
||||
AA_BUG(!label);
|
||||
AA_BUG(!sk);
|
||||
|
||||
if (ctx->label != kernel_t && !unconfined(label)) {
|
||||
if (ctx->label != kernel_t && label_mediates(label, AA_CLASS_NET)) {
|
||||
struct aa_profile *profile;
|
||||
DEFINE_AUDIT_SK(ad, op, sk);
|
||||
|
||||
|
||||
@@ -245,8 +245,8 @@ static int profile_tracee_perm(const struct cred *cred,
|
||||
struct aa_label *tracer, u32 request,
|
||||
struct apparmor_audit_data *ad)
|
||||
{
|
||||
if (profile_unconfined(tracee) || unconfined(tracer) ||
|
||||
!ANY_RULE_MEDIATES(&tracee->rules, AA_CLASS_PTRACE))
|
||||
if (!profile_mediates(tracee, AA_CLASS_PTRACE) ||
|
||||
!label_mediates(tracer, AA_CLASS_PTRACE))
|
||||
return 0;
|
||||
|
||||
return profile_ptrace_perm(cred, tracee, tracer, request, ad);
|
||||
@@ -257,14 +257,11 @@ static int profile_tracer_perm(const struct cred *cred,
|
||||
struct aa_label *tracee, u32 request,
|
||||
struct apparmor_audit_data *ad)
|
||||
{
|
||||
if (profile_unconfined(tracer))
|
||||
return 0;
|
||||
|
||||
if (ANY_RULE_MEDIATES(&tracer->rules, AA_CLASS_PTRACE))
|
||||
if (profile_mediates(tracer, AA_CLASS_PTRACE))
|
||||
return profile_ptrace_perm(cred, tracer, tracee, request, ad);
|
||||
|
||||
/* profile uses the old style capability check for ptrace */
|
||||
if (&tracer->label == tracee)
|
||||
if (&tracer->label == tracee || !profile_mediates(tracer, AA_CLASS_CAP))
|
||||
return 0;
|
||||
|
||||
ad->subj_label = &tracer->label;
|
||||
@@ -325,7 +322,6 @@ int aa_profile_ns_perm(struct aa_profile *profile,
|
||||
ad->subj_label = &profile->label;
|
||||
ad->request = request;
|
||||
|
||||
|
||||
/* TODO: rework unconfined profile/dfa to mediate user ns, then
|
||||
* we can drop the unconfined test
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user