Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-only */
0002 /*
0003  * AppArmor security module
0004  *
0005  * This file contains AppArmor lib definitions
0006  *
0007  * 2017 Canonical Ltd.
0008  */
0009 
0010 #ifndef __AA_LIB_H
0011 #define __AA_LIB_H
0012 
0013 #include <linux/slab.h>
0014 #include <linux/fs.h>
0015 #include <linux/lsm_hooks.h>
0016 
0017 #include "match.h"
0018 
0019 /*
0020  * DEBUG remains global (no per profile flag) since it is mostly used in sysctl
0021  * which is not related to profile accesses.
0022  */
0023 
0024 #define DEBUG_ON (aa_g_debug)
0025 /*
0026  * split individual debug cases out in preparation for finer grained
0027  * debug controls in the future.
0028  */
0029 #define AA_DEBUG_LABEL DEBUG_ON
0030 #define dbg_printk(__fmt, __args...) pr_debug(__fmt, ##__args)
0031 #define AA_DEBUG(fmt, args...)                      \
0032     do {                                \
0033         if (DEBUG_ON)                       \
0034             pr_debug_ratelimited("AppArmor: " fmt, ##args); \
0035     } while (0)
0036 
0037 #define AA_WARN(X) WARN((X), "APPARMOR WARN %s: %s\n", __func__, #X)
0038 
0039 #define AA_BUG(X, args...)                          \
0040     do {                                    \
0041         _Pragma("GCC diagnostic ignored \"-Wformat-zero-length\""); \
0042         AA_BUG_FMT((X), "" args);                   \
0043         _Pragma("GCC diagnostic warning \"-Wformat-zero-length\""); \
0044     } while (0)
0045 #ifdef CONFIG_SECURITY_APPARMOR_DEBUG_ASSERTS
0046 #define AA_BUG_FMT(X, fmt, args...)                 \
0047     WARN((X), "AppArmor WARN %s: (" #X "): " fmt, __func__, ##args)
0048 #else
0049 #define AA_BUG_FMT(X, fmt, args...) no_printk(fmt, ##args)
0050 #endif
0051 
0052 #define AA_ERROR(fmt, args...)                      \
0053     pr_err_ratelimited("AppArmor: " fmt, ##args)
0054 
0055 /* Flag indicating whether initialization completed */
0056 extern int apparmor_initialized;
0057 
0058 /* fn's in lib */
0059 const char *skipn_spaces(const char *str, size_t n);
0060 char *aa_split_fqname(char *args, char **ns_name);
0061 const char *aa_splitn_fqname(const char *fqname, size_t n, const char **ns_name,
0062                  size_t *ns_len);
0063 void aa_info_message(const char *str);
0064 
0065 /* Security blob offsets */
0066 extern struct lsm_blob_sizes apparmor_blob_sizes;
0067 
0068 /**
0069  * aa_strneq - compare null terminated @str to a non null terminated substring
0070  * @str: a null terminated string
0071  * @sub: a substring, not necessarily null terminated
0072  * @len: length of @sub to compare
0073  *
0074  * The @str string must be full consumed for this to be considered a match
0075  */
0076 static inline bool aa_strneq(const char *str, const char *sub, int len)
0077 {
0078     return !strncmp(str, sub, len) && !str[len];
0079 }
0080 
0081 /**
0082  * aa_dfa_null_transition - step to next state after null character
0083  * @dfa: the dfa to match against
0084  * @start: the state of the dfa to start matching in
0085  *
0086  * aa_dfa_null_transition transitions to the next state after a null
0087  * character which is not used in standard matching and is only
0088  * used to separate pairs.
0089  */
0090 static inline unsigned int aa_dfa_null_transition(struct aa_dfa *dfa,
0091                           unsigned int start)
0092 {
0093     /* the null transition only needs the string's null terminator byte */
0094     return aa_dfa_next(dfa, start, 0);
0095 }
0096 
0097 static inline bool path_mediated_fs(struct dentry *dentry)
0098 {
0099     return !(dentry->d_sb->s_flags & SB_NOUSER);
0100 }
0101 
0102 
0103 struct counted_str {
0104     struct kref count;
0105     char name[];
0106 };
0107 
0108 #define str_to_counted(str) \
0109     ((struct counted_str *)(str - offsetof(struct counted_str, name)))
0110 
0111 #define __counted   /* atm just a notation */
0112 
0113 void aa_str_kref(struct kref *kref);
0114 char *aa_str_alloc(int size, gfp_t gfp);
0115 
0116 
0117 static inline __counted char *aa_get_str(__counted char *str)
0118 {
0119     if (str)
0120         kref_get(&(str_to_counted(str)->count));
0121 
0122     return str;
0123 }
0124 
0125 static inline void aa_put_str(__counted char *str)
0126 {
0127     if (str)
0128         kref_put(&str_to_counted(str)->count, aa_str_kref);
0129 }
0130 
0131 
0132 /* struct aa_policy - common part of both namespaces and profiles
0133  * @name: name of the object
0134  * @hname - The hierarchical name
0135  * @list: list policy object is on
0136  * @profiles: head of the profiles list contained in the object
0137  */
0138 struct aa_policy {
0139     const char *name;
0140     __counted char *hname;
0141     struct list_head list;
0142     struct list_head profiles;
0143 };
0144 
0145 /**
0146  * basename - find the last component of an hname
0147  * @name: hname to find the base profile name component of  (NOT NULL)
0148  *
0149  * Returns: the tail (base profile name) name component of an hname
0150  */
0151 static inline const char *basename(const char *hname)
0152 {
0153     char *split;
0154 
0155     hname = strim((char *)hname);
0156     for (split = strstr(hname, "//"); split; split = strstr(hname, "//"))
0157         hname = split + 2;
0158 
0159     return hname;
0160 }
0161 
0162 /**
0163  * __policy_find - find a policy by @name on a policy list
0164  * @head: list to search  (NOT NULL)
0165  * @name: name to search for  (NOT NULL)
0166  *
0167  * Requires: rcu_read_lock be held
0168  *
0169  * Returns: unrefcounted policy that match @name or NULL if not found
0170  */
0171 static inline struct aa_policy *__policy_find(struct list_head *head,
0172                           const char *name)
0173 {
0174     struct aa_policy *policy;
0175 
0176     list_for_each_entry_rcu(policy, head, list) {
0177         if (!strcmp(policy->name, name))
0178             return policy;
0179     }
0180     return NULL;
0181 }
0182 
0183 /**
0184  * __policy_strn_find - find a policy that's name matches @len chars of @str
0185  * @head: list to search  (NOT NULL)
0186  * @str: string to search for  (NOT NULL)
0187  * @len: length of match required
0188  *
0189  * Requires: rcu_read_lock be held
0190  *
0191  * Returns: unrefcounted policy that match @str or NULL if not found
0192  *
0193  * if @len == strlen(@strlen) then this is equiv to __policy_find
0194  * other wise it allows searching for policy by a partial match of name
0195  */
0196 static inline struct aa_policy *__policy_strn_find(struct list_head *head,
0197                         const char *str, int len)
0198 {
0199     struct aa_policy *policy;
0200 
0201     list_for_each_entry_rcu(policy, head, list) {
0202         if (aa_strneq(policy->name, str, len))
0203             return policy;
0204     }
0205 
0206     return NULL;
0207 }
0208 
0209 bool aa_policy_init(struct aa_policy *policy, const char *prefix,
0210             const char *name, gfp_t gfp);
0211 void aa_policy_destroy(struct aa_policy *policy);
0212 
0213 
0214 /*
0215  * fn_label_build - abstract out the build of a label transition
0216  * @L: label the transition is being computed for
0217  * @P: profile parameter derived from L by this macro, can be passed to FN
0218  * @GFP: memory allocation type to use
0219  * @FN: fn to call for each profile transition. @P is set to the profile
0220  *
0221  * Returns: new label on success
0222  *          ERR_PTR if build @FN fails
0223  *          NULL if label_build fails due to low memory conditions
0224  *
0225  * @FN must return a label or ERR_PTR on failure. NULL is not allowed
0226  */
0227 #define fn_label_build(L, P, GFP, FN)                   \
0228 ({                                  \
0229     __label__ __cleanup, __done;                    \
0230     struct aa_label *__new_;                    \
0231                                     \
0232     if ((L)->size > 1) {                        \
0233         /* TODO: add cache of transitions already done */   \
0234         struct label_it __i;                    \
0235         int __j, __k, __count;                  \
0236         DEFINE_VEC(label, __lvec);              \
0237         DEFINE_VEC(profile, __pvec);                \
0238         if (vec_setup(label, __lvec, (L)->size, (GFP))) {   \
0239             __new_ = NULL;                  \
0240             goto __done;                    \
0241         }                           \
0242         __j = 0;                        \
0243         label_for_each(__i, (L), (P)) {             \
0244             __new_ = (FN);                  \
0245             AA_BUG(!__new_);                \
0246             if (IS_ERR(__new_))             \
0247                 goto __cleanup;             \
0248             __lvec[__j++] = __new_;             \
0249         }                           \
0250         for (__j = __count = 0; __j < (L)->size; __j++)     \
0251             __count += __lvec[__j]->size;           \
0252         if (!vec_setup(profile, __pvec, __count, (GFP))) {  \
0253             for (__j = __k = 0; __j < (L)->size; __j++) {   \
0254                 label_for_each(__i, __lvec[__j], (P))   \
0255                     __pvec[__k++] = aa_get_profile(P); \
0256             }                       \
0257             __count -= aa_vec_unique(__pvec, __count, 0);   \
0258             if (__count > 1) {              \
0259                 __new_ = aa_vec_find_or_create_label(__pvec,\
0260                              __count, (GFP));   \
0261                 /* only fails if out of Mem */      \
0262                 if (!__new_)                \
0263                     __new_ = NULL;          \
0264             } else                      \
0265                 __new_ = aa_get_label(&__pvec[0]->label); \
0266             vec_cleanup(profile, __pvec, __count);      \
0267         } else                          \
0268             __new_ = NULL;                  \
0269 __cleanup:                              \
0270         vec_cleanup(label, __lvec, (L)->size);          \
0271     } else {                            \
0272         (P) = labels_profile(L);                \
0273         __new_ = (FN);                      \
0274     }                               \
0275 __done:                                 \
0276     if (!__new_)                            \
0277         AA_DEBUG("label build failed\n");           \
0278     (__new_);                           \
0279 })
0280 
0281 
0282 #define __fn_build_in_ns(NS, P, NS_FN, OTHER_FN)            \
0283 ({                                  \
0284     struct aa_label *__new;                     \
0285     if ((P)->ns != (NS))                        \
0286         __new = (OTHER_FN);                 \
0287     else                                \
0288         __new = (NS_FN);                    \
0289     (__new);                            \
0290 })
0291 
0292 #define fn_label_build_in_ns(L, P, GFP, NS_FN, OTHER_FN)        \
0293 ({                                  \
0294     fn_label_build((L), (P), (GFP),                 \
0295         __fn_build_in_ns(labels_ns(L), (P), (NS_FN), (OTHER_FN))); \
0296 })
0297 
0298 #endif /* __AA_LIB_H */