Linux Audio

Check our new training course

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