]> git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/lsm/lsm.c
fd: only add valid fd to mainloop
[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 #ifndef _GNU_SOURCE
25 #define _GNU_SOURCE 1
26 #endif
27 #include <errno.h>
28 #include <stdlib.h>
29 #include <sys/mount.h>
30 #include <sys/param.h>
31 #include <unistd.h>
32
33 #include "conf.h"
34 #include "config.h"
35 #include "log.h"
36 #include "lsm.h"
37
38 lxc_log_define(lsm, lxc);
39
40 static struct lsm_drv *drv = NULL;
41
42 extern struct lsm_drv *lsm_apparmor_drv_init(void);
43 extern struct lsm_drv *lsm_selinux_drv_init(void);
44 extern struct lsm_drv *lsm_nop_drv_init(void);
45
46 __attribute__((constructor))
47 void lsm_init(void)
48 {
49 if (drv) {
50 INFO("LSM security driver %s", drv->name);
51 return;
52 }
53
54 #if HAVE_APPARMOR
55 drv = lsm_apparmor_drv_init();
56 #endif
57 #if HAVE_SELINUX
58 if (!drv)
59 drv = lsm_selinux_drv_init();
60 #endif
61
62 if (!drv)
63 drv = lsm_nop_drv_init();
64 INFO("Initialized LSM security driver %s", drv->name);
65 }
66
67 int lsm_enabled(void)
68 {
69 if (drv)
70 return drv->enabled();
71 return 0;
72 }
73
74 const char *lsm_name(void)
75 {
76 if (drv)
77 return drv->name;
78 return "none";
79 }
80
81 char *lsm_process_label_get(pid_t pid)
82 {
83 if (!drv) {
84 ERROR("LSM driver not inited");
85 return NULL;
86 }
87 return drv->process_label_get(pid);
88 }
89
90 int lsm_process_label_fd_get(pid_t pid, bool on_exec)
91 {
92 int ret = -1;
93 int labelfd = -1;
94 const char *name;
95 char path[LXC_LSMATTRLEN];
96
97 name = lsm_name();
98
99 if (strcmp(name, "nop") == 0)
100 return 0;
101
102 if (strcmp(name, "none") == 0)
103 return 0;
104
105 /* We don't support on-exec with AppArmor */
106 if (strcmp(name, "AppArmor") == 0)
107 on_exec = 0;
108
109 if (on_exec)
110 ret = snprintf(path, LXC_LSMATTRLEN, "/proc/%d/attr/exec", pid);
111 else
112 ret = snprintf(path, LXC_LSMATTRLEN, "/proc/%d/attr/current", pid);
113 if (ret < 0 || ret >= LXC_LSMATTRLEN)
114 return -1;
115
116 labelfd = open(path, O_RDWR);
117 if (labelfd < 0) {
118 SYSERROR("Unable to %s LSM label file descriptor", name);
119 return -1;
120 }
121
122 return labelfd;
123 }
124
125 int lsm_process_label_set_at(int label_fd, const char *label, bool on_exec)
126 {
127 int ret = -1;
128 const char *name;
129
130 name = lsm_name();
131
132 if (strcmp(name, "nop") == 0)
133 return 0;
134
135 if (strcmp(name, "none") == 0)
136 return 0;
137
138 /* We don't support on-exec with AppArmor */
139 if (strcmp(name, "AppArmor") == 0)
140 on_exec = false;
141
142 if (strcmp(name, "AppArmor") == 0) {
143 size_t len;
144 char *command;
145
146 if (on_exec) {
147 ERROR("Changing AppArmor profile on exec not supported");
148 return -1;
149 }
150
151 len = strlen(label) + strlen("changeprofile ") + 1;
152 command = malloc(len);
153 if (!command)
154 goto on_error;
155
156 ret = snprintf(command, len, "changeprofile %s", label);
157 if (ret < 0 || (size_t)ret >= len) {
158 int saved_errno = errno;
159 free(command);
160 errno = saved_errno;
161 goto on_error;
162 }
163
164 ret = lxc_write_nointr(label_fd, command, len - 1);
165 free(command);
166 } else if (strcmp(name, "SELinux") == 0) {
167 ret = lxc_write_nointr(label_fd, label, strlen(label));
168 } else {
169 errno = EINVAL;
170 ret = -1;
171 }
172 if (ret < 0) {
173 on_error:
174 SYSERROR("Failed to set %s label \"%s\"", name, label);
175 return -1;
176 }
177
178 INFO("Set %s label to \"%s\"", name, label);
179 return 0;
180 }
181
182 int lsm_process_label_set(const char *label, struct lxc_conf *conf,
183 bool on_exec)
184 {
185 if (!drv) {
186 ERROR("LSM driver not inited");
187 return -1;
188 }
189 return drv->process_label_set(label, conf, on_exec);
190 }
191
192 int lsm_process_prepare(struct lxc_conf *conf, const char *lxcpath)
193 {
194 if (!drv) {
195 ERROR("LSM driver not inited");
196 return 0;
197 }
198
199 if (!drv->prepare)
200 return 0;
201
202 return drv->prepare(conf, lxcpath);
203 }
204
205 void lsm_process_cleanup(struct lxc_conf *conf, const char *lxcpath)
206 {
207 if (!drv) {
208 ERROR("LSM driver not inited");
209 return;
210 }
211
212 if (!drv->cleanup)
213 return;
214
215 drv->cleanup(conf, lxcpath);
216 }