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