^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /* SPDX-License-Identifier: GPL-2.0-only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * AppArmor security module
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * This file contains AppArmor lib definitions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * 2017 Canonical Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #ifndef __AA_LIB_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #define __AA_LIB_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/lsm_hooks.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "match.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * DEBUG remains global (no per profile flag) since it is mostly used in sysctl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * which is not related to profile accesses.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define DEBUG_ON (aa_g_debug)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define dbg_printk(__fmt, __args...) pr_debug(__fmt, ##__args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define AA_DEBUG(fmt, args...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) if (DEBUG_ON) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) pr_debug_ratelimited("AppArmor: " fmt, ##args); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define AA_WARN(X) WARN((X), "APPARMOR WARN %s: %s\n", __func__, #X)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define AA_BUG(X, args...) AA_BUG_FMT((X), "" args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #ifdef CONFIG_SECURITY_APPARMOR_DEBUG_ASSERTS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define AA_BUG_FMT(X, fmt, args...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) WARN((X), "AppArmor WARN %s: (" #X "): " fmt, __func__, ##args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define AA_BUG_FMT(X, fmt, args...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define AA_ERROR(fmt, args...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) pr_err_ratelimited("AppArmor: " fmt, ##args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) /* Flag indicating whether initialization completed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) extern int apparmor_initialized;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) /* fn's in lib */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) const char *skipn_spaces(const char *str, size_t n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) char *aa_split_fqname(char *args, char **ns_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) const char *aa_splitn_fqname(const char *fqname, size_t n, const char **ns_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) size_t *ns_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) void aa_info_message(const char *str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) /* Security blob offsets */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) extern struct lsm_blob_sizes apparmor_blob_sizes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * aa_strneq - compare null terminated @str to a non null terminated substring
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) * @str: a null terminated string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) * @sub: a substring, not necessarily null terminated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) * @len: length of @sub to compare
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) * The @str string must be full consumed for this to be considered a match
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) static inline bool aa_strneq(const char *str, const char *sub, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) return !strncmp(str, sub, len) && !str[len];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * aa_dfa_null_transition - step to next state after null character
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * @dfa: the dfa to match against
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * @start: the state of the dfa to start matching in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) * aa_dfa_null_transition transitions to the next state after a null
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) * character which is not used in standard matching and is only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) * used to separate pairs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) static inline unsigned int aa_dfa_null_transition(struct aa_dfa *dfa,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) unsigned int start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) /* the null transition only needs the string's null terminator byte */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) return aa_dfa_next(dfa, start, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) static inline bool path_mediated_fs(struct dentry *dentry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) return !(dentry->d_sb->s_flags & SB_NOUSER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) struct counted_str {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) struct kref count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) char name[];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #define str_to_counted(str) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) ((struct counted_str *)(str - offsetof(struct counted_str, name)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) #define __counted /* atm just a notation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) void aa_str_kref(struct kref *kref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) char *aa_str_alloc(int size, gfp_t gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) static inline __counted char *aa_get_str(__counted char *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) if (str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) kref_get(&(str_to_counted(str)->count));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) return str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) static inline void aa_put_str(__counted char *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) if (str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) kref_put(&str_to_counted(str)->count, aa_str_kref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) /* struct aa_policy - common part of both namespaces and profiles
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) * @name: name of the object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) * @hname - The hierarchical name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) * @list: list policy object is on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) * @profiles: head of the profiles list contained in the object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) struct aa_policy {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) __counted char *hname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) struct list_head list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) struct list_head profiles;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) * basename - find the last component of an hname
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) * @name: hname to find the base profile name component of (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) * Returns: the tail (base profile name) name component of an hname
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) static inline const char *basename(const char *hname)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) char *split;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) hname = strim((char *)hname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) for (split = strstr(hname, "//"); split; split = strstr(hname, "//"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) hname = split + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) return hname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) * __policy_find - find a policy by @name on a policy list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) * @head: list to search (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) * @name: name to search for (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) * Requires: rcu_read_lock be held
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) * Returns: unrefcounted policy that match @name or NULL if not found
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) static inline struct aa_policy *__policy_find(struct list_head *head,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) struct aa_policy *policy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) list_for_each_entry_rcu(policy, head, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) if (!strcmp(policy->name, name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) return policy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) * __policy_strn_find - find a policy that's name matches @len chars of @str
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) * @head: list to search (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) * @str: string to search for (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) * @len: length of match required
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) * Requires: rcu_read_lock be held
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) * Returns: unrefcounted policy that match @str or NULL if not found
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) * if @len == strlen(@strlen) then this is equiv to __policy_find
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) * other wise it allows searching for policy by a partial match of name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) static inline struct aa_policy *__policy_strn_find(struct list_head *head,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) const char *str, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) struct aa_policy *policy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) list_for_each_entry_rcu(policy, head, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) if (aa_strneq(policy->name, str, len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) return policy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) bool aa_policy_init(struct aa_policy *policy, const char *prefix,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) const char *name, gfp_t gfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) void aa_policy_destroy(struct aa_policy *policy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) * fn_label_build - abstract out the build of a label transition
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) * @L: label the transition is being computed for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) * @P: profile parameter derived from L by this macro, can be passed to FN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) * @GFP: memory allocation type to use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) * @FN: fn to call for each profile transition. @P is set to the profile
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) * Returns: new label on success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) * ERR_PTR if build @FN fails
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) * NULL if label_build fails due to low memory conditions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) * @FN must return a label or ERR_PTR on failure. NULL is not allowed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) #define fn_label_build(L, P, GFP, FN) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) ({ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) __label__ __cleanup, __done; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) struct aa_label *__new_; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) if ((L)->size > 1) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) /* TODO: add cache of transitions already done */ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) struct label_it __i; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) int __j, __k, __count; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) DEFINE_VEC(label, __lvec); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) DEFINE_VEC(profile, __pvec); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) if (vec_setup(label, __lvec, (L)->size, (GFP))) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) __new_ = NULL; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) goto __done; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) __j = 0; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) label_for_each(__i, (L), (P)) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) __new_ = (FN); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) AA_BUG(!__new_); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) if (IS_ERR(__new_)) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) goto __cleanup; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) __lvec[__j++] = __new_; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) for (__j = __count = 0; __j < (L)->size; __j++) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) __count += __lvec[__j]->size; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) if (!vec_setup(profile, __pvec, __count, (GFP))) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) for (__j = __k = 0; __j < (L)->size; __j++) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) label_for_each(__i, __lvec[__j], (P)) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) __pvec[__k++] = aa_get_profile(P); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) __count -= aa_vec_unique(__pvec, __count, 0); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) if (__count > 1) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) __new_ = aa_vec_find_or_create_label(__pvec,\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) __count, (GFP)); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) /* only fails if out of Mem */ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) if (!__new_) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) __new_ = NULL; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) } else \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) __new_ = aa_get_label(&__pvec[0]->label); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) vec_cleanup(profile, __pvec, __count); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) } else \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) __new_ = NULL; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) __cleanup: \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) vec_cleanup(label, __lvec, (L)->size); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) } else { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) (P) = labels_profile(L); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) __new_ = (FN); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) __done: \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) if (!__new_) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) AA_DEBUG("label build failed\n"); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) (__new_); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) })
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) #define __fn_build_in_ns(NS, P, NS_FN, OTHER_FN) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) ({ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) struct aa_label *__new; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) if ((P)->ns != (NS)) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) __new = (OTHER_FN); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) else \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) __new = (NS_FN); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) (__new); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) })
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) #define fn_label_build_in_ns(L, P, GFP, NS_FN, OTHER_FN) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) ({ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) fn_label_build((L), (P), (GFP), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) __fn_build_in_ns(labels_ns(L), (P), (NS_FN), (OTHER_FN))); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) })
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) #endif /* __AA_LIB_H */