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