dissect: relate verity partitions
When using `systemd.image_filter=usr=250` a `/usr` was selected based on its label but the corresponding verity partitions were *not* selected based on their (potential labels). This leads to mismatched verity partitions and `dm-verity` failure when using `image_filter` without also explicitly passing matching `usr-verity` and `usr-verity-sig`. Signed-off-by: Simon de Vlieger <cmdr@supakeen.com> (cherry picked from commit b5326670faac3064bcfa01ae3c1d57565d387bfb)
This commit is contained in:
committed by
Luca Boccassi
parent
b07c5a0639
commit
d5c945bddb
@@ -966,16 +966,31 @@ static int compare_arch(Architecture a, Architecture b) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool image_filter_test(const ImageFilter *filter, PartitionDesignator d, const char *label) {
|
||||
bool image_filter_test(const ImageFilter *filter, PartitionDesignator d, const char *label) {
|
||||
assert(d < _PARTITION_DESIGNATOR_MAX);
|
||||
|
||||
if (d < 0) /* For unspecified designators we have no filter expression */
|
||||
return true;
|
||||
|
||||
if (!filter || !filter->pattern[d])
|
||||
if (!filter)
|
||||
return true;
|
||||
|
||||
return fnmatch(filter->pattern[d], strempty(label), FNM_NOESCAPE) == 0;
|
||||
const char *pattern = filter->pattern[d];
|
||||
|
||||
/* If there's no filter for this specific designator but it's a verity partition, fall back to the
|
||||
* filter for the corresponding data partition. This ensures that e.g. image_filter=usr=250 also
|
||||
* constrains which usr verity (and verity sig) partitions are selected. This assumes verity
|
||||
* partitions carry the same label as their corresponding data partition. */
|
||||
if (!pattern) {
|
||||
PartitionDesignator data = partition_verity_to_data(d);
|
||||
if (data >= 0)
|
||||
pattern = filter->pattern[data];
|
||||
}
|
||||
|
||||
if (!pattern)
|
||||
return true;
|
||||
|
||||
return fnmatch(pattern, strempty(label), FNM_NOESCAPE) == 0;
|
||||
}
|
||||
|
||||
static int dissect_image_from_unpartitioned(
|
||||
|
||||
@@ -203,6 +203,7 @@ int dissected_image_relinquish(DissectedImage *m);
|
||||
void image_filter_done(ImageFilter *f);
|
||||
ImageFilter *image_filter_free(ImageFilter *f);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(ImageFilter*, image_filter_free);
|
||||
bool image_filter_test(const ImageFilter *filter, PartitionDesignator d, const char *label);
|
||||
int image_filter_parse(const char *s, ImageFilter **ret);
|
||||
|
||||
int verity_settings_load(VeritySettings *verity, const char *image, const char *root_hash_path, const char *root_hash_sig_path);
|
||||
|
||||
@@ -36,4 +36,95 @@ TEST(image_filter) {
|
||||
ASSERT_ERROR(image_filter_parse("root=knuff:root=knuff", &f), EINVAL);
|
||||
}
|
||||
|
||||
#if HAVE_BLKID
|
||||
TEST(image_filter_test_basic) {
|
||||
_cleanup_(image_filter_freep) ImageFilter *f = NULL;
|
||||
|
||||
/* NULL filter matches everything */
|
||||
ASSERT_TRUE(image_filter_test(NULL, PARTITION_ROOT, "foo"));
|
||||
ASSERT_TRUE(image_filter_test(NULL, PARTITION_USR, "bar"));
|
||||
ASSERT_TRUE(image_filter_test(NULL, PARTITION_USR_VERITY, "baz"));
|
||||
|
||||
/* Filter on usr matches the right label */
|
||||
ASSERT_OK(image_filter_parse("usr=250", &f));
|
||||
ASSERT_TRUE(image_filter_test(f, PARTITION_USR, "250"));
|
||||
ASSERT_FALSE(image_filter_test(f, PARTITION_USR, "251"));
|
||||
ASSERT_FALSE(image_filter_test(f, PARTITION_USR, ""));
|
||||
|
||||
/* Unfiltered designators pass through */
|
||||
ASSERT_TRUE(image_filter_test(f, PARTITION_ROOT, "anything"));
|
||||
ASSERT_TRUE(image_filter_test(f, PARTITION_HOME, "anything"));
|
||||
}
|
||||
|
||||
TEST(image_filter_test_verity_fallback) {
|
||||
_cleanup_(image_filter_freep) ImageFilter *f = NULL;
|
||||
|
||||
/* Filter on usr= should also constrain usr-verity and usr-verity-sig */
|
||||
ASSERT_OK(image_filter_parse("usr=250", &f));
|
||||
ASSERT_TRUE(image_filter_test(f, PARTITION_USR_VERITY, "250"));
|
||||
ASSERT_FALSE(image_filter_test(f, PARTITION_USR_VERITY, "251"));
|
||||
ASSERT_TRUE(image_filter_test(f, PARTITION_USR_VERITY_SIG, "250"));
|
||||
ASSERT_FALSE(image_filter_test(f, PARTITION_USR_VERITY_SIG, "251"));
|
||||
|
||||
f = image_filter_free(f);
|
||||
|
||||
/* Filter on root= should also constrain root-verity and root-verity-sig */
|
||||
ASSERT_OK(image_filter_parse("root=A", &f));
|
||||
ASSERT_TRUE(image_filter_test(f, PARTITION_ROOT_VERITY, "A"));
|
||||
ASSERT_FALSE(image_filter_test(f, PARTITION_ROOT_VERITY, "B"));
|
||||
ASSERT_TRUE(image_filter_test(f, PARTITION_ROOT_VERITY_SIG, "A"));
|
||||
ASSERT_FALSE(image_filter_test(f, PARTITION_ROOT_VERITY_SIG, "B"));
|
||||
|
||||
/* Unrelated verity-less designators are not affected */
|
||||
ASSERT_TRUE(image_filter_test(f, PARTITION_HOME, "anything"));
|
||||
|
||||
f = image_filter_free(f);
|
||||
|
||||
/* Glob patterns should work through the fallback too */
|
||||
ASSERT_OK(image_filter_parse("usr=25*", &f));
|
||||
ASSERT_TRUE(image_filter_test(f, PARTITION_USR, "250"));
|
||||
ASSERT_TRUE(image_filter_test(f, PARTITION_USR, "259"));
|
||||
ASSERT_FALSE(image_filter_test(f, PARTITION_USR, "260"));
|
||||
ASSERT_TRUE(image_filter_test(f, PARTITION_USR_VERITY, "250"));
|
||||
ASSERT_TRUE(image_filter_test(f, PARTITION_USR_VERITY, "259"));
|
||||
ASSERT_FALSE(image_filter_test(f, PARTITION_USR_VERITY, "260"));
|
||||
ASSERT_TRUE(image_filter_test(f, PARTITION_USR_VERITY_SIG, "250"));
|
||||
ASSERT_TRUE(image_filter_test(f, PARTITION_USR_VERITY_SIG, "259"));
|
||||
ASSERT_FALSE(image_filter_test(f, PARTITION_USR_VERITY_SIG, "260"));
|
||||
}
|
||||
|
||||
TEST(image_filter_test_verity_explicit) {
|
||||
_cleanup_(image_filter_freep) ImageFilter *f = NULL;
|
||||
|
||||
/* Explicit usr-verity= pattern wins over the usr= fallback */
|
||||
ASSERT_OK(image_filter_parse("usr=250:usr-verity=999", &f));
|
||||
ASSERT_TRUE(image_filter_test(f, PARTITION_USR, "250"));
|
||||
ASSERT_FALSE(image_filter_test(f, PARTITION_USR, "999"));
|
||||
ASSERT_TRUE(image_filter_test(f, PARTITION_USR_VERITY, "999"));
|
||||
ASSERT_FALSE(image_filter_test(f, PARTITION_USR_VERITY, "250"));
|
||||
/* usr-verity-sig still falls back to usr= since no explicit usr-verity-sig= was given */
|
||||
ASSERT_TRUE(image_filter_test(f, PARTITION_USR_VERITY_SIG, "250"));
|
||||
ASSERT_FALSE(image_filter_test(f, PARTITION_USR_VERITY_SIG, "999"));
|
||||
|
||||
f = image_filter_free(f);
|
||||
|
||||
/* Explicit usr-verity-sig= pattern wins over the usr= fallback */
|
||||
ASSERT_OK(image_filter_parse("usr=250:usr-verity-sig=777", &f));
|
||||
ASSERT_TRUE(image_filter_test(f, PARTITION_USR, "250"));
|
||||
ASSERT_TRUE(image_filter_test(f, PARTITION_USR_VERITY_SIG, "777"));
|
||||
ASSERT_FALSE(image_filter_test(f, PARTITION_USR_VERITY_SIG, "250"));
|
||||
/* usr-verity still falls back to usr= since no explicit usr-verity= was given */
|
||||
ASSERT_TRUE(image_filter_test(f, PARTITION_USR_VERITY, "250"));
|
||||
ASSERT_FALSE(image_filter_test(f, PARTITION_USR_VERITY, "777"));
|
||||
|
||||
f = image_filter_free(f);
|
||||
|
||||
/* Fallback does not apply in reverse: usr-verity= must not constrain usr */
|
||||
ASSERT_OK(image_filter_parse("usr-verity=999", &f));
|
||||
ASSERT_TRUE(image_filter_test(f, PARTITION_USR_VERITY, "999"));
|
||||
ASSERT_FALSE(image_filter_test(f, PARTITION_USR_VERITY, "250"));
|
||||
ASSERT_TRUE(image_filter_test(f, PARTITION_USR, "anything"));
|
||||
}
|
||||
#endif
|
||||
|
||||
DEFINE_TEST_MAIN(LOG_INFO);
|
||||
|
||||
Reference in New Issue
Block a user