Skip to content

Commit 7c0afcd

Browse files
authored
core: gracefully skip unknown policy designators in RootImagePolicy et al (systemd#40060)
Usually we gracefully ignore unknown configuration parameters, so that service files can be written by upstreams and used across a variegated range of distributions with various versions of systemd, to avoid forcing users to the minimum common denominator and only adding settings that are supported by the oldest distro supported. Image policies do not behave like this, and any unknown partition or policy designator causes the whole unit to fail to parse and a hard error. Change it so that parsing RootImagePolicy and friends via unit file or D-Bus logs but otherwise ignores unknown specifiers, like other options do. This allows us to add new specifiers in the future, and users to adopt them immediately. Follow-up for d452335
1 parent 72711b7 commit 7c0afcd

File tree

9 files changed

+62
-36
lines changed

9 files changed

+62
-36
lines changed

src/analyze/analyze-image-policy.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ int verb_image_policy(int argc, char *argv[], void *userdata) {
103103
else if (streq(argv[i], "@host"))
104104
p = &image_policy_host;
105105
else {
106-
r = image_policy_from_string(argv[i], &pbuf);
106+
r = image_policy_from_string(argv[i], /* graceful= */ false, &pbuf);
107107
if (r < 0)
108108
return log_error_errno(r, "Failed to parse image policy '%s': %m", argv[i]);
109109

src/core/dbus-execute.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4308,7 +4308,7 @@ int bus_exec_context_set_transient_property(
43084308
if (r < 0)
43094309
return r;
43104310

4311-
r = image_policy_from_string(s, &p);
4311+
r = image_policy_from_string(s, /* graceful= */ true, &p);
43124312
if (r < 0)
43134313
return sd_bus_error_setf(reterr_error, SD_BUS_ERROR_INVALID_ARGS, "Failed to parse image policy string: %s", s);
43144314

src/core/execute-serialize.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3740,21 +3740,21 @@ static int exec_context_deserialize(ExecContext *c, FILE *f) {
37403740
if (c->root_image_policy)
37413741
return -EINVAL; /* duplicated */
37423742

3743-
r = image_policy_from_string(val, &c->root_image_policy);
3743+
r = image_policy_from_string(val, /* graceful= */ true, &c->root_image_policy);
37443744
if (r < 0)
37453745
return r;
37463746
} else if ((val = startswith(l, "exec-context-mount-image-policy="))) {
37473747
if (c->mount_image_policy)
37483748
return -EINVAL; /* duplicated */
37493749

3750-
r = image_policy_from_string(val, &c->mount_image_policy);
3750+
r = image_policy_from_string(val, /* graceful= */ true, &c->mount_image_policy);
37513751
if (r < 0)
37523752
return r;
37533753
} else if ((val = startswith(l, "exec-context-extension-image-policy="))) {
37543754
if (c->extension_image_policy)
37553755
return -EINVAL; /* duplicated */
37563756

3757-
r = image_policy_from_string(val, &c->extension_image_policy);
3757+
r = image_policy_from_string(val, /* graceful= */ true, &c->extension_image_policy);
37583758
if (r < 0)
37593759
return r;
37603760
} else

src/mountfsd/mountwork.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ static int json_dispatch_image_policy(const char *name, sd_json_variant *variant
7676
if (!sd_json_variant_is_string(variant))
7777
return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not a string.", strna(name));
7878

79-
r = image_policy_from_string(sd_json_variant_string(variant), &q);
79+
r = image_policy_from_string(sd_json_variant_string(variant), /* graceful= */ false, &q);
8080
if (r < 0)
8181
return json_log(variant, flags, r, "JSON field '%s' is not a valid image policy.", strna(name));
8282

@@ -244,7 +244,7 @@ static int determine_image_policy(
244244

245245
e = secure_getenv(envvar);
246246
if (e) {
247-
r = image_policy_from_string(e, &envvar_policy);
247+
r = image_policy_from_string(e, /* graceful= */ false, &envvar_policy);
248248
if (r < 0)
249249
return log_error_errno(r, "Failed to parse image policy supplied via $%s: %m", envvar);
250250

src/shared/image-policy.c

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ static PartitionPolicyFlags policy_flag_from_string_one(const char *s) {
209209
return _PARTITION_POLICY_FLAGS_INVALID;
210210
}
211211

212-
PartitionPolicyFlags partition_policy_flags_from_string(const char *s) {
212+
PartitionPolicyFlags partition_policy_flags_from_string(const char *s, bool graceful) {
213213
PartitionPolicyFlags flags = 0;
214214
int r;
215215

@@ -229,8 +229,13 @@ PartitionPolicyFlags partition_policy_flags_from_string(const char *s) {
229229
break;
230230

231231
ff = policy_flag_from_string_one(strstrip(f));
232-
if (ff < 0)
232+
if (ff < 0) {
233+
if (graceful) {
234+
log_debug("Unknown partition policy flag: %s, ignoring", f);
235+
continue;
236+
}
233237
return -EBADRQC; /* recognizable error */
238+
}
234239

235240
flags |= ff;
236241
}
@@ -254,7 +259,7 @@ static ImagePolicy* image_policy_new(size_t n_policies) {
254259
return p;
255260
}
256261

257-
int image_policy_from_string(const char *s, ImagePolicy **ret) {
262+
int image_policy_from_string(const char *s, bool graceful, ImagePolicy **ret) {
258263
_cleanup_free_ ImagePolicy *p = NULL;
259264
uint64_t dmask = 0;
260265
ImagePolicy *t;
@@ -336,15 +341,20 @@ int image_policy_from_string(const char *s, ImagePolicy **ret) {
336341
default_specified = true;
337342
} else {
338343
designator = partition_designator_from_string(ds);
339-
if (designator < 0)
340-
return log_debug_errno(SYNTHETIC_ERRNO(EBADSLT), "Unknown partition designator: %s", ds); /* recognizable error */
344+
if (designator < 0) {
345+
if (!graceful)
346+
return log_debug_errno(SYNTHETIC_ERRNO(EBADSLT), "Unknown partition designator: %s", ds); /* recognizable error */
347+
348+
log_debug("Unknown partition designator: %s, ignoring", ds);
349+
continue;
350+
}
341351
if (dmask & (UINT64_C(1) << designator))
342352
return log_debug_errno(SYNTHETIC_ERRNO(ENOTUNIQ), "Partition designator specified more than once: %s", ds);
343353
dmask |= UINT64_C(1) << designator;
344354
}
345355

346356
fs = strstrip(f);
347-
flags = partition_policy_flags_from_string(fs);
357+
flags = partition_policy_flags_from_string(fs, graceful);
348358
if (flags == -EBADRQC)
349359
return log_debug_errno(flags, "Unknown partition policy flag: %s", fs);
350360
if (flags < 0)
@@ -651,7 +661,7 @@ int config_parse_image_policy(
651661
return 0;
652662
}
653663

654-
r = image_policy_from_string(rvalue, &np);
664+
r = image_policy_from_string(rvalue, /* graceful */ true, &np);
655665
if (r == -ENOTUNIQ)
656666
return log_syntax(unit, LOG_ERR, filename, line, r, "Duplicate rule in image policy, refusing: %s", rvalue);
657667
if (r == -EBADSLT)
@@ -678,7 +688,7 @@ int parse_image_policy_argument(const char *s, ImagePolicy **policy) {
678688
* Hence, do not pass in uninitialized pointers.
679689
*/
680690

681-
r = image_policy_from_string(s, &np);
691+
r = image_policy_from_string(s, /* graceful= */ false, &np);
682692
if (r == -ENOTUNIQ)
683693
return log_error_errno(r, "Duplicate rule in image policy: %s", s);
684694
if (r == -EBADSLT)

src/shared/image-policy.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,10 @@ static inline size_t image_policy_n_entries(const ImagePolicy *policy) {
8080
PartitionPolicyFlags partition_policy_flags_extend(PartitionPolicyFlags flags);
8181
PartitionPolicyFlags partition_policy_flags_reduce(PartitionPolicyFlags flags);
8282

83-
PartitionPolicyFlags partition_policy_flags_from_string(const char *s);
83+
PartitionPolicyFlags partition_policy_flags_from_string(const char *s, bool graceful);
8484
int partition_policy_flags_to_string(PartitionPolicyFlags flags, bool simplify, char **ret);
8585

86-
int image_policy_from_string(const char *s, ImagePolicy **ret);
86+
int image_policy_from_string(const char *s, bool graceful, ImagePolicy **ret);
8787
int image_policy_to_string(const ImagePolicy *policy, bool simplify, char **ret);
8888

8989
/* Recognizes three special policies by equivalence */

src/test/test-image-policy.c

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@ static void test_policy(const ImagePolicy *p, const char *name) {
2222

2323
printf("%s\n", ansi_normal());
2424

25-
assert_se(image_policy_from_string(as_string, &parsed) >= 0);
25+
assert_se(image_policy_from_string(as_string, /* graceful= */ false, &parsed) >= 0);
2626
assert_se(image_policy_equal(p, parsed));
2727
parsed = image_policy_free(parsed);
2828

29-
assert_se(image_policy_from_string(as_string_simplified, &parsed) >= 0);
29+
assert_se(image_policy_from_string(as_string_simplified, /* graceful= */ false, &parsed) >= 0);
3030
assert_se(image_policy_equivalent(p, parsed));
3131
parsed = image_policy_free(parsed);
3232

@@ -55,14 +55,14 @@ static void test_policy(const ImagePolicy *p, const char *name) {
5555
static void test_policy_string(const char *t) {
5656
_cleanup_free_ ImagePolicy *parsed = NULL;
5757

58-
assert_se(image_policy_from_string(t, &parsed) >= 0);
58+
assert_se(image_policy_from_string(t, /* graceful= */ false, &parsed) >= 0);
5959
test_policy(parsed, t);
6060
}
6161

6262
static void test_policy_equiv(const char *s, bool (*func)(const ImagePolicy *p)) {
6363
_cleanup_(image_policy_freep) ImagePolicy *p = NULL;
6464

65-
assert_se(image_policy_from_string(s, &p) >= 0);
65+
assert_se(image_policy_from_string(s, /* graceful= */ false, &p) >= 0);
6666

6767
assert_se(func(p));
6868
assert_se(func == image_policy_equiv_ignore || !image_policy_equiv_ignore(p));
@@ -106,15 +106,25 @@ TEST_RET(test_image_policy_to_string) {
106106
test_policy_equiv("=unused+absent", image_policy_equiv_ignore);
107107
test_policy_equiv("root=ignore:=ignore", image_policy_equiv_ignore);
108108

109-
assert_se(image_policy_from_string("pfft", NULL) == -EINVAL);
110-
assert_se(image_policy_from_string("öäüß", NULL) == -EINVAL);
111-
assert_se(image_policy_from_string(":", NULL) == -EINVAL);
112-
assert_se(image_policy_from_string("a=", NULL) == -EBADSLT);
113-
assert_se(image_policy_from_string("=a", NULL) == -EBADRQC);
114-
assert_se(image_policy_from_string("==", NULL) == -EBADRQC);
115-
assert_se(image_policy_from_string("root=verity:root=encrypted", NULL) == -ENOTUNIQ);
116-
assert_se(image_policy_from_string("root=grbl", NULL) == -EBADRQC);
117-
assert_se(image_policy_from_string("wowza=grbl", NULL) == -EBADSLT);
109+
assert_se(image_policy_from_string("pfft", /* graceful= */ false, NULL) == -EINVAL);
110+
assert_se(image_policy_from_string("öäüß", /* graceful= */ false, NULL) == -EINVAL);
111+
assert_se(image_policy_from_string(":", /* graceful= */ false, NULL) == -EINVAL);
112+
assert_se(image_policy_from_string("a=", /* graceful= */ false, NULL) == -EBADSLT);
113+
assert_se(image_policy_from_string("=a", /* graceful= */ false, NULL) == -EBADRQC);
114+
assert_se(image_policy_from_string("==", /* graceful= */ false, NULL) == -EBADRQC);
115+
assert_se(image_policy_from_string("root=verity:root=encrypted", /* graceful= */ false, NULL) == -ENOTUNIQ);
116+
assert_se(image_policy_from_string("root=grbl", /* graceful= */ false, NULL) == -EBADRQC);
117+
assert_se(image_policy_from_string("wowza=grbl", /* graceful= */ false, NULL) == -EBADSLT);
118+
119+
assert_se(image_policy_from_string("pfft", /* graceful= */ true, NULL) == -EINVAL);
120+
assert_se(image_policy_from_string("öäüß", /* graceful= */ true, NULL) == -EINVAL);
121+
assert_se(image_policy_from_string(":", /* graceful= */ true, NULL) == -EINVAL);
122+
assert_se(image_policy_from_string("a=", /* graceful= */ true, NULL) == 0);
123+
assert_se(image_policy_from_string("=a", /* graceful= */ true, NULL) == 0);
124+
assert_se(image_policy_from_string("==", /* graceful= */ true, NULL) == 0);
125+
assert_se(image_policy_from_string("root=verity:root=encrypted", /* graceful= */ true, NULL) == -ENOTUNIQ);
126+
assert_se(image_policy_from_string("root=grbl", /* graceful= */ true, NULL) == 0);
127+
assert_se(image_policy_from_string("wowza=grbl", /* graceful= */ true, NULL) == 0);
118128

119129
return 0;
120130
}
@@ -131,9 +141,9 @@ TEST(extend) {
131141
static void test_policy_intersect_one(const char *a, const char *b, const char *c) {
132142
_cleanup_(image_policy_freep) ImagePolicy *x = NULL, *y = NULL, *z = NULL, *t = NULL;
133143

134-
assert_se(image_policy_from_string(a, &x) >= 0);
135-
assert_se(image_policy_from_string(b, &y) >= 0);
136-
assert_se(image_policy_from_string(c, &z) >= 0);
144+
assert_se(image_policy_from_string(a, /* graceful= */ false, &x) >= 0);
145+
assert_se(image_policy_from_string(b, /* graceful= */ false, &y) >= 0);
146+
assert_se(image_policy_from_string(c, /* graceful= */ false, &z) >= 0);
137147

138148
assert_se(image_policy_intersect(x, y, &t) >= 0);
139149

@@ -163,8 +173,8 @@ TEST(image_policy_intersect) {
163173
static void test_policy_ignore_designators_one(const char *a, const PartitionDesignator array[], size_t n, const char *b) {
164174
_cleanup_(image_policy_freep) ImagePolicy *x = NULL, *y = NULL, *t = NULL;
165175

166-
ASSERT_OK(image_policy_from_string(a, &x));
167-
ASSERT_OK(image_policy_from_string(b, &y));
176+
ASSERT_OK(image_policy_from_string(a, /* graceful= */ false, &x));
177+
ASSERT_OK(image_policy_from_string(b, /* graceful= */ false, &y));
168178

169179
_cleanup_free_ char *s1 = NULL, *s2 = NULL, *s3 = NULL;
170180
ASSERT_OK(image_policy_to_string(x, true, &s1));

src/udev/udev-builtin-dissect_image.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ static int acquire_image_policy(ImagePolicy **ret) {
3434
return 0;
3535
}
3636

37-
r = image_policy_from_string(value, ret);
37+
r = image_policy_from_string(value, /* graceful= */ false, ret);
3838
if (r < 0)
3939
return log_error_errno(r, "Failed to parse image policy '%s': %m", value);
4040

test/units/TEST-50-DISSECT.dissect.sh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,12 @@ systemd-run --wait -P \
237237
-p RootImagePolicy='root=signed' \
238238
-p MountAPIVFS=yes \
239239
cat /usr/lib/os-release | grep -F "MARKER=1" >/dev/null
240+
systemd-run --wait -P \
241+
-p RootImage="$MINIMAL_IMAGE.gpt" \
242+
-p RootHash="$MINIMAL_IMAGE_ROOTHASH" \
243+
-p RootImagePolicy='root=signed+lol:wut=wat+signed' \
244+
-p MountAPIVFS=yes \
245+
cat /usr/lib/os-release | grep -F "MARKER=1" >/dev/null
240246
(! systemd-run --wait -P \
241247
-p RootImage="$MINIMAL_IMAGE.gpt" \
242248
-p RootHash="$MINIMAL_IMAGE_ROOTHASH" \

0 commit comments

Comments
 (0)