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:
John Johansen
2023-11-30 11:48:33 -08:00
committed by Paolo Pisati
parent bd1e2a79d2
commit dc757a645c
9 changed files with 48 additions and 43 deletions
+1 -1
View File
@@ -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
View File
@@ -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,
+2 -2
View File
@@ -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,
+1 -1
View File
@@ -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;
+4 -4
View File
@@ -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);
+9 -9
View File
@@ -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,
+1 -2
View File
@@ -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),
+1 -1
View File
@@ -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);
+4 -8
View File
@@ -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
*/