summaryrefslogtreecommitdiffstats
path: root/security/apparmor/include/perms.h
blob: 0f7e913c3fc21428afeeb73f5551cf85ebaea55a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * AppArmor security module
 *
 * This file contains AppArmor basic permission sets definitions.
 *
 * Copyright 2017 Canonical Ltd.
 */

#ifndef __AA_PERM_H
#define __AA_PERM_H

#include <linux/fs.h>
#include "label.h"

#define AA_MAY_EXEC		MAY_EXEC
#define AA_MAY_WRITE		MAY_WRITE
#define AA_MAY_READ		MAY_READ
#define AA_MAY_APPEND		MAY_APPEND

#define AA_MAY_CREATE		0x0010
#define AA_MAY_DELETE		0x0020
#define AA_MAY_OPEN		0x0040
#define AA_MAY_RENAME		0x0080		/* pair */

#define AA_MAY_SETATTR		0x0100		/* meta write */
#define AA_MAY_GETATTR		0x0200		/* meta read */
#define AA_MAY_SETCRED		0x0400		/* security cred/attr */
#define AA_MAY_GETCRED		0x0800

#define AA_MAY_CHMOD		0x1000		/* pair */
#define AA_MAY_CHOWN		0x2000		/* pair */
#define AA_MAY_CHGRP		0x4000		/* pair */
#define AA_MAY_LOCK		0x8000		/* LINK_SUBSET overlaid */

#define AA_EXEC_MMAP		0x00010000
#define AA_MAY_MPROT		0x00020000	/* extend conditions */
#define AA_MAY_LINK		0x00040000	/* pair */
#define AA_MAY_SNAPSHOT		0x00080000	/* pair */

#define AA_MAY_DELEGATE
#define AA_CONT_MATCH		0x08000000

#define AA_MAY_STACK		0x10000000
#define AA_MAY_ONEXEC		0x20000000 /* either stack or change_profile */
#define AA_MAY_CHANGE_PROFILE	0x40000000
#define AA_MAY_CHANGEHAT	0x80000000

#define AA_LINK_SUBSET		AA_MAY_LOCK	/* overlaid */

#define AA_MAY_CREATE_SQPOLL   AA_MAY_CREATE
#define AA_MAY_OVERRIDE_CRED   AA_MAY_APPEND
#define AA_URING_PERM_MASK     (AA_MAY_OVERRIDE_CRED | AA_MAY_CREATE_SQPOLL)

#define PERMS_CHRS_MASK (MAY_READ | MAY_WRITE | AA_MAY_CREATE |		\
			 AA_MAY_DELETE | AA_MAY_LINK | AA_MAY_LOCK |	\
			 AA_MAY_EXEC | AA_EXEC_MMAP | AA_MAY_APPEND)

#define PERMS_NAMES_MASK (PERMS_CHRS_MASK | AA_MAY_OPEN | AA_MAY_RENAME |     \
			  AA_MAY_SETATTR | AA_MAY_GETATTR | AA_MAY_SETCRED | \
			  AA_MAY_GETCRED | AA_MAY_CHMOD | AA_MAY_CHOWN | \
			  AA_MAY_CHGRP | AA_MAY_MPROT | AA_MAY_SNAPSHOT | \
			  AA_MAY_STACK | AA_MAY_ONEXEC |		\
			  AA_MAY_CHANGE_PROFILE | AA_MAY_CHANGEHAT)

extern const char aa_file_perm_chrs[];
extern const char *aa_file_perm_names[];

struct aa_perms {
	u32 allow;
	u32 deny;	/* explicit deny, or conflict if allow also set */

	u32 subtree;	/* allow perm on full subtree only when allow is set */
	u32 cond;	/* set only when ~allow and ~deny */

	u32 kill;	/* set only when ~allow | deny */
	u32 complain;	/* accumulates only used when ~allow & ~deny */
	u32 prompt;	/* accumulates only used when ~allow & ~deny */

	u32 audit;	/* set only when allow is set */
	u32 quiet;	/* set only when ~allow | deny */
	u32 hide;	/* set only when  ~allow | deny */


	u32 xindex;
	u32 tag;	/* tag string index, if present */
	u32 label;	/* label string index, if present */
};

/*
 * Indexes are broken into a 24 bit index and 8 bit flag.
 * For the index to be valid there must be a value in the flag
 */
#define AA_INDEX_MASK			0x00ffffff
#define AA_INDEX_FLAG_MASK		0xff000000
#define AA_INDEX_NONE			0

#define ALL_PERMS_MASK 0xffffffff
extern struct aa_perms nullperms;
extern struct aa_perms allperms;

/**
 * aa_perms_accum_raw - accumulate perms with out masking off overlapping perms
 * @accum - perms struct to accumulate into
 * @addend - perms struct to add to @accum
 */
static inline void aa_perms_accum_raw(struct aa_perms *accum,
				      struct aa_perms *addend)
{
	accum->deny |= addend->deny;
	accum->allow &= addend->allow & ~addend->deny;
	accum->audit |= addend->audit & addend->allow;
	accum->quiet &= addend->quiet & ~addend->allow;
	accum->kill |= addend->kill & ~addend->allow;
	accum->complain |= addend->complain & ~addend->allow & ~addend->deny;
	accum->cond |= addend->cond & ~addend->allow & ~addend->deny;
	accum->hide &= addend->hide & ~addend->allow;
	accum->prompt |= addend->prompt & ~addend->allow & ~addend->deny;
	accum->subtree |= addend->subtree & ~addend->deny;

	if (!accum->xindex)
		accum->xindex = addend->xindex;
	if (!accum->tag)
		accum->tag = addend->tag;
	if (!accum->label)
		accum->label = addend->label;
}

/**
 * aa_perms_accum - accumulate perms, masking off overlapping perms
 * @accum - perms struct to accumulate into
 * @addend - perms struct to add to @accum
 */
static inline void aa_perms_accum(struct aa_perms *accum,
				  struct aa_perms *addend)
{
	accum->deny |= addend->deny;
	accum->allow &= addend->allow & ~accum->deny;
	accum->audit |= addend->audit & accum->allow;
	accum->quiet &= addend->quiet & ~accum->allow;
	accum->kill |= addend->kill & ~accum->allow;
	accum->complain |= addend->complain & ~accum->allow & ~accum->deny;
	accum->cond |= addend->cond & ~accum->allow & ~accum->deny;
	accum->hide &= addend->hide & ~accum->allow;
	accum->prompt |= addend->prompt & ~accum->allow & ~accum->deny;
	accum->subtree &= addend->subtree & ~accum->deny;

	if (!accum->xindex)
		accum->xindex = addend->xindex;
	if (!accum->tag)
		accum->tag = addend->tag;
	if (!accum->label)
		accum->label = addend->label;
}

#define xcheck(FN1, FN2)	\
({				\
	int e, error = FN1;	\
	e = FN2;		\
	if (e)			\
		error = e;	\
	error;			\
})


/*
 * TODO: update for labels pointing to labels instead of profiles
 * TODO: optimize the walk, currently does subwalk of L2 for each P in L1
 * gah this doesn't allow for label compound check!!!!
 */
#define xcheck_ns_profile_profile(P1, P2, FN, args...)		\
({								\
	int ____e = 0;						\
	if (P1->ns == P2->ns)					\
		____e = FN((P1), (P2), args);			\
	(____e);						\
})

#define xcheck_ns_profile_label(P, L, FN, args...)		\
({								\
	struct aa_profile *__p2;				\
	fn_for_each((L), __p2,					\
		    xcheck_ns_profile_profile((P), __p2, (FN), args));	\
})

#define xcheck_ns_labels(L1, L2, FN, args...)			\
({								\
	struct aa_profile *__p1;				\
	fn_for_each((L1), __p1, FN(__p1, (L2), args));		\
})

/* Do the cross check but applying FN at the profiles level */
#define xcheck_labels_profiles(L1, L2, FN, args...)		\
	xcheck_ns_labels((L1), (L2), xcheck_ns_profile_label, (FN), args)

#define xcheck_labels(L1, L2, P, FN1, FN2)			\
	xcheck(fn_for_each((L1), (P), (FN1)), fn_for_each((L2), (P), (FN2)))


extern struct aa_perms default_perms;


void aa_perm_mask_to_str(char *str, size_t str_size, const char *chrs,
			 u32 mask);
void aa_audit_perm_names(struct audit_buffer *ab, const char * const *names,
			 u32 mask);
void aa_audit_perm_mask(struct audit_buffer *ab, u32 mask, const char *chrs,
			u32 chrsmask, const char * const *names, u32 namesmask);
void aa_apply_modes_to_perms(struct aa_profile *profile,
			     struct aa_perms *perms);
void aa_perms_accum(struct aa_perms *accum, struct aa_perms *addend);
void aa_perms_accum_raw(struct aa_perms *accum, struct aa_perms *addend);
void aa_profile_match_label(struct aa_profile *profile,
			    struct aa_ruleset *rules, struct aa_label *label,
			    int type, u32 request, struct aa_perms *perms);
int aa_profile_label_perm(struct aa_profile *profile, struct aa_profile *target,
			  u32 request, int type, u32 *deny,
			  struct apparmor_audit_data *ad);
int aa_check_perms(struct aa_profile *profile, struct aa_perms *perms,
		   u32 request, struct apparmor_audit_data *ad,
		   void (*cb)(struct audit_buffer *, void *));
#endif /* __AA_PERM_H */