]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
apparmor: split xxx_in_ns into its two separate semantic use cases
authorJohn Johansen <john.johansen@canonical.com>
Thu, 25 Dec 2025 09:21:23 +0000 (01:21 -0800)
committerJohn Johansen <john.johansen@canonical.com>
Thu, 29 Jan 2026 09:27:55 +0000 (01:27 -0800)
This patch doesn't change current functionality, it switches the two
uses of the in_ns fns and macros into the two semantically different
cases they are used for.

xxx_in_scope for checking mediation interaction between profiles
xxx_in_view to determine which profiles are visible.The scope will
always be a subset of the view as profiles that can not see each
other can not interact.

The split can not be completely done for label_match because it has to
distinct uses matching permission against label in scope, and checking
if a transition to a profile is allowed. The transition to a profile
can include profiles that are in view but not in scope, so retain this
distinction as a parameter.

While at the moment the two uses are very similar, in the future there
will be additional differences. So make sure the semantics differences
are present in the code.

Reviewed-by: Georgia Garcia <georgia.garcia@canonical.com>
Signed-off-by: John Johansen <john.johansen@canonical.com>
security/apparmor/af_unix.c
security/apparmor/apparmorfs.c
security/apparmor/domain.c
security/apparmor/include/lib.h
security/apparmor/label.c

index ac0f4be791ecea5e1446509fc86f1f619672850b..fdb4a9f212c3bf856e645ec6a80aa4847f1dd7b2 100644 (file)
@@ -416,7 +416,7 @@ static int profile_peer_perm(struct aa_profile *profile, u32 request,
                                      unix_sk(sk),
                                      peer_addr, peer_addrlen, &p, &ad->info);
 
-               return fn_for_each_in_ns(peer_label, peerp,
+               return fn_for_each_in_scope(peer_label, peerp,
                                match_label(profile, rules, state, request,
                                            peerp, p, ad));
        }
index 91c1fcb78ac881403a7443f2ebfa98e0de3d70aa..9b4f833e36cd09427de6e5693910deb689ce4c21 100644 (file)
@@ -801,7 +801,7 @@ static ssize_t query_label(char *buf, size_t buf_len,
 
        perms = allperms;
        if (view_only) {
-               label_for_each_in_ns(i, labels_ns(label), label, profile) {
+               label_for_each_in_scope(i, labels_ns(label), label, profile) {
                        profile_query_cb(profile, &perms, match_str, match_len);
                }
        } else {
index ee2df25f355d2781cb33ac7a7e853c135202c4ac..f02bf770f6385437946b24e97f85e8ab7d1182b0 100644 (file)
@@ -115,7 +115,7 @@ static inline aa_state_t match_component(struct aa_profile *profile,
  * @label: label to check access permissions for
  * @stack: whether this is a stacking request
  * @state: state to start match in
- * @subns: whether to do permission checks on components in a subns
+ * @inview: whether to match labels in view or only in scope
  * @request: permissions to request
  * @perms: perms struct to set
  *
@@ -127,7 +127,7 @@ static inline aa_state_t match_component(struct aa_profile *profile,
  */
 static int label_compound_match(struct aa_profile *profile,
                                struct aa_label *label, bool stack,
-                               aa_state_t state, bool subns, u32 request,
+                               aa_state_t state, bool inview, u32 request,
                                struct aa_perms *perms)
 {
        struct aa_ruleset *rules = profile->label.rules[0];
@@ -135,9 +135,9 @@ static int label_compound_match(struct aa_profile *profile,
        struct label_it i;
        struct path_cond cond = { };
 
-       /* find first subcomponent that is visible */
+       /* find first subcomponent that is in view and going to be interated with */
        label_for_each(i, label, tp) {
-               if (!aa_ns_visible(profile->ns, tp->ns, subns))
+               if (!aa_ns_visible(profile->ns, tp->ns, inview))
                        continue;
                state = match_component(profile, tp, stack, state);
                if (!state)
@@ -151,7 +151,7 @@ static int label_compound_match(struct aa_profile *profile,
 
 next:
        label_for_each_cont(i, label, tp) {
-               if (!aa_ns_visible(profile->ns, tp->ns, subns))
+               if (!aa_ns_visible(profile->ns, tp->ns, inview))
                        continue;
                state = aa_dfa_match(rules->file->dfa, state, "//&");
                state = match_component(profile, tp, false, state);
@@ -177,7 +177,7 @@ fail:
  * @label: label to check access permissions for
  * @stack: whether this is a stacking request
  * @start: state to start match in
- * @subns: whether to do permission checks on components in a subns
+ * @inview: whether to match labels in view or only in scope
  * @request: permissions to request
  * @perms: an initialized perms struct to add accumulation to
  *
@@ -189,7 +189,7 @@ fail:
  */
 static int label_components_match(struct aa_profile *profile,
                                  struct aa_label *label, bool stack,
-                                 aa_state_t start, bool subns, u32 request,
+                                 aa_state_t start, bool inview, u32 request,
                                  struct aa_perms *perms)
 {
        struct aa_ruleset *rules = profile->label.rules[0];
@@ -201,7 +201,7 @@ static int label_components_match(struct aa_profile *profile,
 
        /* find first subcomponent to test */
        label_for_each(i, label, tp) {
-               if (!aa_ns_visible(profile->ns, tp->ns, subns))
+               if (!aa_ns_visible(profile->ns, tp->ns, inview))
                        continue;
                state = match_component(profile, tp, stack, start);
                if (!state)
@@ -218,7 +218,7 @@ next:
        aa_apply_modes_to_perms(profile, &tmp);
        aa_perms_accum(perms, &tmp);
        label_for_each_cont(i, label, tp) {
-               if (!aa_ns_visible(profile->ns, tp->ns, subns))
+               if (!aa_ns_visible(profile->ns, tp->ns, inview))
                        continue;
                state = match_component(profile, tp, stack, start);
                if (!state)
@@ -245,26 +245,26 @@ fail:
  * @label: label to match (NOT NULL)
  * @stack: whether this is a stacking request
  * @state: state to start in
- * @subns: whether to match subns components
+ * @inview: whether to match labels in view or only in scope
  * @request: permission request
  * @perms: Returns computed perms (NOT NULL)
  *
  * Returns: the state the match finished in, may be the none matching state
  */
 static int label_match(struct aa_profile *profile, struct aa_label *label,
-                      bool stack, aa_state_t state, bool subns, u32 request,
+                      bool stack, aa_state_t state, bool inview, u32 request,
                       struct aa_perms *perms)
 {
        int error;
 
        *perms = nullperms;
-       error = label_compound_match(profile, label, stack, state, subns,
+       error = label_compound_match(profile, label, stack, state, inview,
                                     request, perms);
        if (!error)
                return error;
 
        *perms = allperms;
-       return label_components_match(profile, label, stack, state, subns,
+       return label_components_match(profile, label, stack, state, inview,
                                      request, perms);
 }
 
@@ -880,14 +880,16 @@ static struct aa_label *handle_onexec(const struct cred *subj_cred,
        AA_BUG(!bprm);
        AA_BUG(!buffer);
 
-       /* TODO: determine how much we want to loosen this */
-       error = fn_for_each_in_ns(label, profile,
+       /* TODO: determine how much we want to loosen this
+        * only check profiles in scope for permission to change at exec
+        */
+       error = fn_for_each_in_scope(label, profile,
                        profile_onexec(subj_cred, profile, onexec, stack,
                                       bprm, buffer, cond, unsafe));
        if (error)
                return ERR_PTR(error);
 
-       new = fn_label_build_in_ns(label, profile, GFP_KERNEL,
+       new = fn_label_build_in_scope(label, profile, GFP_KERNEL,
                        stack ? aa_label_merge(&profile->label, onexec,
                                               GFP_KERNEL)
                              : aa_get_newest_label(onexec),
@@ -897,7 +899,7 @@ static struct aa_label *handle_onexec(const struct cred *subj_cred,
                return new;
 
        /* TODO: get rid of GLOBAL_ROOT_UID */
-       error = fn_for_each_in_ns(label, profile,
+       error = fn_for_each_in_scope(label, profile,
                        aa_audit_file(subj_cred, profile, &nullperms,
                                      OP_CHANGE_ONEXEC,
                                      AA_MAY_ONEXEC, bprm->filename, NULL,
@@ -1123,7 +1125,7 @@ static struct aa_label *change_hat(const struct cred *subj_cred,
        /*find first matching hat */
        for (i = 0; i < count && !hat; i++) {
                name = hats[i];
-               label_for_each_in_ns(it, labels_ns(label), label, profile) {
+               label_for_each_in_scope(it, labels_ns(label), label, profile) {
                        if (sibling && PROFILE_IS_HAT(profile)) {
                                root = aa_get_profile_rcu(&profile->parent);
                        } else if (!sibling && !PROFILE_IS_HAT(profile)) {
@@ -1159,7 +1161,7 @@ outer_continue:
         * change_hat.
         */
        name = NULL;
-       label_for_each_in_ns(it, labels_ns(label), label, profile) {
+       label_for_each_in_scope(it, labels_ns(label), label, profile) {
                if (!list_empty(&profile->base.profiles)) {
                        info = "hat not found";
                        error = -ENOENT;
@@ -1170,7 +1172,7 @@ outer_continue:
        error = -ECHILD;
 
 fail:
-       label_for_each_in_ns(it, labels_ns(label), label, profile) {
+       label_for_each_in_scope(it, labels_ns(label), label, profile) {
                /*
                 * no target as it has failed to be found or built
                 *
@@ -1188,7 +1190,7 @@ fail:
        return ERR_PTR(error);
 
 build:
-       new = fn_label_build_in_ns(label, profile, GFP_KERNEL,
+       new = fn_label_build_in_scope(label, profile, GFP_KERNEL,
                                   build_change_hat(subj_cred, profile, name,
                                                    sibling),
                                   aa_get_label(&profile->label));
@@ -1251,7 +1253,7 @@ int aa_change_hat(const char *hats[], int count, u64 token, int flags)
                bool empty = true;
 
                rcu_read_lock();
-               label_for_each_in_ns(i, labels_ns(label), label, profile) {
+               label_for_each_in_scope(i, labels_ns(label), label, profile) {
                        empty &= list_empty(&profile->base.profiles);
                }
                rcu_read_unlock();
@@ -1338,7 +1340,7 @@ kill:
        perms.kill = AA_MAY_CHANGEHAT;
 
 fail:
-       fn_for_each_in_ns(label, profile,
+       fn_for_each_in_scope(label, profile,
                aa_audit_file(subj_cred, profile, &perms, OP_CHANGE_HAT,
                              AA_MAY_CHANGEHAT, NULL, NULL, target,
                              GLOBAL_ROOT_UID, info, error));
@@ -1446,7 +1448,7 @@ int aa_change_profile(const char *fqname, int flags)
                 */
                stack = true;
                perms.audit = request;
-               (void) fn_for_each_in_ns(label, profile,
+               (void) fn_for_each_in_scope(label, profile,
                                aa_audit_file(subj_cred, profile, &perms, op,
                                              request, auditname, NULL, target,
                                              GLOBAL_ROOT_UID, stack_msg, 0));
@@ -1492,7 +1494,7 @@ int aa_change_profile(const char *fqname, int flags)
         *
         * if (!stack) {
         */
-       error = fn_for_each_in_ns(label, profile,
+       error = fn_for_each_in_scope(label, profile,
                        change_profile_perms_wrapper(op, auditname,
                                                     subj_cred,
                                                     profile, target, stack,
@@ -1506,7 +1508,7 @@ int aa_change_profile(const char *fqname, int flags)
 check:
        /* check if tracing task is allowed to trace target domain */
        error = may_change_ptraced_domain(subj_cred, target, &info);
-       if (error && !fn_for_each_in_ns(label, profile,
+       if (error && !fn_for_each_in_scope(label, profile,
                                        COMPLAIN_MODE(profile)))
                goto audit;
 
@@ -1522,7 +1524,7 @@ check:
 
        /* stacking is always a subset, so only check the nonstack case */
        if (!stack) {
-               new = fn_label_build_in_ns(label, profile, GFP_KERNEL,
+               new = fn_label_build_in_scope(label, profile, GFP_KERNEL,
                                           aa_get_label(target),
                                           aa_get_label(&profile->label));
                /*
@@ -1565,7 +1567,7 @@ check:
        }
 
 audit:
-       error = fn_for_each_in_ns(label, profile,
+       error = fn_for_each_in_scope(label, profile,
                        aa_audit_file(subj_cred,
                                      profile, &perms, op, request, auditname,
                                      NULL, new ? new : target,
index 73ec624fd8c4dc1e77c4fbc86ff7e3845ff81c7b..1c5d1f60f6a7a50a3b970baa832428dc385c3b10 100644 (file)
@@ -80,6 +80,19 @@ int aa_print_debug_params(char *buffer);
 /* Flag indicating whether initialization completed */
 extern int apparmor_initialized;
 
+/* semantic split of scope and view */
+#define aa_in_scope(SUBJ, OBJ)                                         \
+       aa_ns_visible(SUBJ, OBJ, false)
+
+#define aa_in_view(SUBJ, OBJ)                                          \
+       aa_ns_visible(SUBJ, OBJ, true)
+
+#define label_for_each_in_scope(I, NS, L, P)                           \
+       label_for_each_in_ns(I, NS, L, P)
+
+#define fn_for_each_in_scope(L, P, FN)                                 \
+       fn_for_each_in_ns(L, P, FN)
+
 /* fn's in lib */
 const char *skipn_spaces(const char *str, size_t n);
 const char *aa_splitn_fqname(const char *fqname, size_t n, const char **ns_name,
@@ -316,7 +329,7 @@ __done:                                                                     \
 })
 
 
-#define __fn_build_in_ns(NS, P, NS_FN, OTHER_FN)                       \
+#define __fn_build_in_scope(NS, P, NS_FN, OTHER_FN)                    \
 ({                                                                     \
        struct aa_label *__new;                                         \
        if ((P)->ns != (NS))                                            \
@@ -326,10 +339,10 @@ __done:                                                                   \
        (__new);                                                        \
 })
 
-#define fn_label_build_in_ns(L, P, GFP, NS_FN, OTHER_FN)               \
+#define fn_label_build_in_scope(L, P, GFP, NS_FN, OTHER_FN)            \
 ({                                                                     \
        fn_label_build((L), (P), (GFP),                                 \
-               __fn_build_in_ns(labels_ns(L), (P), (NS_FN), (OTHER_FN))); \
+               __fn_build_in_scope(labels_ns(L), (P), (NS_FN), (OTHER_FN))); \
 })
 
 #endif /* __AA_LIB_H */
index 1d3fa5c28d97fc4d2cb367ba754d8745323fbbb2..ef3448ecdf5f2215ddbbd707df05cd8ac75f67eb 100644 (file)
@@ -1274,7 +1274,7 @@ static inline aa_state_t match_component(struct aa_profile *profile,
  * @rules: ruleset to search
  * @label: label to check access permissions for
  * @state: state to start match in
- * @subns: whether to do permission checks on components in a subns
+ * @inview: whether to match labels in view or only in scope
  * @request: permissions to request
  * @perms: perms struct to set
  *
@@ -1287,7 +1287,7 @@ static inline aa_state_t match_component(struct aa_profile *profile,
 static int label_compound_match(struct aa_profile *profile,
                                struct aa_ruleset *rules,
                                struct aa_label *label,
-                               aa_state_t state, bool subns, u32 request,
+                               aa_state_t state, bool inview, u32 request,
                                struct aa_perms *perms)
 {
        struct aa_profile *tp;
@@ -1295,7 +1295,7 @@ static int label_compound_match(struct aa_profile *profile,
 
        /* find first subcomponent that is visible */
        label_for_each(i, label, tp) {
-               if (!aa_ns_visible(profile->ns, tp->ns, subns))
+               if (!aa_ns_visible(profile->ns, tp->ns, inview))
                        continue;
                state = match_component(profile, rules, tp, state);
                if (!state)
@@ -1309,7 +1309,7 @@ static int label_compound_match(struct aa_profile *profile,
 
 next:
        label_for_each_cont(i, label, tp) {
-               if (!aa_ns_visible(profile->ns, tp->ns, subns))
+               if (!aa_ns_visible(profile->ns, tp->ns, inview))
                        continue;
                state = aa_dfa_match(rules->policy->dfa, state, "//&");
                state = match_component(profile, rules, tp, state);
@@ -1330,7 +1330,7 @@ fail:
  * @rules: ruleset to search
  * @label: label to check access permissions for
  * @start: state to start match in
- * @subns: whether to do permission checks on components in a subns
+ * @subns: whether to match labels in view or only in scope
  * @request: permissions to request
  * @perms: an initialized perms struct to add accumulation to
  *
@@ -1343,7 +1343,7 @@ fail:
 static int label_components_match(struct aa_profile *profile,
                                  struct aa_ruleset *rules,
                                  struct aa_label *label, aa_state_t start,
-                                 bool subns, u32 request,
+                                 bool inview, u32 request,
                                  struct aa_perms *perms)
 {
        struct aa_profile *tp;
@@ -1353,7 +1353,7 @@ static int label_components_match(struct aa_profile *profile,
 
        /* find first subcomponent to test */
        label_for_each(i, label, tp) {
-               if (!aa_ns_visible(profile->ns, tp->ns, subns))
+               if (!aa_ns_visible(profile->ns, tp->ns, inview))
                        continue;
                state = match_component(profile, rules, tp, start);
                if (!state)
@@ -1368,7 +1368,7 @@ next:
        tmp = *aa_lookup_perms(rules->policy, state);
        aa_perms_accum(perms, &tmp);
        label_for_each_cont(i, label, tp) {
-               if (!aa_ns_visible(profile->ns, tp->ns, subns))
+               if (!aa_ns_visible(profile->ns, tp->ns, inview))
                        continue;
                state = match_component(profile, rules, tp, start);
                if (!state)
@@ -1393,24 +1393,24 @@ fail:
  * @rules: ruleset to search
  * @label: label to match (NOT NULL)
  * @state: state to start in
- * @subns: whether to match subns components
+ * @subns: whether to match labels in view or only in scope
  * @request: permission request
  * @perms: Returns computed perms (NOT NULL)
  *
  * Returns: the state the match finished in, may be the none matching state
  */
 int aa_label_match(struct aa_profile *profile, struct aa_ruleset *rules,
-                  struct aa_label *label, aa_state_t state, bool subns,
+                  struct aa_label *label, aa_state_t state, bool inview,
                   u32 request, struct aa_perms *perms)
 {
-       aa_state_t tmp = label_compound_match(profile, rules, label, state, subns,
-                                       request, perms);
+       aa_state_t tmp = label_compound_match(profile, rules, label, state,
+                                             inview, request, perms);
        if ((perms->allow & request) == request)
                return 0;
 
        /* failed compound_match try component matches */
        *perms = allperms;
-       return label_components_match(profile, rules, label, state, subns,
+       return label_components_match(profile, rules, label, state, inview,
                                      request, perms);
 }