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/>.
26 #include <selinux/selinux.h>
27 #include <selinux/context.h>
28 #include <sys/xattr.h>
31 #include "testutils.h"
32 #include "testutilsqemu.h"
33 #include "qemu/qemu_domain.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
{
57 testUserXattrEnabled(void)
61 const char *con_value
= "system_u:object_r:svirt_image_t:s0:c41,c264";
63 if (virAsprintf(&path
, "%s/securityselinuxlabeldata/testxattr",
67 if (virFileMakePath(abs_builddir
"/securityselinuxlabeldata") < 0 ||
68 virFileTouch(path
, 0600) < 0)
71 len
= setxattr(path
, "user.libvirt.selinux", con_value
,
72 strlen(con_value
), 0);
74 if (errno
== EOPNOTSUPP
)
83 rmdir(abs_builddir
"/securityselinuxlabeldata");
89 testSELinuxMungePath(char **path
)
93 if (virAsprintf(&tmp
, "%s/securityselinuxlabeldata%s",
94 abs_builddir
, *path
) < 0)
103 testSELinuxLoadFileList(const char *testname
,
104 testSELinuxFile
**files
,
115 if (virAsprintf(&path
, "%s/securityselinuxlabeldata/%s.txt",
116 abs_srcdir
, testname
) < 0)
119 if (!(fp
= fopen(path
, "r")))
122 if (VIR_ALLOC_N(line
, 1024) < 0)
126 char *file
= NULL
, *context
= NULL
, *tmp
;
127 if (!fgets(line
, 1024, fp
)) {
133 tmp
= strchr(line
, ';');
135 virReportError(VIR_ERR_INTERNAL_ERROR
,
136 "unexpected format for line '%s'",
143 if (virAsprintf(&file
, "%s/securityselinuxlabeldata%s",
144 abs_builddir
, line
) < 0)
146 if (*tmp
!= '\0' && *tmp
!= '\n') {
147 if (VIR_STRDUP(context
, tmp
) < 0) {
152 tmp
= strchr(context
, '\n');
157 if (VIR_EXPAND_N(*files
, *nfiles
, 1) < 0) {
163 (*files
)[(*nfiles
)-1].file
= file
;
164 (*files
)[(*nfiles
)-1].context
= context
;
170 VIR_FORCE_FCLOSE(fp
);
177 static virDomainDefPtr
178 testSELinuxLoadDef(const char *testname
)
180 char *xmlfile
= NULL
;
181 virDomainDefPtr def
= NULL
;
184 if (virAsprintf(&xmlfile
, "%s/securityselinuxlabeldata/%s.xml",
185 abs_srcdir
, testname
) < 0)
188 if (!(def
= virDomainDefParseFile(xmlfile
, driver
.caps
, driver
.xmlopt
,
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
)
197 if (testSELinuxMungePath(&def
->disks
[i
]->src
->path
) < 0)
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
)
208 if (def
->serials
[i
]->source
->type
== VIR_DOMAIN_CHR_TYPE_UNIX
) {
209 if (testSELinuxMungePath(&def
->serials
[i
]->source
->data
.nix
.path
) < 0)
212 if (testSELinuxMungePath(&def
->serials
[i
]->source
->data
.file
.path
) < 0)
217 if (def
->os
.kernel
&&
218 testSELinuxMungePath(&def
->os
.kernel
) < 0)
220 if (def
->os
.initrd
&&
221 testSELinuxMungePath(&def
->os
.initrd
) < 0)
231 testSELinuxCreateDisks(testSELinuxFile
*files
, size_t nfiles
)
235 if (virFileMakePath(abs_builddir
"/securityselinuxlabeldata/nfs") < 0)
238 for (i
= 0; i
< nfiles
; i
++) {
239 if (virFileTouch(files
[i
].file
, 0600) < 0)
246 testSELinuxDeleteDisks(testSELinuxFile
*files
, size_t nfiles
)
250 for (i
= 0; i
< nfiles
; i
++) {
251 if (unlink(files
[i
].file
) < 0)
254 if (rmdir(abs_builddir
"/securityselinuxlabeldata/nfs") < 0)
256 /* Ignore failure to remove non-empty directory with in-tree build */
257 rmdir(abs_builddir
"/securityselinuxlabeldata");
262 testSELinuxCheckLabels(testSELinuxFile
*files
, size_t nfiles
)
265 security_context_t ctx
;
267 for (i
= 0; i
< nfiles
; i
++) {
269 if (getfilecon(files
[i
].file
, &ctx
) < 0) {
270 if (errno
== ENODATA
) {
272 } else if (errno
== EOPNOTSUPP
) {
273 if (VIR_STRDUP(ctx
, "EOPNOTSUPP") < 0)
276 virReportSystemError(errno
,
277 "Cannot read label on %s",
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
);
295 testSELinuxLabeling(const void *opaque
)
297 const char *testname
= opaque
;
299 testSELinuxFile
*files
= NULL
;
302 virDomainDefPtr def
= NULL
;
304 if (testSELinuxLoadFileList(testname
, &files
, &nfiles
) < 0)
307 if (testSELinuxCreateDisks(files
, nfiles
) < 0)
310 if (!(def
= testSELinuxLoadDef(testname
)))
313 if (virSecurityManagerSetAllLabel(mgr
, def
, NULL
, false) < 0)
316 if (testSELinuxCheckLabels(files
, nfiles
) < 0)
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
);
332 VIR_TEST_VERBOSE("%s\n", virGetLastErrorMessage());
342 int rc
= testUserXattrEnabled();
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());
357 if (qemuTestDriverInit(&driver
) < 0)
360 #define DO_TEST_LABELING(name) \
361 if (virTestRun("Labelling " # name, testSELinuxLabeling, name) < 0) \
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")