Skip to content

Commit d2b705d

Browse files
Detect dm-verity for EMT based images (#376)
* Added initial logic to detect dm-verity * minor cleanup * Removed os-image-composer binary and log file * Updated gitignore, and added test cases * chore: auto-update coverage threshold to 64.8% (was 64.3%) * updated loop index for consistency * Revert "updated loop index for consistency" This reverts commit a56c954. * Renamed loop variable for consistency and .gitignore --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
1 parent d8d0e84 commit d2b705d

10 files changed

Lines changed: 920 additions & 10 deletions

.coverage-threshold

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
64.3
1+
64.8

.gitignore

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
# ignore everything under the downloads folder
1+
# ignore build artifacts, cache files, and temporary files
22
downloads/
33
builds/
4-
/cache/
4+
cache/
55
tmp/
6+
workspace/
67
# AI embedding cache
78
.ai-cache/

internal/image/imageinspect/compare.go

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,26 @@ type ImageDiff struct {
3939
PartitionTable PartitionTableDiff `json:"partitionTable,omitempty"`
4040
Partitions PartitionDiff `json:"partitions,omitempty"`
4141
EFIBinaries EFIBinaryDiff `json:"efiBinaries,omitempty"`
42+
Verity *VerityDiff `json:"verity,omitempty" yaml:"verity,omitempty"`
4243
}
4344

4445
// MetaDiff represents differences in image-level metadata.
4546
type MetaDiff struct {
4647
SizeBytes *ValueDiff[int64] `json:"sizeBytes,omitempty"`
4748
}
4849

50+
// VerityDiff represents differences in dm-verity configuration.
51+
type VerityDiff struct {
52+
Added *VerityInfo `json:"added,omitempty" yaml:"added,omitempty"`
53+
Removed *VerityInfo `json:"removed,omitempty" yaml:"removed,omitempty"`
54+
Changed bool `json:"changed,omitempty" yaml:"changed,omitempty"`
55+
56+
Enabled *ValueDiff[bool] `json:"enabled,omitempty" yaml:"enabled,omitempty"`
57+
Method *ValueDiff[string] `json:"method,omitempty" yaml:"method,omitempty"`
58+
RootDevice *ValueDiff[string] `json:"rootDevice,omitempty" yaml:"rootDevice,omitempty"`
59+
HashPartition *ValueDiff[int] `json:"hashPartition,omitempty" yaml:"hashPartition,omitempty"`
60+
}
61+
4962
// PartitionTableDiff represents differences in partition table-level fields.
5063
type PartitionTableDiff struct {
5164
DiskGUID *ValueDiff[string] `json:"diskGuid,omitempty"`
@@ -234,6 +247,12 @@ func CompareImages(from, to *ImageSummary) ImageCompareResult {
234247
res.Summary.Changed = true
235248
}
236249

250+
// --- dm-verity ---
251+
res.Diff.Verity = compareVerity(from.Verity, to.Verity)
252+
if res.Diff.Verity != nil && res.Diff.Verity.Changed {
253+
res.Summary.Changed = true
254+
}
255+
237256
// Deterministic ordering for stable JSON
238257
normalizeCompareResult(&res)
239258

@@ -284,6 +303,56 @@ func compareMeta(from, to ImageSummary) MetaDiff {
284303
return out
285304
}
286305

306+
func compareVerity(from, to *VerityInfo) *VerityDiff {
307+
// Both nil = no difference
308+
if from == nil && to == nil {
309+
return nil
310+
}
311+
312+
diff := &VerityDiff{}
313+
314+
// Added (to has verity, from doesn't)
315+
if from == nil && to != nil {
316+
diff.Added = to
317+
diff.Changed = true
318+
return diff
319+
}
320+
321+
// Removed (from has verity, to doesn't)
322+
if from != nil && to == nil {
323+
diff.Removed = from
324+
diff.Changed = true
325+
return diff
326+
}
327+
328+
// Both present
329+
if from.Enabled != to.Enabled {
330+
diff.Enabled = &ValueDiff[bool]{From: from.Enabled, To: to.Enabled}
331+
diff.Changed = true
332+
}
333+
334+
if from.Method != to.Method {
335+
diff.Method = &ValueDiff[string]{From: from.Method, To: to.Method}
336+
diff.Changed = true
337+
}
338+
339+
if from.RootDevice != to.RootDevice {
340+
diff.RootDevice = &ValueDiff[string]{From: from.RootDevice, To: to.RootDevice}
341+
diff.Changed = true
342+
}
343+
344+
if from.HashPartition != to.HashPartition {
345+
diff.HashPartition = &ValueDiff[int]{From: from.HashPartition, To: to.HashPartition}
346+
diff.Changed = true
347+
}
348+
349+
if !diff.Changed {
350+
return nil
351+
}
352+
353+
return diff
354+
}
355+
287356
// comparePartitionTable compares two PartitionTableSummary objects and returns a PartitionTableDiff.
288357
func comparePartitionTable(from, to PartitionTableSummary) PartitionTableDiff {
289358
var d PartitionTableDiff
@@ -751,6 +820,29 @@ func tallyDiffs(d ImageDiff) diffTally {
751820

752821
tallyEFIBinaryDiff(&t, d.EFIBinaries)
753822

823+
// dm-verity changes are meaningful (security-critical)
824+
if d.Verity != nil && d.Verity.Changed {
825+
if d.Verity.Added != nil {
826+
t.addMeaningful(1, "dm-verity enabled")
827+
} else if d.Verity.Removed != nil {
828+
t.addMeaningful(1, "dm-verity disabled")
829+
} else {
830+
// Field changes
831+
if d.Verity.Enabled != nil {
832+
t.addMeaningful(1, "dm-verity enabled status changed")
833+
}
834+
if d.Verity.Method != nil {
835+
t.addMeaningful(1, "dm-verity method changed")
836+
}
837+
if d.Verity.RootDevice != nil {
838+
t.addMeaningful(1, "dm-verity root device changed")
839+
}
840+
if d.Verity.HashPartition != nil {
841+
t.addMeaningful(1, "dm-verity hash partition changed")
842+
}
843+
}
844+
}
845+
754846
return t
755847
}
756848

0 commit comments

Comments
 (0)