mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-09 01:18:00 +03:00
selinux: enhance test to cover nfs label failure
Daniel Berrange (correctly) pointed out that we should do a better job of testing selinux labeling fallbacks on NFS disks that lack labeling support. * tests/securityselinuxhelper.c (includes): Makefile already guaranteed xattr support. Add additional headers. (init_syms): New function, borrowing from vircgroupmock.c. (setfilecon_raw, getfilecon_raw): Fake NFS failure. (statfs): Fake an NFS mount point. (security_getenforce, security_get_boolean_active): Don't let host environment affect test. * tests/securityselinuxlabeldata/nfs.data: New file. * tests/securityselinuxlabeldata/nfs.xml: New file. * tests/securityselinuxlabeltest.c (testSELinuxCreateDisks) (testSELinuxDeleteDisks): Setup and cleanup for fake NFS mount. (testSELinuxCheckLabels): Test handling of SELinux NFS denial. Fix memory leak. (testSELinuxLabeling): Avoid infinite loop on dirty tree. (mymain): Add new test.
This commit is contained in:
parent
0f082e699e
commit
95577af442
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2011-2012 Red Hat, Inc.
|
* Copyright (C) 2011-2013 Red Hat, Inc.
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
@ -19,22 +19,53 @@
|
|||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
|
/* This file is only compiled on Linux, and only if xattr support was
|
||||||
|
* detected. */
|
||||||
|
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <linux/magic.h>
|
||||||
#include <selinux/selinux.h>
|
#include <selinux/selinux.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <sys/vfs.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
#include <attr/xattr.h>
|
||||||
#if WITH_ATTR
|
|
||||||
# include <attr/xattr.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "virstring.h"
|
#include "virstring.h"
|
||||||
|
|
||||||
|
static int (*realstatfs)(const char *path, struct statfs *buf);
|
||||||
|
static int (*realsecurity_get_boolean_active)(const char *name);
|
||||||
|
|
||||||
|
static void init_syms(void)
|
||||||
|
{
|
||||||
|
if (realstatfs)
|
||||||
|
return;
|
||||||
|
|
||||||
|
#define LOAD_SYM(name) \
|
||||||
|
do { \
|
||||||
|
if (!(real ## name = dlsym(RTLD_NEXT, #name))) { \
|
||||||
|
fprintf(stderr, "Cannot find real '%s' symbol\n", #name); \
|
||||||
|
abort(); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
LOAD_SYM(statfs);
|
||||||
|
LOAD_SYM(security_get_boolean_active);
|
||||||
|
|
||||||
|
#undef LOAD_SYM
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The kernel policy will not allow us to arbitrarily change
|
* The kernel policy will not allow us to arbitrarily change
|
||||||
* test process context. This helper is used as an LD_PRELOAD
|
* test process context. This helper is used as an LD_PRELOAD
|
||||||
* so that the libvirt code /thinks/ it is changing/reading
|
* so that the libvirt code /thinks/ it is changing/reading
|
||||||
* the process context, where as in fact we're faking it all
|
* the process context, whereas in fact we're faking it all.
|
||||||
|
* Furthermore, we fake out that we are using an nfs subdirectory,
|
||||||
|
* where we control whether selinux is enforcing and whether
|
||||||
|
* the virt_use_nfs bool is set.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int getcon_raw(security_context_t *context)
|
int getcon_raw(security_context_t *context)
|
||||||
@ -83,10 +114,13 @@ int setcon(security_context_t context)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if WITH_ATTR
|
|
||||||
int setfilecon_raw(const char *path, security_context_t con)
|
int setfilecon_raw(const char *path, security_context_t con)
|
||||||
{
|
{
|
||||||
const char *constr = con;
|
const char *constr = con;
|
||||||
|
if (STRPREFIX(path, abs_builddir "/securityselinuxlabeldata/nfs/")) {
|
||||||
|
errno = EOPNOTSUPP;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
return setxattr(path, "user.libvirt.selinux",
|
return setxattr(path, "user.libvirt.selinux",
|
||||||
constr, strlen(constr), 0);
|
constr, strlen(constr), 0);
|
||||||
}
|
}
|
||||||
@ -101,6 +135,10 @@ int getfilecon_raw(const char *path, security_context_t *con)
|
|||||||
char *constr = NULL;
|
char *constr = NULL;
|
||||||
ssize_t len = getxattr(path, "user.libvirt.selinux",
|
ssize_t len = getxattr(path, "user.libvirt.selinux",
|
||||||
NULL, 0);
|
NULL, 0);
|
||||||
|
if (STRPREFIX(path, abs_builddir "/securityselinuxlabeldata/nfs/")) {
|
||||||
|
errno = EOPNOTSUPP;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
if (len < 0)
|
if (len < 0)
|
||||||
return -1;
|
return -1;
|
||||||
if (!(constr = malloc(len+1)))
|
if (!(constr = malloc(len+1)))
|
||||||
@ -114,8 +152,40 @@ int getfilecon_raw(const char *path, security_context_t *con)
|
|||||||
constr[len] = '\0';
|
constr[len] = '\0';
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int getfilecon(const char *path, security_context_t *con)
|
int getfilecon(const char *path, security_context_t *con)
|
||||||
{
|
{
|
||||||
return getfilecon_raw(path, con);
|
return getfilecon_raw(path, con);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
|
int statfs(const char *path, struct statfs *buf)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
init_syms();
|
||||||
|
|
||||||
|
ret = realstatfs(path, buf);
|
||||||
|
if (!ret && STREQ(path, abs_builddir "/securityselinuxlabeldata/nfs"))
|
||||||
|
buf->f_type = NFS_SUPER_MAGIC;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int security_getenforce(void)
|
||||||
|
{
|
||||||
|
/* For the purpose of our test, we are enforcing. */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int security_get_boolean_active(const char *name)
|
||||||
|
{
|
||||||
|
/* For the purpose of our test, nfs is not permitted. */
|
||||||
|
if (STREQ(name, "virt_use_nfs"))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
init_syms();
|
||||||
|
return realsecurity_get_boolean_active(name);
|
||||||
|
}
|
||||||
|
1
tests/securityselinuxlabeldata/nfs.txt
Normal file
1
tests/securityselinuxlabeldata/nfs.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
/nfs/plain.raw;EOPNOTSUPP
|
24
tests/securityselinuxlabeldata/nfs.xml
Normal file
24
tests/securityselinuxlabeldata/nfs.xml
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<domain type='kvm'>
|
||||||
|
<name>vm1</name>
|
||||||
|
<uuid>c7b3edbd-edaf-9455-926a-d65c16db1800</uuid>
|
||||||
|
<memory unit='KiB'>219200</memory>
|
||||||
|
<os>
|
||||||
|
<type arch='i686' machine='pc-1.0'>hvm</type>
|
||||||
|
<boot dev='cdrom'/>
|
||||||
|
</os>
|
||||||
|
<devices>
|
||||||
|
<disk type='file' device='disk'>
|
||||||
|
<driver name='qemu' type='raw'/>
|
||||||
|
<source file='/nfs/plain.raw'/>
|
||||||
|
<target dev='vda' bus='virtio'/>
|
||||||
|
</disk>
|
||||||
|
<input type='mouse' bus='ps2'/>
|
||||||
|
<graphics type='vnc' port='-1' autoport='yes' listen='0.0.0.0'>
|
||||||
|
<listen type='address' address='0.0.0.0'/>
|
||||||
|
</graphics>
|
||||||
|
</devices>
|
||||||
|
<seclabel model="selinux" type="dynamic" relabel="yes">
|
||||||
|
<label>system_u:system_r:svirt_t:s0:c41,c264</label>
|
||||||
|
<imagelabel>system_u:object_r:svirt_image_t:s0:c41,c264</imagelabel>
|
||||||
|
</seclabel>
|
||||||
|
</domain>
|
@ -209,7 +209,7 @@ testSELinuxCreateDisks(testSELinuxFile *files, size_t nfiles)
|
|||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
if (virFileMakePath(abs_builddir "/securityselinuxlabeldata") < 0)
|
if (virFileMakePath(abs_builddir "/securityselinuxlabeldata/nfs") < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
for (i = 0; i < nfiles; i++) {
|
for (i = 0; i < nfiles; i++) {
|
||||||
@ -228,6 +228,10 @@ testSELinuxDeleteDisks(testSELinuxFile *files, size_t nfiles)
|
|||||||
if (unlink(files[i].file) < 0)
|
if (unlink(files[i].file) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if (rmdir(abs_builddir "/securityselinuxlabeldata/nfs") < 0)
|
||||||
|
return -1;
|
||||||
|
/* Ignore failure to remove non-empty directory with in-tree build */
|
||||||
|
rmdir(abs_builddir "/securityselinuxlabeldata");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -238,9 +242,13 @@ testSELinuxCheckLabels(testSELinuxFile *files, size_t nfiles)
|
|||||||
security_context_t ctx;
|
security_context_t ctx;
|
||||||
|
|
||||||
for (i = 0; i < nfiles; i++) {
|
for (i = 0; i < nfiles; i++) {
|
||||||
|
ctx = NULL;
|
||||||
if (getfilecon(files[i].file, &ctx) < 0) {
|
if (getfilecon(files[i].file, &ctx) < 0) {
|
||||||
if (errno == ENODATA) {
|
if (errno == ENODATA) {
|
||||||
ctx = NULL;
|
/* nothing to do */
|
||||||
|
} else if (errno == EOPNOTSUPP) {
|
||||||
|
if (VIR_STRDUP(ctx, "EOPNOTSUPP") < 0)
|
||||||
|
return -1;
|
||||||
} else {
|
} else {
|
||||||
virReportSystemError(errno,
|
virReportSystemError(errno,
|
||||||
"Cannot read label on %s",
|
"Cannot read label on %s",
|
||||||
@ -252,8 +260,10 @@ testSELinuxCheckLabels(testSELinuxFile *files, size_t nfiles)
|
|||||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||||
"File %s context '%s' did not match epected '%s'",
|
"File %s context '%s' did not match epected '%s'",
|
||||||
files[i].file, ctx, files[i].context);
|
files[i].file, ctx, files[i].context);
|
||||||
|
VIR_FREE(ctx);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
VIR_FREE(ctx);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -287,7 +297,7 @@ testSELinuxLabeling(const void *opaque)
|
|||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
if (testSELinuxDeleteDisks(files, nfiles) < 0)
|
if (testSELinuxDeleteDisks(files, nfiles) < 0)
|
||||||
goto cleanup;
|
VIR_WARN("unable to fully clean up");
|
||||||
|
|
||||||
virDomainDefFree(def);
|
virDomainDefFree(def);
|
||||||
for (i = 0; i < nfiles; i++) {
|
for (i = 0; i < nfiles; i++) {
|
||||||
@ -334,6 +344,7 @@ mymain(void)
|
|||||||
DO_TEST_LABELING("disks");
|
DO_TEST_LABELING("disks");
|
||||||
DO_TEST_LABELING("kernel");
|
DO_TEST_LABELING("kernel");
|
||||||
DO_TEST_LABELING("chardev");
|
DO_TEST_LABELING("chardev");
|
||||||
|
DO_TEST_LABELING("nfs");
|
||||||
|
|
||||||
return (ret == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
|
return (ret == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user