Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/security/apparmor/context.c
10814 views
1
/*
2
* AppArmor security module
3
*
4
* This file contains AppArmor functions used to manipulate object security
5
* contexts.
6
*
7
* Copyright (C) 1998-2008 Novell/SUSE
8
* Copyright 2009-2010 Canonical Ltd.
9
*
10
* This program is free software; you can redistribute it and/or
11
* modify it under the terms of the GNU General Public License as
12
* published by the Free Software Foundation, version 2 of the
13
* License.
14
*
15
*
16
* AppArmor sets confinement on every task, via the the aa_task_cxt and
17
* the aa_task_cxt.profile, both of which are required and are not allowed
18
* to be NULL. The aa_task_cxt is not reference counted and is unique
19
* to each cred (which is reference count). The profile pointed to by
20
* the task_cxt is reference counted.
21
*
22
* TODO
23
* If a task uses change_hat it currently does not return to the old
24
* cred or task context but instead creates a new one. Ideally the task
25
* should return to the previous cred if it has not been modified.
26
*
27
*/
28
29
#include "include/context.h"
30
#include "include/policy.h"
31
32
/**
33
* aa_alloc_task_context - allocate a new task_cxt
34
* @flags: gfp flags for allocation
35
*
36
* Returns: allocated buffer or NULL on failure
37
*/
38
struct aa_task_cxt *aa_alloc_task_context(gfp_t flags)
39
{
40
return kzalloc(sizeof(struct aa_task_cxt), flags);
41
}
42
43
/**
44
* aa_free_task_context - free a task_cxt
45
* @cxt: task_cxt to free (MAYBE NULL)
46
*/
47
void aa_free_task_context(struct aa_task_cxt *cxt)
48
{
49
if (cxt) {
50
aa_put_profile(cxt->profile);
51
aa_put_profile(cxt->previous);
52
aa_put_profile(cxt->onexec);
53
54
kzfree(cxt);
55
}
56
}
57
58
/**
59
* aa_dup_task_context - duplicate a task context, incrementing reference counts
60
* @new: a blank task context (NOT NULL)
61
* @old: the task context to copy (NOT NULL)
62
*/
63
void aa_dup_task_context(struct aa_task_cxt *new, const struct aa_task_cxt *old)
64
{
65
*new = *old;
66
aa_get_profile(new->profile);
67
aa_get_profile(new->previous);
68
aa_get_profile(new->onexec);
69
}
70
71
/**
72
* aa_replace_current_profile - replace the current tasks profiles
73
* @profile: new profile (NOT NULL)
74
*
75
* Returns: 0 or error on failure
76
*/
77
int aa_replace_current_profile(struct aa_profile *profile)
78
{
79
struct aa_task_cxt *cxt = current_cred()->security;
80
struct cred *new;
81
BUG_ON(!profile);
82
83
if (cxt->profile == profile)
84
return 0;
85
86
new = prepare_creds();
87
if (!new)
88
return -ENOMEM;
89
90
cxt = new->security;
91
if (unconfined(profile) || (cxt->profile->ns != profile->ns)) {
92
/* if switching to unconfined or a different profile namespace
93
* clear out context state
94
*/
95
aa_put_profile(cxt->previous);
96
aa_put_profile(cxt->onexec);
97
cxt->previous = NULL;
98
cxt->onexec = NULL;
99
cxt->token = 0;
100
}
101
/* be careful switching cxt->profile, when racing replacement it
102
* is possible that cxt->profile->replacedby is the reference keeping
103
* @profile valid, so make sure to get its reference before dropping
104
* the reference on cxt->profile */
105
aa_get_profile(profile);
106
aa_put_profile(cxt->profile);
107
cxt->profile = profile;
108
109
commit_creds(new);
110
return 0;
111
}
112
113
/**
114
* aa_set_current_onexec - set the tasks change_profile to happen onexec
115
* @profile: system profile to set at exec (MAYBE NULL to clear value)
116
*
117
* Returns: 0 or error on failure
118
*/
119
int aa_set_current_onexec(struct aa_profile *profile)
120
{
121
struct aa_task_cxt *cxt;
122
struct cred *new = prepare_creds();
123
if (!new)
124
return -ENOMEM;
125
126
cxt = new->security;
127
aa_get_profile(profile);
128
aa_put_profile(cxt->onexec);
129
cxt->onexec = profile;
130
131
commit_creds(new);
132
return 0;
133
}
134
135
/**
136
* aa_set_current_hat - set the current tasks hat
137
* @profile: profile to set as the current hat (NOT NULL)
138
* @token: token value that must be specified to change from the hat
139
*
140
* Do switch of tasks hat. If the task is currently in a hat
141
* validate the token to match.
142
*
143
* Returns: 0 or error on failure
144
*/
145
int aa_set_current_hat(struct aa_profile *profile, u64 token)
146
{
147
struct aa_task_cxt *cxt;
148
struct cred *new = prepare_creds();
149
if (!new)
150
return -ENOMEM;
151
BUG_ON(!profile);
152
153
cxt = new->security;
154
if (!cxt->previous) {
155
/* transfer refcount */
156
cxt->previous = cxt->profile;
157
cxt->token = token;
158
} else if (cxt->token == token) {
159
aa_put_profile(cxt->profile);
160
} else {
161
/* previous_profile && cxt->token != token */
162
abort_creds(new);
163
return -EACCES;
164
}
165
cxt->profile = aa_get_profile(aa_newest_version(profile));
166
/* clear exec on switching context */
167
aa_put_profile(cxt->onexec);
168
cxt->onexec = NULL;
169
170
commit_creds(new);
171
return 0;
172
}
173
174
/**
175
* aa_restore_previous_profile - exit from hat context restoring the profile
176
* @token: the token that must be matched to exit hat context
177
*
178
* Attempt to return out of a hat to the previous profile. The token
179
* must match the stored token value.
180
*
181
* Returns: 0 or error of failure
182
*/
183
int aa_restore_previous_profile(u64 token)
184
{
185
struct aa_task_cxt *cxt;
186
struct cred *new = prepare_creds();
187
if (!new)
188
return -ENOMEM;
189
190
cxt = new->security;
191
if (cxt->token != token) {
192
abort_creds(new);
193
return -EACCES;
194
}
195
/* ignore restores when there is no saved profile */
196
if (!cxt->previous) {
197
abort_creds(new);
198
return 0;
199
}
200
201
aa_put_profile(cxt->profile);
202
cxt->profile = aa_newest_version(cxt->previous);
203
BUG_ON(!cxt->profile);
204
if (unlikely(cxt->profile != cxt->previous)) {
205
aa_get_profile(cxt->profile);
206
aa_put_profile(cxt->previous);
207
}
208
/* clear exec && prev information when restoring to previous context */
209
cxt->previous = NULL;
210
cxt->token = 0;
211
aa_put_profile(cxt->onexec);
212
cxt->onexec = NULL;
213
214
commit_creds(new);
215
return 0;
216
}
217
218