Skip to content

Commit d314440

Browse files
authored
Remove all references to old dm-verity boot tooling [1/3] (#10973)
1 parent 32d38c5 commit d314440

26 files changed

Lines changed: 72 additions & 1319 deletions

File tree

toolkit/docs/formats/imageconfig.md

Lines changed: 4 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ Sample partitions entry, specifying a boot partition and a root partition:
8383
- `grub` indicates this is a grub boot partition
8484
- `bios_grub` indicates this is a bios grub boot partition
8585
- `boot` indicates this is a boot partition
86-
- `dmroot` indicates this partition will be used for a device mapper root device (i.e. `Encryption` or `ReadOnlyVerityRoot`)
86+
- `dmroot` indicates this partition will be used for a device mapper root device (i.e. `Encryption`)
8787

8888
#### TypeUUID
8989

@@ -259,7 +259,7 @@ The `OverrideRpmLocales` and `DisableRpmDocs` settings are stored in `/usr/lib/r
259259

260260
The tools offer the option of executing arbitrary shell scripts during various points of the image generation process. There are three points that scripts can be executed: `PreInstall`, `PostInstall`, and `ImageFinalize`.
261261

262-
>Installer starts -> `PreInstallScripts` -> Create Partitions -> Install Packages -> `PostInstallScripts` -> Configure Bootloader (if any) -> Calculate dm-verity hashes (if configured) -> `ImageFinalizeScripts`
262+
>Installer starts -> `PreInstallScripts` -> Create Partitions -> Install Packages -> `PostInstallScripts` -> Configure Bootloader (if any) -> `ImageFinalizeScripts`
263263
264264
Each of the `PreInstallScripts`, `PostInstallScripts`, and `FinalizeImageScripts` entires are an array of file paths and the corresponding input arguments. The scripts will be executed in sequential order and within the context of the final image. The file paths are relative to the image configuration file. Scripts may be passed without arguments if desired.
265265

@@ -416,58 +416,9 @@ A sample KernelOptions specifying a default kernel:
416416

417417
### ReadOnlyVerityRoot
418418

419-
"ReadOnlyVerityRoot" key controls making the root filesystem read-only using dm-verity.
420-
It will create a verity disk from the partition mounted at "/". The verity data is stored as
421-
part of the image's initramfs. More details can be found in [Misc: Read Only Roots](../how_it_works/5_misc.md#dm-verity-read-only-roots)
419+
ReadOnlyVerityRoot has been deprecated in the image configuration. The feature is suppored in the [Azure Linux Image Customizer](../../tools/imagecustomizer/README.md) tool now.
422420

423-
#### Considerations
424-
425-
Having a read-only root filesystem will change the behavior of the image in some fundamental ways. There are several areas that should be considered before enabling a read-only root:
426-
427-
##### Writable Data
428-
429-
Any writable data which needs to be preserved will need to be stored into a separate writable partition. The `TmpfsOverlays` key will create throw-away writable partitions which are reset on every boot. The example configs create an overlay on `/var`, but the more refined the overlays are, the more secure they will be.
430-
431-
##### GPL Licensing
432-
433-
If using a read-only root in conjunction with a verified boot flow that uses a signed initramfs, carefully consider the implications on GPLv3 code. The read-only nature of the filesystem means a user cannot replace GPLv3 components without re-signing a new initramfs.
434-
435-
##### Users
436-
437-
Since users are controlled by files in `/etc`, these files are read-only when this is set. It is recommended to either use SSH key based login or pre-hash the password to avoid storing passwords in plain text in the config files (See [Users](#users)).
438-
439-
##### Separate `/boot` Partition
440-
441-
Since the root partition's hash tree is stored as part of the initramfs, the initramfs cannot be stored on the same root partition (it would invalidate the measurements). To avoid this a separate `/boot` partition is needed to house the hash tree (via the initramfs).
442-
443-
##### ISO
444-
445-
The ISO command line installer supports enabling read-only roots if they are configured through the configuration JSON file (see [full.json's](../../imageconfigs/full.json) `"Azure Linux Core Read-Only"` entry). The automatic partition creation mode will create the required `/boot` partition if the read-only root is enabled.
446-
447-
The GUI installer does not currently support read-only roots.
448-
449-
- `Enable`: Enable dm-verity on the root filesystem
450-
- `Name`: Custom name for the mounted root (default is `"verity_root_fs"`)
451-
- `ErrorCorrectionEnable`: Enable automatic error correction of modified blocks (default is `true`)
452-
- `ErrorCorrectionEncodingRoots`: Increase overhead to increase resiliency of the forward error correction (default is `2` bytes of code per 255 bytes of data)
453-
- `RootHashSignatureEnable`: Validate the root hash against a key stored in the kernel's system keyring. The signature file should be called `<Name>.p7` and must be stored in the initramfs. This signature WILL NOT BE included automatically in the initramfs. It must be included via an out of band build step.
454-
- `ValidateOnBoot`: Run a validation of the full disk at boot time, normally blocks are validated only as needed. This can take several minutes if the disk is corrupted.
455-
- `VerityErrorBehavior`: Indicate additional special system behavior when encountering an unrecoverable verity corruption. One of `"ignore"`, `"restart"`, `"panic"`. Normal behavior is to return an IO error when reading corrupt blocks.
456-
- `TmpfsOverlays`: Mount these paths as writable overlays backed by a tmpfs in memory.
457-
- `TmpfsOverlaySize`: Maximum amount of memory the overlays may use. Maybe be one of three forms: `"1234"`, `"1234[k,m,g]"`, `"20%"` (default is `"20%"`)
458-
- `TmpfsOverlayDebugEnabled`: Make the tmpfs overlay mounts easily accessible for debugging purposes. They can be found in /mnt/verity_overlay_debug_tmpfs. Include the
459-
`verity-read-only-root-debug-tools` package to create the required mount points.
460-
461-
A sample ReadOnlyVerityRoot specifying a basic read-only root using default error correction. This configuration may be used for both normal images and ISO configurations:
462-
463-
``` json
464-
"ReadOnlyVerityRoot": {
465-
"Enable": true,
466-
"TmpfsOverlays": [
467-
"/var"
468-
],
469-
},
470-
```
421+
See [Azure Linux Image Customizer configuration](../../tools/imagecustomizer/docs/configuration.md#verity-type) for more information.
471422

472423
### KernelCommandLine
473424

toolkit/docs/security/intro.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,3 @@ Below topics are dedicated to security-related details of the operating system.
44

55
## 1. [Security features](security-features.md)
66
## 2. [SSL CA certificates management](ca-certificates.md)
7-
8-
## 3. [Read-Only Roots](read-only-roots.md)
Lines changed: 2 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -1,111 +1,6 @@
11
Read-Only Roots
22
===
33

4-
- [dm-verity Read Only Roots](#dm-verity-read-only-roots)
5-
- [Creating Verity Disks](#Creating-Verity-Disks)
6-
- [Writable Areas](#Writable-Areas)
7-
- [Root of Trust](#Root-of-Trust)
8-
- [Users, Machine ID, Misc. Configuration](#Users-Machine-ID-Misc-Configuration)
9-
- [Forward Error Correction (FEC)](#Forward-Error-Correction-(FEC))
10-
- [Hash Tree and FEC Overhead](#Hash-Tree-and-FEC-Overhead)
11-
- [Debugging](#Debugging)
12-
- [ISO Installers](#ISO-Installers)
4+
ReadOnlyVerityRoot has been deprecated in the image configuration. The feature is suppored in the [Azure Linux Image Customizer](../../tools/imagecustomizer/README.md) tool now.
135

14-
## dm-verity Read Only Roots
15-
`dm-verity` is a Device Mapper target which creates read-only partitions with built-in integrity checking. This means a verity partition can detect (and if FEC is enabled, fix) changes to the data in the partition.
16-
17-
A Merkle hash tree is created from the measurements of each block in the partition (Hash each 4k block, then hash those hashes. Repeat until you have a single hash). The root node of the tree, a single hash, is called the `root hash`.
18-
19-
When data is read from disk the blocks are hashed and checked against the hash tree to detect any changes. Any change to a block will modify its branch of the tree, all the way down to the root hash. By securing the root hash the entire partition can be secured.
20-
21-
### Creating Verity Disks
22-
Read-only roots can be enabled using the `"ReadOnlyVerityRoot"` key in the image configuration JSON file (See [imageconfig.md](../formats/imageconfig.md#ReadOnlyVerityRoot) for details)
23-
Since the read-only partition becomes unmodifiable as soon as it's measured, the snapshot must be taken at the very end of the build process. The `imager` tool switches the root to read-only mode, then uses the `veritysetup` tool to measure the root into a hash tree, FEC data, and compute the root hash. These files are then placed into the `initramfs`.
24-
25-
Any non-standard modifications to the image (adding symlinks, generating custom machine IDs, changing configs, etc.) need to be made prior to this point by using the `"PostInstallScripts"` key in the image config.
26-
27-
### Writable Areas
28-
The build system currently supports two types of writable areas which are useful for read-only verity disks:
29-
30-
#### Temporary Overlays
31-
Passing a list of directories using the `"TmpfsOverlays"` key in the `"ReadOnlyVerityRoot"` config will cause the initramfs to add `tmpfs` based writable overlays to each listed directory. These overlays are backed in RAM and will be reset after a reboot. These are useful for logging, or other transient data that is not security critical. Ideally the overlays should be kept as small as possible to minimize the number of files which may be maliciously modified at run time. The example configurations mount `/var` under a single overlay, but a more targeted approach is desirable. By default the overlays will consume at most 20% of the available memory. This can be configured using the `"TmpfsOverlaysSize"` key.
32-
33-
#### Writable Mount Points
34-
Traditional mount points still function as expected. A writable data partition can be mounted using the normal configuration keys if desired.
35-
36-
### Root of Trust
37-
The root of trust for a verity partition is the root hash. If this single hash is trusted, the entire hash tree, and subsequently the root partition, can also be trusted.
38-
39-
The root hash may be protected in three ways:
40-
- The file itself is stored in a safe location (signed `initramfs`)
41-
- The root hash is accompanied by a signature file which is validated against the kernel key ring
42-
- The root hash is passed on the kernel's command line in a secure manner
43-
44-
The `imager` tool automatically places the root hash and hash tree in the initramfs and sets the kernel command line in the `grub.cfg` file to use the verity files. This means that both the grub configuration files and the initramfs must be part of the verified boot chain to fully tie the verity root filesystem into the chain of trust.
45-
46-
### Users, Machine ID, Misc. Configuration
47-
Files in `/etc` such as the `passwd` and `machine-id` files are also part of the read-only filesystem, making them unmodifiable. If the machine-id is blank on system start, and the file is read-only, the systemd `systemd-machine-id-setup` command will create a tmpfs backed machine-id which will be different for every boot. If a stable `machine-id` is desired this file will need to be writable. Consider bind mounting the file early using the `x-initrd.mount` mount option and adding it to the `fstab` with `"PostInstallScripts"`.
48-
49-
Ideally as much of `/etc` as possible should be left read-only to avoid miss-configuration.
50-
51-
### Forward Error Correction (FEC)
52-
Verity supports error correction which will return the original data even if the underlying blocks have been modified (it does not restore the underlying data stored on disk however). FEC incurs some overhead but the hash tree, which is a sunk cost, makes it much more effective than normal Reed-Solomon codes. For a 2GiB disk, FEC with 2 roots (i.e. 2 bytes of error correction codes per 255 bytes of real data) can correct ~16MiB of errors with ~16MiB of overhead. See [veritydisk.go](../../tools/imagegen/configuration/veritydisk.go) for calculation details.
53-
54-
### Hash Tree and FEC Overhead
55-
The extra data required for verity needs to be stored outside the measured partition. In the case of Azure Linux it is stored in the initramfs. Assuming the Merkle tree is a full m-ary tree with m=128 (128 branches per node, from `4k/sizeof(sha256)`), the size of the Merkle tree is:
56-
```
57-
blockSize = 4k
58-
m = blockSize / sizeof(sha256)
59-
leafNodes = diskSize/blockSize
60-
totalNodes = ceil((leafNodes*m - 1) / (m - 1))
61-
totalTreeSize = totalNodes * sizeof(sha256)
62-
```
63-
64-
The FEC data grows linearly with the disk size. By default two bytes of error correction data are used for every 255 bytes of actual data. This gives:
65-
```
66-
fecBytesPerBlock = 2
67-
fecBlockSize = 255
68-
fecDataSize = ceil(diskSize / fecBlockSize) * fecBytesPerBlock
69-
```
70-
71-
#### Examples
72-
For a 2GiB root disk we would expect:
73-
```
74-
leafNodes = 2GiB / 4KiB = 524288
75-
totalTreeSize = ceil((524288*128 - 1) / (128 - 1)) * 256 = 135274752 bits = 16.13 MiB
76-
77-
fecDataSize = ceil(2GiB / 255 bits) * 2 bits = 134700000 = 16.06 MiB
78-
79-
totalOverhead = 32.19 MiB (1.5% overhead)
80-
```
81-
For a 20GiB root disk we would expect:
82-
```
83-
totalTreeSize = 161.3 MiB
84-
85-
fecDataSize = 160.6 MiB
86-
87-
totalOverhead = 321.9 MiB (1.6% overhead)
88-
```
89-
90-
### Debugging
91-
The read-only nature of these images can make debugging quite challenging.
92-
#### Serial Debugging
93-
Adding the following config will enable serial output (useful for both hardware and VM images), and will set `dracut` (The package which runs in the initramfs) to log its output and drop to an interactive shell in the event of a failure.
94-
```json
95-
"KernelCommandLine": {
96-
"ExtraCommandLine": "console=tty0 console=ttyS0=9800 rd.debug rd.shell=1"
97-
}
98-
```
99-
100-
#### Overlay Debugging
101-
If the `verity-read-only-root-debug-tools` package is included in the image, and the `"TmpfsOverlayDebugEnabled"` key is set to `true`, a read-only copy of the overlay upper directories (which will show the modified files for each overlay) will be visible under `/mnt/verity_overlay_debug_tmpfs`.
102-
103-
#### Error Handling Debugging
104-
The `verity-read-only-root-debug-tools` package also includes the `/mnt/create_linear_mount.sh` script which will freeze the verity root and make a new, writable, mount at `/mnt/verity_writable_debug`. Interacting with the system while the root is frozen can be unstable however, so proceed with caution.
105-
106-
Once the writable mount is created it is possible to write data back to the underlying disk. If the root partition is unfrozen again the changes will begin to be detected. Most changes will not show since the view of the disk is cached, but any changes to uncached files should trigger the error behavior. If FEC is enabled errors will simply be fixed until enough blocks are corrupted. The FEC correction is visible in the `dmesg` log.
107-
108-
If enough blocks are corrupted the system will eventually be unable to recover them with FEC and the error handling behavior will trigger. The default behavior is to simply return an IO error, but other options are available by setting the `"VerityErrorBehavior"` key in the configuration file.
109-
110-
## ISO Installers
111-
If a configuration used to create an ISO has a read-only root configured, the ISO installer will honor that configuration. (See `full.json`'s `"Azure Linux Core Read-Only"` entry).
6+
See [Azure Linux Image Customizer configuration](../../tools/imagecustomizer/docs/configuration.md#verity-type) for more information.

toolkit/tools/imageconfigvalidator/imageconfigvalidator.go

Lines changed: 4 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -113,12 +113,10 @@ func validatePackages(config configuration.Config) (err error) {
113113
defer timestamp.StopEvent(nil)
114114

115115
const (
116-
validateError = "failed to validate package lists in config"
117-
verityPkgName = "verity-read-only-root"
118-
verityDebugPkgName = "verity-read-only-root-debug-tools"
119-
dracutFipsPkgName = "dracut-fips"
120-
fipsKernelCmdLine = "fips=1"
121-
userAddPkgName = "shadow-utils"
116+
validateError = "failed to validate package lists in config"
117+
dracutFipsPkgName = "dracut-fips"
118+
fipsKernelCmdLine = "fips=1"
119+
userAddPkgName = "shadow-utils"
122120
)
123121

124122
for _, systemConfig := range config.SystemConfigs {
@@ -127,8 +125,6 @@ func validatePackages(config configuration.Config) (err error) {
127125
return fmt.Errorf("%s: %w", validateError, err)
128126
}
129127
foundSELinuxPackage := false
130-
foundVerityInitramfsPackage := false
131-
foundVerityInitramfsDebugPackage := false
132128
foundDracutFipsPackage := false
133129
foundUserAddPackage := false
134130
kernelCmdLineString := systemConfig.KernelCommandLine.ExtraCommandLine
@@ -141,12 +137,6 @@ func validatePackages(config configuration.Config) (err error) {
141137
if pkg == "kernel" {
142138
return fmt.Errorf("%s: kernel should not be included in a package list, add via config file's [KernelOptions] entry", validateError)
143139
}
144-
if pkg == verityPkgName {
145-
foundVerityInitramfsPackage = true
146-
}
147-
if pkg == verityDebugPkgName {
148-
foundVerityInitramfsDebugPackage = true
149-
}
150140
if pkg == dracutFipsPkgName {
151141
foundDracutFipsPackage = true
152142
}
@@ -157,14 +147,6 @@ func validatePackages(config configuration.Config) (err error) {
157147
foundUserAddPackage = true
158148
}
159149
}
160-
if systemConfig.ReadOnlyVerityRoot.Enable {
161-
if !foundVerityInitramfsPackage {
162-
return fmt.Errorf("%s: [ReadOnlyVerityRoot] selected, but '%s' package is not included in the package lists", validateError, verityPkgName)
163-
}
164-
if systemConfig.ReadOnlyVerityRoot.TmpfsOverlayDebugEnabled && !foundVerityInitramfsDebugPackage {
165-
return fmt.Errorf("%s: [ReadOnlyVerityRoot] and [TmpfsOverlayDebugEnabled] selected, but '%s' package is not included in the package lists", validateError, verityDebugPkgName)
166-
}
167-
}
168150
if strings.Contains(kernelCmdLineString, fipsKernelCmdLine) || systemConfig.KernelCommandLine.EnableFIPS {
169151
if !foundDracutFipsPackage {
170152
return fmt.Errorf("%s: 'fips=1' provided on kernel cmdline, but '%s' package is not included in the package lists", validateError, dracutFipsPkgName)

toolkit/tools/imagegen/attendedinstaller/_manualrun/manualrun.go

Lines changed: 0 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,6 @@ func main() {
2323

2424
logger.InitStderrLog()
2525

26-
// The JSON parser if responsible for filling defaults, since we are
27-
// using a Go struct need to manually use the defaults.
28-
verityConfig := configuration.GetDefaultReadOnlyVerityRoot()
29-
verityConfig.Enable = true
30-
3126
baseCfg := configuration.Config{
3227
SystemConfigs: []configuration.SystemConfig{
3328
configuration.SystemConfig{
@@ -95,40 +90,6 @@ func main() {
9590
},
9691
},
9792
},
98-
configuration.SystemConfig{
99-
Name: "Read-Only",
100-
PackageLists: []string{
101-
"packagelists/core-packages-image.json",
102-
"packagelists/hyperv-packages.json",
103-
"packagelists/read-only-root-packages.json",
104-
},
105-
KernelOptions: map[string]string{
106-
"default": "kernel",
107-
},
108-
AdditionalFiles: map[string]string{
109-
"/etc/resolv.conf": "/etc/resolv.conf",
110-
"/root/.bashrc": "/root/.bashrc",
111-
},
112-
ReadOnlyVerityRoot: verityConfig,
113-
PostInstallScripts: []configuration.InstallScript{
114-
configuration.InstallScript{
115-
Path: "arglessScript.sh",
116-
},
117-
configuration.InstallScript{
118-
Path: "thisOneNeedsArguments.sh",
119-
Args: "--input abc --output cba",
120-
},
121-
},
122-
FinalizeImageScripts: []configuration.InstallScript{
123-
configuration.InstallScript{
124-
Path: "arglessScript.sh",
125-
},
126-
configuration.InstallScript{
127-
Path: "thisOneNeedsArguments.sh",
128-
Args: "--input abc --output cba",
129-
},
130-
},
131-
},
13293
},
13394
}
13495

toolkit/tools/imagegen/attendedinstaller/uitext/uitext.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@ const (
6969
// Errors
7070
InvalidBootPartitionErrorFmt = "Invalid boot partition: first partition must be of type '%s'"
7171
InvalidRootPartitionErrorFmt = "Must specify a partition to have the mount point '%s'"
72-
InvalidRootDeviceMapperError = "Must have a root to use with device mapper roots (Encryption, Read-Only)"
7372
InvalidRootPartitionErrorFormatFmt = "Root partition cannot be %s"
7473
MountPointAlreadyInUseError = "Mount point is already in use"
7574
MountPointStartError = "Mount point must start with `/`"
@@ -137,8 +136,6 @@ const (
137136
PasswordMismatchFeedback = "Passwords do not match"
138137
EnumNavigationFeedback = "Use left or right arrow keys to change the selection"
139138

140-
EncryptionVerityIncompatible = "Encrypted and read-only roots are currently incompatible with each other"
141-
142139
UserNameEmptyError = "user name cannot be empty"
143140
UserNameInvalidRuneError = "user name should only contain alpha-numeric and '-', '.' or '_' characters"
144141
UserNameInvalidStartError = "user name should start with an alpha-numeric character"

0 commit comments

Comments
 (0)