This repository has been archived by the owner on Oct 4, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 20
/
apparmor-support.c
132 lines (124 loc) · 4.06 KB
/
apparmor-support.c
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
/*
* Copyright (C) 2016 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "apparmor-support.h"
#include <string.h>
#include <errno.h>
#ifdef HAVE_APPARMOR
#include <sys/apparmor.h>
#endif // ifdef HAVE_APPARMOR
#include "cleanup-funcs.h"
#include "utils.h"
// NOTE: Those constants map exactly what apparmor is returning and cannot be
// changed without breaking apparmor functionality.
#define SC_AA_ENFORCE_STR "enforce"
#define SC_AA_COMPLAIN_STR "complain"
#define SC_AA_MIXED_STR "mixed"
#define SC_AA_UNCONFINED_STR "unconfined"
void sc_init_apparmor_support(struct sc_apparmor *apparmor)
{
#ifdef HAVE_APPARMOR
// Use aa_is_enabled() to see if apparmor is available in the kernel and
// enabled at boot time. If it isn't log a diagnostic message and assume
// we're not confined.
if (aa_is_enabled() != true) {
switch (errno) {
case ENOSYS:
debug
("apparmor extensions to the system are not available");
break;
case ECANCELED:
debug
("apparmor is available on the system but has been disabled at boot");
break;
case ENOENT:
debug
("apparmor is available but the interface but the interface is not available");
case EPERM:
// NOTE: fall-through
case EACCES:
debug
("insufficient permissions to determine if apparmor is enabled");
break;
default:
debug("apparmor is not enabled: %s", strerror(errno));
break;
}
apparmor->is_confined = false;
apparmor->mode = SC_AA_NOT_APPLICABLE;
return;
}
// Use aa_getcon() to check the label of the current process and
// confinement type. Note that the returned label must be released with
// free() but the mode is a constant string that must not be freed.
char *label __attribute__ ((cleanup(sc_cleanup_string))) = NULL;
char *mode = NULL;
if (aa_getcon(&label, &mode) < 0) {
die("cannot query current apparmor profile");
}
// The label has a special value "unconfined" that is applied to all
// processes without a dedicated profile. If that label is used then the
// current process is not confined. All other labels imply confinement.
if (label != NULL && strcmp(label, SC_AA_UNCONFINED_STR) == 0) {
apparmor->is_confined = false;
} else {
apparmor->is_confined = true;
}
// There are several possible results for the confinement type (mode) that
// are checked for below.
if (mode != NULL && strcmp(mode, SC_AA_COMPLAIN_STR) == 0) {
apparmor->mode = SC_AA_COMPLAIN;
} else if (mode != NULL && strcmp(mode, SC_AA_ENFORCE_STR) == 0) {
apparmor->mode = SC_AA_ENFORCE;
} else if (mode != NULL && strcmp(mode, SC_AA_MIXED_STR) == 0) {
apparmor->mode = SC_AA_MIXED;
} else {
apparmor->mode = SC_AA_INVALID;
}
#else
apparmor->mode = SC_AA_NOT_APPLICABLE;
apparmor->is_confined = false;
#endif // ifdef HAVE_APPARMOR
}
void
sc_maybe_aa_change_onexec(struct sc_apparmor *apparmor, const char *profile)
{
#ifdef HAVE_APPARMOR
debug("requesting changing of apparmor profile on next exec to %s",
profile);
if (aa_change_onexec(profile) < 0) {
if (secure_getenv("SNAPPY_LAUNCHER_INSIDE_TESTS") == NULL) {
die("cannot change profile for the next exec call");
}
}
#endif // ifdef HAVE_APPARMOR
}
void
sc_maybe_aa_change_hat(struct sc_apparmor *apparmor,
const char *subprofile, unsigned long magic_token)
{
#ifdef HAVE_APPARMOR
if (apparmor->is_confined) {
debug("changing apparmor hat to %s", subprofile);
if (aa_change_hat(subprofile, magic_token) < 0) {
die("cannot change apparmor hat");
}
}
#endif // ifdef HAVE_APPARMOR
}