3 * Copyright © 2012 Serge Hallyn <serge.hallyn@ubuntu.com>.
4 * Copyright © 2012 Canonical Ltd.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 #include <sys/types.h>
27 #include <sys/mount.h>
28 #include <sys/apparmor.h>
33 lxc_log_define(lxc_apparmor
, lxc
);
35 /* set by lsm_apparmor_drv_init if true */
36 static int aa_enabled
= 0;
38 #define AA_DEF_PROFILE "lxc-container-default"
39 #define AA_MOUNT_RESTR "/sys/kernel/security/apparmor/features/mount/mask"
40 #define AA_ENABLED_FILE "/sys/module/apparmor/parameters/enabled"
42 /* aa_getcon is not working right now. Use our hand-rolled version below */
43 static int apparmor_enabled(void)
50 ret
= stat(AA_MOUNT_RESTR
, &statbuf
);
53 fin
= fopen(AA_ENABLED_FILE
, "r");
56 ret
= fscanf(fin
, "%c", &e
);
58 if (ret
== 1 && e
== 'Y')
63 static char *apparmor_process_label_get(pid_t pid
)
65 char path
[100], *space
;
67 char *buf
= NULL
, *newbuf
;
71 ret
= snprintf(path
, 100, "/proc/%d/attr/current", pid
);
72 if (ret
< 0 || ret
>= 100) {
73 ERROR("path name too long");
79 SYSERROR("opening %s\n", path
);
85 newbuf
= realloc(buf
, sz
);
88 ERROR("out of memory");
94 ret
= fread(buf
, 1, sz
- 1, f
);
97 ERROR("reading %s\n", path
);
103 space
= index(buf
, '\n');
106 space
= index(buf
, ' ');
112 static int apparmor_am_unconfined(void)
114 char *p
= apparmor_process_label_get(getpid());
116 if (!p
|| strcmp(p
, "unconfined") == 0)
124 * apparmor_process_label_set: Set AppArmor process profile
126 * @label : the profile to set
127 * @default : use the default profile if label is NULL
128 * @on_exec : the new profile will take effect on exec(2) not immediately
130 * Returns 0 on success, < 0 on failure
132 * Notes: This relies on /proc being available.
134 static int apparmor_process_label_set(const char *label
, int use_default
,
142 label
= AA_DEF_PROFILE
;
147 if (strcmp(label
, "unconfined") == 0 && apparmor_am_unconfined()) {
148 INFO("apparmor profile unchanged");
153 if (aa_change_onexec(label
) < 0) {
154 SYSERROR("failed to change exec apparmor profile to %s", label
);
158 if (aa_change_profile(label
) < 0) {
159 SYSERROR("failed to change apparmor profile to %s", label
);
164 INFO("changed apparmor%s profile to %s", on_exec
? " exec" : "", label
);
168 static struct lsm_drv apparmor_drv
= {
170 .enabled
= apparmor_enabled
,
171 .process_label_get
= apparmor_process_label_get
,
172 .process_label_set
= apparmor_process_label_set
,
175 struct lsm_drv
*lsm_apparmor_drv_init(void)
177 if (!apparmor_enabled())
180 return &apparmor_drv
;