As of glibc 2.25, warnings will be emitted at compile time to state
that you must explicitly include the header now, due to libraries
tending to have their own definitions.
Signed-off-by: Ikey Doherty <michael.i.doherty@intel.com>
Prior to this change, the kernel and initrd paths were not using the
namespace directory during kernel removal, leading to assets being left
on the disk and filling up the ESP with junk that could not be reclaimed.
This change introduces the simple fix, as well as the UEFI specific test
to ensure that the files are being removed.
Signed-off-by: Ikey Doherty <michael.i.doherty@intel.com>
Now that we no longer write out separate GRUB2 entry files, we have a simple
test to ensure that the old GRUB2 files get removed, and that only the new
one is used.
Signed-off-by: Ikey Doherty <michael.i.doherty@intel.com>
With a GPT disk, in native mode, we should ensure that we only use syslinux
if the native system isn't actually UEFI. This test will account for that,
in preparation for issue #58.
Signed-off-by: Ikey Doherty <michael.i.doherty@intel.com>
In accordance with issue #53, we must only use the PartUUID for root=
entries when we *know* that the partition definitely resides on a GPT
disk.
Whilst an EFI System Partition must live on a GPT disk to be considered
a valid ESP, there is no such constraint on the rootfs itself. Cases
emerged during testing of an MBR rootfs partition, with a GPT disk used
to house the ESP itself.
This change ensures we only ever write a root=PARTUUID if we're fully
certain of the topology, otherwise all bootloaders will automatically
fall back to root=UUID entries.
Signed-off-by: Ikey Doherty <michael.i.doherty@intel.com>
This test exposes bugs within the core cbm_inspect_root function, by
validating exactly *which* bootloader we select depending on the system
topology.
The tests show that the majority of cases are handled properly, however
when encountering a UEFI system, and we have not been able to explicitly
find the ESP (which is allowed to be mounted already), we fail to select
the UEFI capability, and *very* incorrectly fallback to GRUB2.
Obviously this is highly broken but the test suite is required to develop
the correct functionality, whilst being able to validate changes for *all*
of the possible configurations.
This test is required for issue #54.
Signed-off-by: Ikey Doherty <michael.i.doherty@intel.com>
This mechanism is used as a fallback when all other methods are unavailable,
i.e. a non GPT non UEFI disk. The basic workflow is as follows:
- Create /etc/grub.d/10_* files containing our wanted boot configuration
- Add necessary shell script glue for grub-mkconfig environment
- Remove any default /vmlinuz /initrd.img symlinks for "default" detection
- Invoke "grub-mkconfig" to cause the grub.d files to be executed
- Restore default /vmlinuz /initrd.img symlinks for dual boot compatibility
The separate namespacing ensures GRUB can never *natively* detect the CBM
managed kernels, and we're free to integrate in this fashion. Due to a number
of severe limitations in the GRUB2 machinery & tooling, we do NOT manage the
actual bootloader itself, rather, the entries for boot.
The GRUB2 bootloader should be installed by the operating system installer and
managed outside the domain of CBM. In the world of UEFI we're able to provide
automatic bootloader updates due to enforced sanity in the protocols and
specifications available to us. In the legacy world, we'd have to consider
a plethora of locations for, and versions of, GRUB2, to provide the binary
management. Thus, it is considered out of scope.
Another key limitation to this approach is that CBM should really be invoked
in "native" mode, that is to say, with chroot from installer or on the native
host. This is due to grub-mkconfig hardcoding the locations of the script
assets to host-side only. An OS installer should chroot into the environment
before invoking "clr-boot-manager update".
Signed-off-by: Ikey Doherty <michael.i.doherty@intel.com>
In order to meet full UEFI compliance, and to enable secure boot, we must
now install our kernel/initrd assets within the /EFI directory on the ESP.
Additionally, we must maintain our unique namespace within this tree to
avoid collisions and allow sane dual boot strategies.
This change moves kernels + initrds to /EFI/$NAMESPACE, i.e.
/EFI/org.clearlinux. To ensure a sane upgrade experiene, we'll now attempt
to non-fatally remove the *old* kernel bits once we've successfully
installed or removed a given kernel.
To better match the use of the 'initrd-' prefix, the new kernels are
prefixed with 'kernel-' but retain much of the name structure. A full test
is also introduced for this UEFI-specific change, which first performs a
simulated install to the legacy paths, and then attempts an upgrade to the
new namespace, while ensuring retention policies. Care is taken within the
test to ensure old files *are* removed.
Signed-off-by: Ikey Doherty <michael.i.doherty@intel.com>
This completely broke the condition to effectively return true == true.
Luckily our *current* tests still pass with this change, however it was
discovered when introducing namespacing.
Signed-off-by: Ikey Doherty <michael.i.doherty@intel.com>
This change introduces some namespacing within the Kernel struct itself
so that members are now accessed by "->source." and "->meta." to keep them
organised. This makes it far simpler to see *what* is being manipulated as
well as the intent.
This will be followed up with some more changes to include the target fields
as an anonymous struct too, which will help in reducing the duplication in
the various basename/copy/ approaches seen throughout the codebase.
Signed-off-by: Ikey Doherty <michael.i.doherty@intel.com>
We may, in certain dual boot scenarios, encounter paths on the ESP that
we don't expect. Previously the use of nc_build_case_correct_path was
relied upon for this, to ensure that even if a directory "EFI" is called
"efi" on the FAT32 ESP, we use the "efi" name, to satisfy both the FAT32
case ignorance, and Linux case sensitive, requirements.
However testing shows that we only actually init the paths *before* mounting
any ESP, meaning we are case sensitive. This test suite change then forces
deliberately case-incorrect paths, and forces clr-boot-manager to compensate
by building the case correct paths.
The next change will change clr-boot-manager to correctly reinit the bootloader
with the newly available paths post-mount stages to ensure we fix this newly
introduced test failure.
Signed-off-by: Ikey Doherty <michael.i.doherty@intel.com>
This will help in recovering the coverage numbers that have been lost to
untestable malloc-failure codepaths, by continuing to do exactly the same
thing as before: if malloc-fail, abort().
This also makes the code far simpler and more pleasant to navigate and
removes a huge number of the abort calls from the codebase. Some still
exist but they are both minimal and obvious.
This small, seemingly trivial change, restores almost 2% coverage in the
codebase testing.
Signed-off-by: Ikey Doherty <michael.i.doherty@intel.com>
We now just leverage the existing defines at build time due to our
new-lack of architecture-size specific support, making the codebase
significantly less complicated.
Signed-off-by: Ikey Doherty <michael.i.doherty@intel.com>
To ensure that new tests are less complex, and that there are no unknown
parameters in the test system, we move all initial bootloader setup to
the test harness.
Additionally, we now ensure we setup the bootloader based on whether the
UEFI configuration is selected, and fallback to syslinux propagation when
this isn't the case. Now all tests are tailored explicitly to use UEFI
or syslinux legacy, leaving less room for error/guesswork.
Signed-off-by: Ikey Doherty <michael.i.doherty@intel.com>
This test ensures that the UEFI-specific bootloader removal functionality
does as advertised, and truly does remove all of our "bits" from the
target system when requested.
This test is distinctly more messy than the current tests as it has to
know exactly which files should be gone due to the opaque bootloader
system.
Signed-off-by: Ikey Doherty <michael.i.doherty@intel.com>
These tests verify the basic install & update functionality for the
bootloaders, not the kernels. It should be noted that in the case of
syslinux, we have a restricted feature-set. As such we *always* report
that syslinux needs an update when the source file changes, because
it's far cheaper than actually reading the block device itself.
This change also addresses the gptmbr bin file being 1 byte too long,
which was revealed during the development of this test.
Signed-off-by: Ikey Doherty <michael.i.doherty@intel.com>
This test enables us to mock the upgrade process going from a non CBM
managed system to a CBM managed one, for the first update. Importantly,
it ensures that the kernel transition itself works fine.
Signed-off-by: Ikey Doherty <michael.i.doherty@intel.com>
This test checks the basic kernel install functionality in native mode
for both legacy & UEFI boot systems. It is not a comprehensive policy
test.
Signed-off-by: Ikey Doherty <michael.i.doherty@intel.com>
This mimics the check-legacy test almost identically, but taking the
inverse road in certain areas to cater specifically for UEFI. Notably,
it also ensures that Legacy Boot is not detected.
This change will allow us to begin fleshing the main test suites out
in parallel to ensure they do not drift.
Signed-off-by: Ikey Doherty <michael.i.doherty@intel.com>
This allows humans to look at the generate files during test suite
creation and actually understand what is happening, instead of dealing
with arbitrary version numbers.
Signed-off-by: Ikey Doherty <michael.i.doherty@intel.com>
This test adds very basic coverage for doing a basic image installation,
using the syslinux legacy path.
Signed-off-by: Ikey Doherty <michael.i.doherty@intel.com>
We now create the relevant GPT structure to allow CBM to detect a legacy
boot device. Currently this is only used for the syslinux bootloader, but
in future will be extended to permit GRUB too.
Signed-off-by: Ikey Doherty <michael.i.doherty@intel.com>
This change adds a new skeletal test designed specifically for the
legacy boot codepath. It deliberately fails right now as it constructs
a mocking environment whereby CBM cannot find UEFI *or* legacy boot.
Thus, the following changes will focus on adding the relevant mocking
support for legacy boot, i.e. via syslinux.
Signed-off-by: Ikey Doherty <michael.i.doherty@intel.com>
This modifies the harness to initialise UEFI mocking only when specified
in the PlaygroundConfig. As such this now allows us to introduce some
deliberately failing test to allow construction of a legacy mocking codepath.
Signed-off-by: Ikey Doherty <michael.i.doherty@intel.com>
All of these tests are actually duplicated in the core of any other
install/remove/update tests we'll define now in our replacement tests.
Thus, by themselves, are completely pointless.
Signed-off-by: Ikey Doherty <michael.i.doherty@intel.com>
This test suite asks all the wrong questions and is very much tied
to the old architecture. Thus, we remove it, to pave the way for some
better, more specific, test suites, using full mocking.
Signed-off-by: Ikey Doherty <michael.i.doherty@intel.com>
Prior to our mocking abilities we had to inject a custom systeminfo
definition. However, this masks the blkid ops vtable and makes debugging
difficult. As such, we remove this code and rely entirely on the internal
checks being performed.
Signed-off-by: Ikey Doherty <michael.i.doherty@intel.com>
For now we'll force detection of a "valid" UEFI system by constructing
a fake devfs/sysfs to fool the clr-boot-manager code into following our
mocking functions to get UUID, etc, for a fake boot device.
Signed-off-by: Ikey Doherty <michael.i.doherty@intel.com>
In order to facilitate mocking, we must stop hardcoding /sys and /dev
paths. Unfortunately, these are the *right* paths to use in real life.
However, during testing, we most certainly do not want to use the host-side
virtual filesystems.
As such we change our assumptions and ensure /sys and /dev are baked in
constants in the test suite and internal to CBM, allowing us to now populate
fake vfs trees. Additionally, this will allow us to turn on and disable the
"UEFI support" in clr-boot-manager.
Signed-off-by: Ikey Doherty <michael.i.doherty@intel.com>
This allows us to mock the return location for a /dev/ node per the stat
calls, enabling the full blkid / check loop to run.
Signed-off-by: Ikey Doherty <michael.i.doherty@intel.com>
Now that we only use mount/umount family via the system vfunc table, we
can safely push these calls to any replacement function without actually
calling the system functions, helping to improve coverage.
Signed-off-by: Ikey Doherty <michael.i.doherty@intel.com>
This default harness makes the system vtable ops all return as being
successful, allowing us to unblock mount/umount/system syscalls for
further coverage testing.
Signed-off-by: Ikey Doherty <michael.i.doherty@intel.com>
In order to facilitate safety and coverage, we now override all aspects
of blkid during testing, allowing a certain level of coverage. Each test
case will then be able to extend the default table to enhance coverage.
Signed-off-by: Ikey Doherty <michael.i.doherty@intel.com>
With the move to CbmDeviceProbe API, this functionality is no longer
necessary within clr-boot-manager.
Signed-off-by: Ikey Doherty <michael.i.doherty@intel.com>
In order to facilitate a more flexible approach to the root devices, we
now make use of the CbmDeviceProbe. This in turn allows us to dynamically
determine whether to use the UUID or PartUUID depending on the disk
configuration.
Signed-off-by: Ikey Doherty <michael.i.doherty@intel.com>
In order to help reduce the complexity of clr-boot-manager, much of which
actually revolves around handling string and malloc failures, we now add
a new CbmWriter type.
Effectively, this is a memory based write stream, designed to allow failure.
It is designed to allow multiple append/printf style invocations, and then
only testing for memory failures when this has all been done. As such this
can vastly simplify the obtuse code used to build up configuration files
within clr-boot-manager (syslinux handler being a perfect example.)
The style of the API usage largely follows that of the CbmMappedFile system,
in attempting to avoid as many copies as possible, by using a pointer to an
anonymous stack struct, and associated open/close methods. Due to the way
that the memstream API works, we require both a free *and* a close.
The close method is responsible for finalizing the buffer, and cleaning up
the associated file resource. This in turn ensures the null terminator is
placed into the final buffer. The free method is then hooked up into the
autofree system to ensure we never leak.
Signed-off-by: Ikey Doherty <michael.i.doherty@intel.com>
This change adds preliminary support for initial ramdisk files in
distributions that make use of them. It is expected that the initrd
file suffix match the kernel path, and be prefixed with "initrd-".
This should be shipped within the kernel packaging or deployment
mechanism in the distribution. As such it removes a great deal of
scope for error, by ensuring the initrd's are sane at source, and
not rely on initrd generation on the installation (i.e. via use of
dracut.)
As users may actually have requirements for overwriting their initramfs,
we'll first look for the file in /etc/kernel and use that, otherwise we
will fallback to the distribution provided file.
Upon removal, the user's initrd is left intact, and we only remove the
files within our own domain.
Signed-off-by: Ikey Doherty <michael.i.doherty@intel.com>
Recent changes have made CBM read files from /etc/kernel, such as the
cmdline. Keeping in line with this simpler approach, i.e. "echo >" and
upgrade, we use a simpler filename.
To enhance ease of use, we'll also create the /etc/kernel directory if
it doesn't already exist, so that there are less steps involved for the
user.
Signed-off-by: Ikey Doherty <michael.i.doherty@intel.com>
To make it easier to manipulate the cmdline that is emitted into the
per-kernel boot entries, we add a new parser to clr-boot-manager. This
parser will be responsible in future for loading a *per kernel* cmdline,
as well as loading a global system cmdline.
The first file to be read will always be /etc/kernel/cmdline, and after
this the files in /etc/kernel/cmdline.d/*.conf will be read in, which is
then merged into a single cmdline line.
The file format permits new lines and comments, which are stripped from
the emitted text. It also takes care to skip unnecessary whitespace,
allowing the cmdline to be built in layers from various locations.
Two immediate consequences arise: The ability for the user to append to
the default kernel cmdline, and the ability for vendors to provide
quirks and such by default, without modifying kernel packages or CBM
itself.
Signed-off-by: Ikey Doherty <michael.i.doherty@intel.com>
To keep an eye on things, we ensure that os-release is always used, even
within our own playground test suite. Human validation simply needs to
check that we're still using the "clr-boot-manager testing" string in
the playground root loader files for peace of mind.
Signed-off-by: Ikey Doherty <michael.i.doherty@intel.com>
Instead of hard-coding the OS ID into clr-boot-manager at build time,
we'll be able to use the standardised {/etc/,/usr/lib/}os-release file
to provide updated OS identity information.
This change adds the os-release parser, which takes steps to ensure that
only predefined sane keys are used, and that value keys never have NULL
values.
In the absence of all configuration, an empty map is returned to allow
the library to make use of default values and not rely on extensive
error handling in multiple locations, making the change far less
invasive.
Signed-off-by: Ikey Doherty <michael.i.doherty@intel.com>
Much of our low coverage rate can be attributed to using an imported version
of libnica, without the test suites. This change incorporate much of the nica
test suite for the core types that we utilize.
Signed-off-by: Ikey Doherty <michael.i.doherty@intel.com>
It's currently ambiguous and unreliable what we truly mean with the
negated test for asprintf. Per the documentation, we should check that
the return was less than zero, indicating an issue with the asprintf
call itself.
This is also more helpful to tooling that would look at the return code
for branch prediction to more clearly state what the negative path would
actually be.
As a side note, it may be wise to increase the column limit in our
clang-format following this change, as some of it is quite clearly
..odd.
Signed-off-by: Ikey Doherty <michael.i.doherty@intel.com>
This is just part of improving coverage within clr-boot-manager, and is
a critical requirement given that we have changed how we determine that
two files differ.
With that said, we still do have the test harness that makes heavy use of
cbm_files_match, and one can clearly see that by deliberately inverting
logic in paths within cbm_files_match, the harness tests then completely
fail.
Signed-off-by: Ikey Doherty <michael.i.doherty@intel.com>