When I suggested to Jim to call real virFileExists() I forgot to
also suggest calling init_syms(). Without it, real_virFileExists
pointer might be left unset. And indeed, that's what we were
seeing on FreeBSD.
This effectively reverts commit 4b5cc57ed3.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
Reviewed-by: Jim Fehlig <jfehlig@suse.com>
Calling the real virFileExists in qemusecuritymock.c can cause a
segfault in qemusecuritytest. No segfaults are noticed when calling
access(2) instead of virFileExists.
Fixes: 4ed5ade753
Signed-off-by: Jim Fehlig <jfehlig@suse.com>
When performing an install, it's common for tooling such as virt-install
to remove the install kernel/initrd once they are successfully booted and
the domain has been redefined to boot without them. After the installation
is complete and the domain is rebooted/shutdown, the DAC and selinux
security drivers attempt to restore labels on the now deleted files. It's
harmles wrt functionality, but results in error messages such as
Mar 08 12:40:37 virtqemud[5639]: internal error: child reported (status=125): unable to stat: /var/lib/libvirt/boot/vir>
Mar 08 12:40:37 virtqemud[5639]: unable to stat: /var/lib/libvirt/boot/virtinst-yvp19moo-linux: No such file or directo>
Mar 08 12:40:37 virtqemud[5639]: Unable to run security manager transaction
Add a check for file existence to the virSecurity*RestoreFileLabel functions,
and avoid relabeling if the file is no longer available. Skipping the restore
caused failures in qemusecuritytest, which mocks stat, chown, etc as part of
ensuring the security drivers properly restore labels. virFileExists is now
mocked in qemusecuritymock.c to return true when passed a file previously
seen by the mocked stat, chown, etc functions.
Signed-off-by: Jim Fehlig <jfehlig@suse.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
As of commit [1] glibc may overwrite a call to open() with call
to __open_2() (if only two arguments are provided and the code is
compiled with clang). But since we are not mocking the latter our
test suite is broken as tests try to access paths outside of our
repo.
1: https://sourceware.org/git/?p=glibc.git;a=commit;h=86889e22db329abac618c6a41f86c84657a15324
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Pavel Hrdina <phrdina@redhat.com>
Use 'g_clear_pointer(&ptr, g_hash_table_unref)' instead.
In few instances it allows us to also remove explicit clearing of
pointers.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
Reviewed-by: Martin Kletzander <mkletzan@redhat.com>
In a few places we declare a variable (which is optionally
followed by a code not touching it) then set the variable to a
value and return the variable immediately. It's obvious that the
variable is needless and the value can be returned directly
instead.
This patch was generated using this semantic patch:
@@
type T;
identifier ret;
expression E;
@@
- T ret;
... when != ret
when strict
- ret = E;
- return ret;
+ return E;
After that I fixed couple of formatting issues because coccinelle
formatted some lines differently than our coding style.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
The validation code looks whether certain paths are in the 'notRestored'
list. For the purpose of lookup it's better to use a hash table rather
than a string list.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
Don't hide our use of GHashTable behind our typedef. This will also
promote the use of glibs hash function directly.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Daniel Henrique Barboza <danielhb413@gmail.com>
Reviewed-by: Matt Coleman <matt@datto.com>
The qemusecuritytest checks for random domain XMLs from
qemuxml2argvdata/ whether set+restore seclabels leaves something
behind. It can be an XATTR that we forgot to remove or a file
that the owner was not restored on. But so far only DAC driver is
checked. Implement missing pieces and enable SELinux testing too.
This is done by mocking some libselinux APIs and following the
same logic used for DAC - everything is implemented in memory,
there is new hash table introduced that holds SELinux labels for
paths that were setfilecon_raw()-ed and in the end the hash table
is checked for entries that don't have the default SELinux label
(i.e. were not restored).
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Andrea Bolognani <abologna@redhat.com>
All users of virHashTable pass strings as the name/key of the entry.
Make this an official requirement by turning the variables to 'const
char *'.
For any other case it's better to use glib's GHashTable.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Pavel Hrdina <phrdina@redhat.com>
It doesn't make much sense to configure the bucket count in the hash
table for each case specifically. Replace all calls of virHashCreate
with virHashNew which has a pre-set size and remove virHashCreate
completely.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Pavel Hrdina <phrdina@redhat.com>
Various places reported by cppcheck's invalidPrintfArgType_sint
and invalidPrintfArgType_uint.
Signed-off-by: Ján Tomko <jtomko@redhat.com>
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
Replace all occurrences of
if (VIR_STRDUP(a, b) < 0)
/* effectively dead code */
with:
a = g_strdup(b);
Signed-off-by: Ján Tomko <jtomko@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
Use G_GNUC_UNUSED from GLib instead of ATTRIBUTE_UNUSED.
Signed-off-by: Ján Tomko <jtomko@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
It may happen that we leave some XATTRs behind. For instance, on
a sudden power loss, the host just shuts down without calling
restore on domain paths. This creates a problem, because when the
host starts up again, the XATTRs are there but they don't reflect
the true state and this may result in libvirt denying start of a
domain.
To solve this, save a unique timestamp (host boot time) among
with our XATTRs.
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1741140
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
The qemusecuritytest is failing on FreeBSD 11/12, reporting that files
are not correctly restored. Debugging code printfs show that the
virFileGetXAttrQuiet mock is returning 0, but the virFileGetXAttr
function is seeing -1 as the return value.
Essentially there appears to be some kind of optimization between the
real virFileGetXAttrQuiet and the real virFileGetXAttr, which breaks
when we mock virFileGetXAttrQuiet. Rather than trying to figure out
how to avoid this, it is simpler to just mock virFileGetXAttr too
since it is very short code.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
Some paths will not be restored. Because we can't possibly know
if they are still in use or not. Reflect this in the test so that
we can test more domains. Also see next commit for more detailed
explanation.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
The way that security drivers use XATTR is kind of verbose. If
error reporting was left for caller then the caller would end up
even more verbose.
There are two places where we do not want to report error if
virFileGetXAttr fails. Therefore virFileGetXAttrQuiet is
introduced as an alternative that doesn't report errors.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Cole Robinson <crobinso@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Problem with current approach is that if
qemuSecuritySetAllLabel() fails, then the @chown_paths and
@xattr_paths hash tables are not freed and preserve values
already stored there into the next test case.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
I don't really know what happened when I was writing the original
code, but even if error was to be set the corresponding boolean
was set to false meaning no error.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
One of the functions of this mock is that it spoofs chown() and
stat() calls. But it is doing so in a clever way: it stores the
new owner on chown() and reports it on subsequent stat(). This is
done by using a 32bit unsigned integer where one half is used to
store uid the other is for gid. Later, when stat() is called the
integer is fetched and split into halves again. Well, my bit
operation skills are poor and the code I've written does not do
that properly.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
This test is beautiful. It checks if we haven't messed up
refcounting on security labels (well, XATTRs where the original
owner is stored). It does this by setting up tracking of XATTR
setting/removing into a hash table, then calling
qemuSecuritySetAllLabel() followed by immediate
qemuSecurityRestoreAllLabel() at which point, the hash table must
be empty. The test so beautifully written that no matter
what you do it won't fail. The reason is that all seclabel work
is done in a child process. Therefore, the hash table in the
parent is never changed and thus always empty.
There are two reasons for forking (only one of them makes sense
here though):
1) namespaces - when chown()-ing a file we have to fork() and
make the child enter desired namespace,
2) locking - because of exclusive access to XATTRs we lock the
files we chown() and this is done in a fork (see 207860927a for
more info).
While we want to fork in real world, we don't want that in a test
suite. Override virProcessRunInFork() then.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
'viralloc.h' does not provide any type or macro which would be necessary
in headers. Prevent leakage of the inclusion.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
Quite a few of the tests have a need to mock the stat() / lstat()
functions and they are taking somewhat different & inconsistent
approaches none of which are actually fully correct. This is shown
by fact that 'make check' fails on 32-bit hosts. Investigation
revealed that the code was calling into the native C library impl,
not getting intercepted by our mocks.
The POSIX stat() function might resolve to any number of different
symbols in the C library.
The may be an additional stat64() function exposed by the headers
too.
On 64-bit hosts the stat & stat64 functions are identical, always
refering to the 64-bit ABI.
On 32-bit hosts they refer to the 32-bit & 64-bit ABIs respectively.
Libvirt uses _FILE_OFFSET_BITS=64 on 32-bit hosts, which causes the
C library to transparently rewrite stat() calls to be stat64() calls.
Libvirt will never see the 32-bit ABI from the traditional stat()
call. We cannot assume this rewriting is done using a macro. It might
be, but on GLibC it is done with a magic __asm__ statement to apply
the rewrite at link time instead of at preprocessing.
In GLibC there may be two additional functions exposed by the headers,
__xstat() and __xstat64(). When these exist, stat() and stat64() are
transparently rewritten to call __xstat() and __xstat64() respectively.
The former symbols will not actally exist in the library at all, only
the header. The leading "__" indicates the symbols are a private impl
detail of the C library that applications should not care about.
Unfortunately, because we are trying to mock replace the C library,
we need to know about this internal impl detail.
With all this in mind the list of functions we have to mock will depend
on several factors
- If _FILE_OFFSET_BITS is set, then we are on a 32-bit host, and we
only need to mock stat64 and __xstat64. The other stat / __xstat
functions exist, but we'll never call them so they can be ignored
for mocking.
- If _FILE_OFFSET_BITS is not set, then we are on a 64-bit host and
we should mock stat, stat64, __xstat & __xstat64. Either may be
called by app code.
- If __xstat & __xstat64 exist, then stat & stat64 will not exist
as symbols in the library, so the latter should not be mocked.
The same all applies to lstat()
These rules are complex enough that we don't want to duplicate them
across every mock file, so this centralizes all the logic in a helper
file virmockstathelper.c that should be #included when needed. The
code merely need to provide a filename rewriting callback called
virMockStatRedirect(). Optionally VIR_MOCK_STAT_HOOK can be defined
as a macro if further processing is needed inline.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
This test checks if security label remembering works correctly.
It uses qemuSecurity* APIs to do that. And some mocking (even
though it's not real mocking as we are used to from other tests
like virpcitest). So far, only DAC driver is tested.
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>