cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

lib.h (7997B)


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