backup: Wire up qemu full pull backup commands over QMP
[libvirt/ericb.git] / tests / securityselinuxlabeltest.c
blob76db2494bd4c890cd135812e1fda28d0c5a2b310
1 /*
2 * Copyright (C) 2011-2014 Red Hat, Inc.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * License along with this library; If not, see
17 * <http://www.gnu.org/licenses/>.
22 #include <config.h>
24 #include <time.h>
26 #include <selinux/selinux.h>
27 #include <selinux/context.h>
28 #include <sys/xattr.h>
30 #include "internal.h"
31 #include "testutils.h"
32 #include "testutilsqemu.h"
33 #include "qemu/qemu_domain.h"
34 #include "viralloc.h"
35 #include "virerror.h"
36 #include "virfile.h"
37 #include "virlog.h"
38 #include "security/security_manager.h"
39 #include "virstring.h"
41 #define VIR_FROM_THIS VIR_FROM_NONE
43 VIR_LOG_INIT("tests.securityselinuxlabeltest");
45 static virQEMUDriver driver;
47 static virSecurityManagerPtr mgr;
49 typedef struct testSELinuxFile testSELinuxFile;
51 struct testSELinuxFile {
52 char *file;
53 char *context;
56 static int
57 testUserXattrEnabled(void)
59 int ret = -1;
60 ssize_t len;
61 const char *con_value = "system_u:object_r:svirt_image_t:s0:c41,c264";
62 char *path = NULL;
63 if (virAsprintf(&path, "%s/securityselinuxlabeldata/testxattr",
64 abs_builddir) < 0)
65 goto cleanup;
67 if (virFileMakePath(abs_builddir "/securityselinuxlabeldata") < 0 ||
68 virFileTouch(path, 0600) < 0)
69 goto cleanup;
71 len = setxattr(path, "user.libvirt.selinux", con_value,
72 strlen(con_value), 0);
73 if (len < 0) {
74 if (errno == EOPNOTSUPP)
75 ret = 0;
76 goto cleanup;
79 ret = 1;
81 cleanup:
82 unlink(path);
83 rmdir(abs_builddir "/securityselinuxlabeldata");
84 VIR_FREE(path);
85 return ret;
88 static int
89 testSELinuxMungePath(char **path)
91 char *tmp;
93 if (virAsprintf(&tmp, "%s/securityselinuxlabeldata%s",
94 abs_builddir, *path) < 0)
95 return -1;
97 VIR_FREE(*path);
98 *path = tmp;
99 return 0;
102 static int
103 testSELinuxLoadFileList(const char *testname,
104 testSELinuxFile **files,
105 size_t *nfiles)
107 int ret = -1;
108 char *path = NULL;
109 FILE *fp = NULL;
110 char *line = NULL;
112 *files = NULL;
113 *nfiles = 0;
115 if (virAsprintf(&path, "%s/securityselinuxlabeldata/%s.txt",
116 abs_srcdir, testname) < 0)
117 goto cleanup;
119 if (!(fp = fopen(path, "r")))
120 goto cleanup;
122 if (VIR_ALLOC_N(line, 1024) < 0)
123 goto cleanup;
125 while (!feof(fp)) {
126 char *file = NULL, *context = NULL, *tmp;
127 if (!fgets(line, 1024, fp)) {
128 if (!feof(fp))
129 goto cleanup;
130 break;
133 tmp = strchr(line, ';');
134 if (!tmp) {
135 virReportError(VIR_ERR_INTERNAL_ERROR,
136 "unexpected format for line '%s'",
137 line);
138 goto cleanup;
140 *tmp = '\0';
141 tmp++;
143 if (virAsprintf(&file, "%s/securityselinuxlabeldata%s",
144 abs_builddir, line) < 0)
145 goto cleanup;
146 if (*tmp != '\0' && *tmp != '\n') {
147 if (VIR_STRDUP(context, tmp) < 0) {
148 VIR_FREE(file);
149 goto cleanup;
152 tmp = strchr(context, '\n');
153 if (tmp)
154 *tmp = '\0';
157 if (VIR_EXPAND_N(*files, *nfiles, 1) < 0) {
158 VIR_FREE(file);
159 VIR_FREE(context);
160 goto cleanup;
163 (*files)[(*nfiles)-1].file = file;
164 (*files)[(*nfiles)-1].context = context;
167 ret = 0;
169 cleanup:
170 VIR_FORCE_FCLOSE(fp);
171 VIR_FREE(path);
172 VIR_FREE(line);
173 return ret;
177 static virDomainDefPtr
178 testSELinuxLoadDef(const char *testname)
180 char *xmlfile = NULL;
181 virDomainDefPtr def = NULL;
182 size_t i;
184 if (virAsprintf(&xmlfile, "%s/securityselinuxlabeldata/%s.xml",
185 abs_srcdir, testname) < 0)
186 goto cleanup;
188 if (!(def = virDomainDefParseFile(xmlfile, driver.caps, driver.xmlopt,
189 NULL, 0)))
190 goto cleanup;
192 for (i = 0; i < def->ndisks; i++) {
193 if (def->disks[i]->src->type != VIR_STORAGE_TYPE_FILE &&
194 def->disks[i]->src->type != VIR_STORAGE_TYPE_BLOCK)
195 continue;
197 if (testSELinuxMungePath(&def->disks[i]->src->path) < 0)
198 goto cleanup;
201 for (i = 0; i < def->nserials; i++) {
202 if (def->serials[i]->source->type != VIR_DOMAIN_CHR_TYPE_FILE &&
203 def->serials[i]->source->type != VIR_DOMAIN_CHR_TYPE_PIPE &&
204 def->serials[i]->source->type != VIR_DOMAIN_CHR_TYPE_DEV &&
205 def->serials[i]->source->type != VIR_DOMAIN_CHR_TYPE_UNIX)
206 continue;
208 if (def->serials[i]->source->type == VIR_DOMAIN_CHR_TYPE_UNIX) {
209 if (testSELinuxMungePath(&def->serials[i]->source->data.nix.path) < 0)
210 goto cleanup;
211 } else {
212 if (testSELinuxMungePath(&def->serials[i]->source->data.file.path) < 0)
213 goto cleanup;
217 if (def->os.kernel &&
218 testSELinuxMungePath(&def->os.kernel) < 0)
219 goto cleanup;
220 if (def->os.initrd &&
221 testSELinuxMungePath(&def->os.initrd) < 0)
222 goto cleanup;
224 cleanup:
225 VIR_FREE(xmlfile);
226 return def;
230 static int
231 testSELinuxCreateDisks(testSELinuxFile *files, size_t nfiles)
233 size_t i;
235 if (virFileMakePath(abs_builddir "/securityselinuxlabeldata/nfs") < 0)
236 return -1;
238 for (i = 0; i < nfiles; i++) {
239 if (virFileTouch(files[i].file, 0600) < 0)
240 return -1;
242 return 0;
245 static int
246 testSELinuxDeleteDisks(testSELinuxFile *files, size_t nfiles)
248 size_t i;
250 for (i = 0; i < nfiles; i++) {
251 if (unlink(files[i].file) < 0)
252 return -1;
254 if (rmdir(abs_builddir "/securityselinuxlabeldata/nfs") < 0)
255 return -1;
256 /* Ignore failure to remove non-empty directory with in-tree build */
257 rmdir(abs_builddir "/securityselinuxlabeldata");
258 return 0;
261 static int
262 testSELinuxCheckLabels(testSELinuxFile *files, size_t nfiles)
264 size_t i;
265 security_context_t ctx;
267 for (i = 0; i < nfiles; i++) {
268 ctx = NULL;
269 if (getfilecon(files[i].file, &ctx) < 0) {
270 if (errno == ENODATA) {
271 /* nothing to do */
272 } else if (errno == EOPNOTSUPP) {
273 if (VIR_STRDUP(ctx, "EOPNOTSUPP") < 0)
274 return -1;
275 } else {
276 virReportSystemError(errno,
277 "Cannot read label on %s",
278 files[i].file);
279 return -1;
282 if (STRNEQ_NULLABLE(files[i].context, ctx)) {
283 virReportError(VIR_ERR_INTERNAL_ERROR,
284 "File %s context '%s' did not match expected '%s'",
285 files[i].file, ctx, files[i].context);
286 VIR_FREE(ctx);
287 return -1;
289 VIR_FREE(ctx);
291 return 0;
294 static int
295 testSELinuxLabeling(const void *opaque)
297 const char *testname = opaque;
298 int ret = -1;
299 testSELinuxFile *files = NULL;
300 size_t nfiles = 0;
301 size_t i;
302 virDomainDefPtr def = NULL;
304 if (testSELinuxLoadFileList(testname, &files, &nfiles) < 0)
305 goto cleanup;
307 if (testSELinuxCreateDisks(files, nfiles) < 0)
308 goto cleanup;
310 if (!(def = testSELinuxLoadDef(testname)))
311 goto cleanup;
313 if (virSecurityManagerSetAllLabel(mgr, def, NULL, false) < 0)
314 goto cleanup;
316 if (testSELinuxCheckLabels(files, nfiles) < 0)
317 goto cleanup;
319 ret = 0;
321 cleanup:
322 if (testSELinuxDeleteDisks(files, nfiles) < 0)
323 VIR_WARN("unable to fully clean up");
325 virDomainDefFree(def);
326 for (i = 0; i < nfiles; i++) {
327 VIR_FREE(files[i].file);
328 VIR_FREE(files[i].context);
330 VIR_FREE(files);
331 if (ret < 0)
332 VIR_TEST_VERBOSE("%s\n", virGetLastErrorMessage());
333 return ret;
338 static int
339 mymain(void)
341 int ret = 0;
342 int rc = testUserXattrEnabled();
344 if (rc < 0)
345 return EXIT_FAILURE;
346 if (!rc)
347 return EXIT_AM_SKIP;
349 if (!(mgr = virSecurityManagerNew("selinux", "QEMU",
350 VIR_SECURITY_MANAGER_DEFAULT_CONFINED |
351 VIR_SECURITY_MANAGER_PRIVILEGED))) {
352 VIR_TEST_VERBOSE("Unable to initialize security driver: %s\n",
353 virGetLastErrorMessage());
354 return EXIT_FAILURE;
357 if (qemuTestDriverInit(&driver) < 0)
358 return EXIT_FAILURE;
360 #define DO_TEST_LABELING(name) \
361 if (virTestRun("Labelling " # name, testSELinuxLabeling, name) < 0) \
362 ret = -1;
364 setcon((security_context_t)"system_r:system_u:libvirtd_t:s0:c0.c1023");
366 DO_TEST_LABELING("disks");
367 DO_TEST_LABELING("kernel");
368 DO_TEST_LABELING("chardev");
369 DO_TEST_LABELING("nfs");
371 qemuTestDriverFree(&driver);
373 return (ret == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
376 VIR_TEST_MAIN_PRELOAD(mymain, abs_builddir "/.libs/libsecurityselinuxhelper.so")