]> git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/lsm/lsm.c
refactor AppArmor into LSM backend, add SELinux support
[mirror_lxc.git] / src / lxc / lsm / lsm.c
1 /*
2 * lxc: linux Container library
3 *
4 * Authors:
5 * Copyright © 2012 Serge Hallyn <serge.hallyn@ubuntu.com>
6 * Copyright © 2012 Canonical Ltd.
7 * Dwight Engen <dwight.engen@oracle.com>
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24 #if HAVE_APPARMOR || HAVE_SELINUX
25
26 #include <errno.h>
27 #include <stdlib.h>
28 #include <unistd.h>
29 #include <sys/mount.h>
30 #include <sys/param.h>
31
32 #include "conf.h"
33 #include "log.h"
34 #include "lsm/lsm.h"
35
36 lxc_log_define(lxc_lsm, lxc);
37
38 static struct lsm_drv *drv = NULL;
39
40 extern struct lsm_drv *lsm_apparmor_drv_init(void);
41 extern struct lsm_drv *lsm_selinux_drv_init(void);
42 extern struct lsm_drv *lsm_nop_drv_init(void);
43
44 __attribute__((constructor))
45 void lsm_init(void)
46 {
47 if (drv) {
48 INFO("LSM security driver %s", drv->name);
49 return;
50 }
51
52 #if HAVE_APPARMOR
53 drv = lsm_apparmor_drv_init();
54 #endif
55 #if HAVE_SELINUX
56 if (!drv)
57 drv = lsm_selinux_drv_init();
58 #endif
59
60 if (!drv)
61 drv = lsm_nop_drv_init();
62 INFO("Initialized LSM security driver %s", drv->name);
63 }
64
65 char *lsm_process_label_get(pid_t pid)
66 {
67 if (!drv) {
68 ERROR("LSM driver not inited");
69 return NULL;
70 }
71 return drv->process_label_get(pid);
72 }
73
74 int lsm_process_label_set(const char *label, int use_default)
75 {
76 if (!drv) {
77 ERROR("LSM driver not inited");
78 return -1;
79 }
80 return drv->process_label_set(label, use_default);
81 }
82
83 /*
84 * _lsm_mount_proc: Mount /proc inside container to enable
85 * security domain transition
86 *
87 * @rootfs : the rootfs where proc should be mounted
88 *
89 * Returns < 0 on failure, 0 if the correct proc was already mounted
90 * and 1 if a new proc was mounted.
91 */
92 static int _lsm_proc_mount(const char *rootfs)
93 {
94 char path[MAXPATHLEN];
95 char link[20];
96 int linklen, ret;
97
98 ret = snprintf(path, MAXPATHLEN, "%s/proc/self", rootfs);
99 if (ret < 0 || ret >= MAXPATHLEN) {
100 SYSERROR("proc path name too long");
101 return -1;
102 }
103 memset(link, 0, 20);
104 linklen = readlink(path, link, 20);
105 INFO("I am %d, /proc/self points to '%s'", getpid(), link);
106 ret = snprintf(path, MAXPATHLEN, "%s/proc", rootfs);
107 if (linklen < 0) /* /proc not mounted */
108 goto domount;
109 /* can't be longer than rootfs/proc/1 */
110 if (strncmp(link, "1", linklen) != 0) {
111 /* wrong /procs mounted */
112 umount2(path, MNT_DETACH); /* ignore failure */
113 goto domount;
114 }
115 /* the right proc is already mounted */
116 return 0;
117
118 domount:
119 if (mount("proc", path, "proc", 0, NULL))
120 return -1;
121 INFO("Mounted /proc in container for security transition");
122 return 1;
123 }
124
125 int lsm_proc_mount(struct lxc_conf *lxc_conf)
126 {
127 int mounted;
128
129 if (!drv || strcmp(drv->name, "nop") == 0)
130 return 0;
131
132 if (lxc_conf->rootfs.path == NULL || strlen(lxc_conf->rootfs.path) == 0) {
133 if (mount("proc", "/proc", "proc", 0, NULL)) {
134 SYSERROR("Failed mounting /proc, proceeding");
135 mounted = 0;
136 } else
137 mounted = 1;
138 } else
139 mounted = _lsm_proc_mount(lxc_conf->rootfs.mount);
140 if (mounted == -1) {
141 SYSERROR("failed to mount /proc in the container.");
142 return -1;
143 } else if (mounted == 1) {
144 lxc_conf->lsm_umount_proc = 1;
145 }
146 return 0;
147 }
148
149 void lsm_proc_unmount(struct lxc_conf *lxc_conf)
150 {
151 if (lxc_conf->lsm_umount_proc == 1) {
152 umount("/proc");
153 lxc_conf->lsm_umount_proc = 0;
154 }
155 }
156 #endif