46 Commits

Author SHA1 Message Date
Miguel Pires
29c9752d66 many: s/ioutil.WriteFile/os.WriteFile (#13217)
Replace ioutil.WriteFile with os.WriteFile since the former has been
deprecated since go1.16 and simply calls the latter.

Signed-off-by: Miguel Pires <miguel.pires@canonical.com>
2023-09-26 11:38:46 +01:00
Valentin David
c9bbf25300 osutil: extract kcmdline to its own package 2023-07-31 16:40:56 +02:00
Alex Lewontin
041b90b183 bootloader: handle uboot envs both with and without header flag byte
Allows snapd to handle uboot envs for uboots with
CONFIG_SYS_REDUNDAND_ENV=n

Signed-off-by: Alex Lewontin <alex.lewontin@canonical.com>
2023-02-22 17:24:56 +01:00
alfonsosanchezbeato
4cc40898a9 b/piboot.go: check EEPROM version for RPi4
* b/piboot.go: check EEPROM version for RPi4

Check EEPROM version for RPi4 to make sure that tryboot is
supported. If the EEPROM need updating, return an error when
installing the kernel.

* bootloader: add unit tests for detection of RPi4 EEPROM

* bootloader/piboot: use osutil instead of using directly os.Stat

* bootloader: address review comments
2022-04-07 19:22:08 +02:00
Alfonso Sánchez-Beato
5519698c94 bootloader/piboot: simplify mocking of seed dir
Just using a variable is enough, intstead of simulating by a function.
2022-02-23 16:25:58 +01:00
Alfonso Sánchez-Beato
8c240a75aa bootloader: make sure to revert seed partition directory
Otherwise we could point to data from  previous test if not calling
again MockPibootFiles().
2022-02-23 16:23:53 +01:00
Alfonso Sánchez-Beato
f84a6ddb38 bootloader: add more tests for piboot 2022-01-26 14:54:57 +01:00
Alfonso Sánchez-Beato
429a2025c7 bootloader/piboot: use ubootenv for storing environment
Use uboot env files for storing piboot configuration. This reduces the
amount of new code and has the added benefit of having a checksum for
the file.
2021-11-19 16:34:15 +01:00
Alfonso Sánchez-Beato
c061d65550 bootloader: add piboot and pibootenv tests 2021-11-16 17:11:31 +01:00
Ian Johnson
89d3d02ec9 many: mv MockDeviceNameDisksToPartitionMapping -> MockDeviceNameToDiskMapping
This isn't mapping to partitions anymore, rather to a Disk itself.

Signed-off-by: Ian Johnson <ian.johnson@canonical.com>
2021-10-13 20:39:07 -05:00
Ian Johnson
06c8892536 osutil/disks, many: switch to defining Partitions directly for MockDiskMapping
This will be necessary for more complicated test cases in the gadget package,
so time to rip this band-aid and get rid of the old methods.

Signed-off-by: Ian Johnson <ian.johnson@canonical.com>
2021-10-13 20:30:31 -05:00
Ian Johnson
66ae3673cc bootloader/lk: add support for UC20 lk bootloader with V2 lkenv structs (#9695)
This commit adds support for the UC20 LittleKernel bootloader to snapd.

The big changes for using V2 are that we now use a secure bootloader set kernel
command line parameter to identify what disk to look for bootloader environment
structures, and that we use different lkenv structs for different role
bootloaders.

Eventually we should make V1 also use a secure bootloader set kernel command
line parameter to identify what disk to look for bootloader environment
structures on too, as using the partition label like this is vulnerable to
attack by attaching a USB disk with the same partition label to the system.

Signed-off-by: Ian Johnson <ian.johnson@canonical.com>

* bootloader/lk{,env}: use xerrors to make Load() err observable as ErrNotExist

Previously we would never continue in SetBootVars if the file doesn't exist
because we used fmt.Errorf which does not preserve the error type such that
os.IsNotExist would return true.

Now, we can continue to provide a customized error message from Load(), as well
as make SetBootVars continue and just write out a new file even if we can't read
the lkenv file in Load().

Signed-off-by: Ian Johnson <ian.johnson@canonical.com>

* many: rename disks.FindMatching... to FindMatching...WithFsLabel and err types

This is to accommodate a future FindMatching...WithPartLabel. Additionally, an
internal refactor to support storing additional properties for partitions when
we search a disk is implemented to allow for the additional future method.

The error type now is also more versatile to allow specifying what part failed,
searching for a partition by filesystem label or by partition label.

Signed-off-by: Ian Johnson <ian.johnson@canonical.com>

* osutil/disks: add FindMatchingPartitionUUIDFromPartLabel to Disk iface

This will enable searching for a partition with a given label on the provided
disk.

Signed-off-by: Ian Johnson <ian.johnson@canonical.com>

* bootloader/lk: search for partition labels on the bootloader disk, not fs labels

The partitions with the bootloader structures we care about do not have
filesystems on them, and as such they will not have filesystem labels. Instead,
they will have partition labels, and as such we should search using the
partition label instead.

Signed-off-by: Ian Johnson <ian.johnson@canonical.com>

* bootloader/lk: rename inRuntimeMode to prepareImageTime

This simplifies numerous functions to be more clear with the simpler
prepare-image time implementation happening first, then the complex runtime
cases happening afterwards are not indented as much.

Thanks to @bboozzoo for the suggestion.

Signed-off-by: Ian Johnson <ian.johnson@canonical.com>

* bootloader/lk.go: rename var

Thanks to @bboozzoo for the suggestion.

Signed-off-by: Ian Johnson <ian.johnson@canonical.com>

* bootloader/lk.go: fix handling of os.ErrNotExist everywhere, add comments

We should be using xerrors.Is() everywhere here, since the error returned is
wrapped.

However, for specifically RemoveKernelAssets, it's not a bug that we would skip
over os.ErrNotExist, but it would result in a more confusing error message - we
should try to give better error messages, and returning early with
os.ErrNotExist is more useful to the user than the existing error around not
being able to find the specified kernel blob.

Signed-off-by: Ian Johnson <ian.johnson@canonical.com>

* bootloader/lk.go: move prepare-image check earlier in ExtractRecoveryKernelAssets

Thanks to @bboozzoo for the recommendation.

Signed-off-by: Ian Johnson <ian.johnson@canonical.com>

* osutil/disks/disks_linux.go: adjust comment about optional partition labels

Thanks to @bboozzoo for clarifying this for me. Partition labels are optional on
GPT partitions.

Signed-off-by: Ian Johnson <ian.johnson@canonical.com>

* osutil/disks/disks.go: fix typo

Thanks to @bboozzoo for catching this.

Signed-off-by: Ian Johnson <ian.johnson@canonical.com>

* osutil/disks/disks_linux.go: add some TODOs about things to cleanup/simplify

Signed-off-by: Ian Johnson <ian.johnson@canonical.com>

* osutil/disks/disks_linux.go: add comments about the encoding of the udev props

Thanks to @bboozzoo for the suggestion.

Signed-off-by: Ian Johnson <ian.johnson@canonical.com>

* osutil/disks/mockdisk.go: fix typo

Thanks to @bboozzoo again for spotting all my typos :-)

Signed-off-by: Ian Johnson <ian.johnson@canonical.com>

* osutil/disks: add FindMatchingPartitionUUIDFromPartLabel to Disk iface

This will enable searching for a partition with a given label on the provided
disk.

Signed-off-by: Ian Johnson <ian.johnson@canonical.com>

* many: fix rename of disks pkg function name from rebase

Signed-off-by: Ian Johnson <ian.johnson@canonical.com>

* bootloader/lk: don't use l.rootdir for the returned partition file

Using l.rootdir here was wrong in that it would produce for RoleRunMode
bootloaders paths like /run/mnt/ubuntu-boot/dev/disk/by-partuuid/1234, instead
of the correct path of /dev/disk/by-partuuid/... at runtime.

We didn't catch this in tests because we pass in the same rootdir as what we
test for, we didn't test passing in boot.InitramfsUbuntuBootDir for example, so
change the tests to account for this.

Signed-off-by: Ian Johnson <ian.johnson@canonical.com>

* bootloader/lkenv: add compatibility error impl for Go 1.9

Go 1.9 os.PathError does not implement Unwrap(), so using
xerrors.Is(err,os.ErrNotExist) does not work, as Is() calls Unwrap() in a loop,
waiting for either the error returned to be equal to the target error or to be
nil, and in the case of Go 1.9, where os.PathError does not implement Unwrap(),
then nil is returned and Is() returns false.

We can work around this by implementing Unwrap() on our own error type and
specifically returning os.ErrNotExist on Go 1.9 when we know the error is
actually os.ErrNotExist.

This will make the unit tests with Go 1.9 pass.

Signed-off-by: Ian Johnson <ian.johnson@canonical.com>

* bootloader/lk: use specific backup file for lkenv

For UC20 runtime, the backup file will be a different partition, and since we
are using partition uuid symlinks instead of partition labels, we can't just
append "bak" to the primary env file, and instead need to manually provide the
backup file.

Also add a test which validates that the backup env file for run mode on uc20 is
handled appropriately and updated.

Signed-off-by: Ian Johnson <ian.johnson@canonical.com>

* bootloader/lk: add test scaffolding and TODO about recovery system add/remove

Signed-off-by: Ian Johnson <ian.johnson@canonical.com>

* bootloader/lk.go: adjust comments

Signed-off-by: Ian Johnson <ian.johnson@canonical.com>

* bootloader/lkenv/lkenv.go: change XXX to TODO

Signed-off-by: Ian Johnson <ian.johnson@canonical.com>

* bootloader/lkenv/lkenv.go: inspect the err in compatErrNotExist for Unwrap()

Instead of checking the version of Go we were compiled with which is weird, we
can instead just check for the exact thing we know doesn't work, which is that
os.PathError doesn't implement Unwrap(), so if it doesn't implement Unwrap(), we
know we are in a legacy version of Go and thus should do the manual unwrapping
to return ErrNotExist directly.

Signed-off-by: Ian Johnson <ian.johnson@canonical.com>

* bootloader/lk: refactor helper methods

This refactors some helper methods to be more clear, namely that envFile becomes
envBackstore, and it takes an argument for whether or not it is returning the
primary or the backup, and eliminating the specific method for getting the
backup file, as well as combining some codepaths in the other helpers to be more
easily readable if slightly redundant in terms of actual code execution.

Signed-off-by: Ian Johnson <ian.johnson@canonical.com>

* bootloader/lk: move some function definitions around for conventions' sake

Signed-off-by: Ian Johnson <ian.johnson@canonical.com>

* bootloader/lk: adjust comment to explain we should try to use kernel cmdline

It might not be there on older gadget bootloaders which don't set that kernel
command line value and as such we will have to fallback to our current behavior.

Signed-off-by: Ian Johnson <ian.johnson@canonical.com>

* bootloader/lkenv/lkenv.go: fix for gofmt 1.9

Signed-off-by: Ian Johnson <ian.johnson@canonical.com>

* bootloader/lk: update handling of os.ErrNotExist for various cases

The only case where we can really proceed without having an initial env file is
at prepare image time when the bootloader env file doesn't exist, as we could be
writing an empty/new one. All other cases we need the file to exist as a
pre-requisite, if only for accurate error reporting.

Signed-off-by: Ian Johnson <ian.johnson@canonical.com>

* bootloader/lk.go: rename variable, simplify return statement

Thanks to @pedronis for the suggestion.

Signed-off-by: Ian Johnson <ian.johnson@canonical.com>

* bootloader/lk.go: implement TODO about checking the backup file in Present()

Signed-off-by: Ian Johnson <ian.johnson@canonical.com>

* bootloader/lk.go: re-word awkwardly phrased TODO about using kernel cmdline

Signed-off-by: Ian Johnson <ian.johnson@canonical.com>

* bootloader/lk_test.go: add unit test for Present() RoleSole checking backup

Signed-off-by: Ian Johnson <ian.johnson@canonical.com>

Co-authored-by: Maciej Borzecki <maciej.zenon.borzecki@canonical.com>
2020-12-04 20:50:28 +01:00
Ian Johnson
dbf5dd36db bootloader/lkenv: specify backup file as arg to NewEnv(), use "" as path+"bak"
To simplify existing code, use "" as the backup file to mean path+"bak".

Also add tests that when specifying a non-empty string as the backup file that
we don't use the legacy backup file handling logic.

Signed-off-by: Ian Johnson <ian.johnson@canonical.com>
2020-12-01 20:03:08 -06:00
Ian Johnson
5e70102321 Merge branch 'master' into feature/uc20-lk-bootloader-3-take-2
Signed-off-by: Ian Johnson <ian.johnson@canonical.com>
2020-11-24 11:39:32 -06:00
Ian Johnson
b05b054489 bootloader/lkenv: major refactor of lkenv
Refactor the lkenv package to use a better abstraction of the boot image
partition matrices that are common between the kernel revision for v1 and v2
run and the recovery system label for v2 recovery.

Also rename many methods to better match the naming scheme and consistently use
"boot image partitions" or "boot image partition labels" to refer to the first
row in the matrix, with value generically being the second row, which can either
be a kernel snap revision or a recovery system label.

Also make the signature for v2 recovery struct a separate value to be able to
indicate which lkenv object is which if we ever need to import or read an
arbitrary file, we can know which one it is from the bits alone.

Signed-off-by: Ian Johnson <ian.johnson@canonical.com>
2020-11-23 17:12:50 -06:00
Ian Johnson
9767c7871d bootloader/lkenv: support v2 environment structs, specify v1 from lk.go
This does not yet use v2 environment structs, but enables them for use later on.

V2 structs are used when creating the lkenv, and many functions switch on which
object they actually operate on from which version of the lkenv is used.

The unit testing is not complete, but will be completed in a followup commit.

Signed-off-by: Ian Johnson <ian.johnson@canonical.com>
2020-11-20 09:04:31 -06:00
Ian Johnson
5a717a278a bootloader: refactor static set of bootloaders to list instead of a map
This is simpler and avoids from having to maintain the list of names of
bootloaders in three locations, one in the bootloader implementation itself, one
in the gadget.yaml bootloader setting, and one in Find(). Now we just have the
bootloader implementation and the gadget.yaml validator.

Signed-off-by: Ian Johnson <ian.johnson@canonical.com>
2020-11-20 09:03:22 -06:00
Ian Johnson
e4ab1c5ca9 bootloader/many: rm ConfigFile, add Present for indicating presence of bloader
Now we have a specific method on the Bootloader interface which tells Find()
whether the specific bootloader is actually present on the current system. This
will simplify future bootloader implementations to be able to return errors when
identifying if a bootloader is present on the system is more complicated a
question than just if the config file for that bootloader exists.

Signed-off-by: Ian Johnson <ian.johnson@canonical.com>
2020-11-19 15:39:56 -06:00
Maciej Borzecki
05de6a44a2 bootloader: docstrings, TODOs, tweaks
Signed-off-by: Maciej Borzecki <maciej.zenon.borzecki@canonical.com>
2020-08-12 15:01:01 +02:00
Maciej Borzecki
3ca692ed30 bootloader: add helper for creating a bootloader based on gadget
The bootloader.Find() expects bootloader configuration to be present in the root
directory. However, when we are installing a run mode system, the bootloader
config is not present until after InstallBootConfig() gets called, which happens
only after the filesystem has been created and populated. However, when using
the ContentObserver to track trusted assets, we must know what the bootloader
is.

Add a helper for creating a bootloader based on what is carried by the gadget.
Move the basic checks for config file existence to Find().

Signed-off-by: Maciej Borzecki <maciej.zenon.borzecki@canonical.com>
2020-08-12 14:16:42 +02:00
Maciej Borzecki
08570477d2 bootloader/grub: drop unnecessary validation of mode and system arguments
Signed-off-by: Maciej Borzecki <maciej.zenon.borzecki@canonical.com>
2020-07-27 17:56:30 +02:00
Maciej Borzecki
e506c46135 bootloader/grub: have mode and system be passed explicitly in CommandLine()
Signed-off-by: Maciej Borzecki <maciej.zenon.borzecki@canonical.com>
2020-07-27 16:30:02 +02:00
Maciej Borzecki
58d2df4a32 bootloader: use internally tracked, per edition static command line arguments
Signed-off-by: Maciej Borzecki <maciej.zenon.borzecki@canonical.com>
2020-07-15 17:14:51 +02:00
Maciej Borzecki
dc2509b69f bootloader: more strict validation of mode arguments
Signed-off-by: Maciej Borzecki <maciej.zenon.borzecki@canonical.com>
2020-07-15 08:40:21 +02:00
Maciej Borzecki
b26f2ade50 bootloader/grub: implement composing of grub command line
The patch implements a helper for composing the kernel command line when using a
grub bootloader.

The command line is composed of 3 main elements, the static part defined in the
boot asset, plus extra arguments (usually set by snapd in the boot environment)
and mode arguments

Signed-off-by: Maciej Borzecki <maciej.zenon.borzecki@canonical.com>
2020-07-14 09:53:43 +02:00