Skip to content

Commit 5762dbf

Browse files
authored
Merge pull request systemd#24883 from bluca/extrel_force
portable: allow caller to override extension-release name check
2 parents 31b5f92 + 06768b9 commit 5762dbf

15 files changed

+153
-80
lines changed

man/org.freedesktop.portable1.xml

+7-4
Original file line numberDiff line numberDiff line change
@@ -307,13 +307,16 @@ node /org/freedesktop/portable1 {
307307
<para>The <function>AttachImageWithExtensions()</function>,
308308
<function>DetachImageWithExtensions()</function> and
309309
<function>ReattachImageWithExtensions()</function> methods take in options as flags instead of
310-
booleans to allow for extendability. <varname>SD_SYSTEMD_PORTABLE_FORCE</varname> will cause
310+
booleans to allow for extendability. <varname>SD_SYSTEMD_PORTABLE_FORCE_ATTACH</varname> will cause
311311
safety checks that ensure the units are not running while the new image is attached or detached
312-
to be skipped. They are defined as follows:</para>
312+
to be skipped. <varname>SD_SYSTEMD_PORTABLE_FORCE_SYSEXT</varname> will cause the check that the
313+
<filename>extension-release.<replaceable>NAME</replaceable></filename> file in the extension image
314+
matches the image name to be skipped. They are defined as follows:</para>
313315

314316
<programlisting>
315-
#define SD_SYSTEMD_PORTABLE_RUNTIME (UINT64_C(1) &lt;&lt; 0)
316-
#define SD_SYSTEMD_PORTABLE_FORCE (UINT64_C(1) &lt;&lt; 1)
317+
#define SD_SYSTEMD_PORTABLE_RUNTIME (UINT64_C(1) &lt;&lt; 0)
318+
#define SD_SYSTEMD_PORTABLE_FORCE_ATTACH (UINT64_C(1) &lt;&lt; 1)
319+
#define SD_SYSTEMD_PORTABLE_FORCE_SYSEXT (UINT64_C(1) &lt;&lt; 2)
317320
</programlisting>
318321
</refsect2>
319322

man/portablectl.xml

+3-1
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,9 @@
378378
<term><option>--force</option></term>
379379

380380
<listitem><para>Skip safety checks and attach or detach images (with extensions) without first ensuring
381-
that the units are not running.</para></listitem>
381+
that the units are not running, and do not insist that the
382+
<filename>extension-release.<replaceable>NAME</replaceable></filename> file in the extension image has
383+
to match the image filename.</para></listitem>
382384
</varlistentry>
383385

384386
<xi:include href="user-system-options.xml" xpointer="host" />

man/systemd.exec.xml

+3-1
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,9 @@
441441
<para>Each image must carry a <filename>/usr/lib/extension-release.d/extension-release.IMAGE</filename>
442442
file, with the appropriate metadata which matches <varname>RootImage=</varname>/<varname>RootDirectory=</varname>
443443
or the host. See:
444-
<citerefentry><refentrytitle>os-release</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
444+
<citerefentry><refentrytitle>os-release</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
445+
To disable the safety check that the extension-release file name matches the image file name, the
446+
<varname>x-systemd.relax-extension-release-check</varname> mount option may be appended.</para>
445447

446448
<para>When <varname>DevicePolicy=</varname> is set to <literal>closed</literal> or
447449
<literal>strict</literal>, or set to <literal>auto</literal> and <varname>DeviceAllow=</varname> is

src/basic/os-util.c

+57-39
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ bool image_name_is_valid(const char *s) {
3636
return true;
3737
}
3838

39-
int path_is_extension_tree(const char *path, const char *extension) {
39+
int path_is_extension_tree(const char *path, const char *extension, bool relax_extension_release_check) {
4040
int r;
4141

4242
assert(path);
@@ -49,7 +49,7 @@ int path_is_extension_tree(const char *path, const char *extension) {
4949

5050
/* We use /usr/lib/extension-release.d/extension-release[.NAME] as flag for something being a system extension,
5151
* and {/etc|/usr/lib}/os-release as a flag for something being an OS (when not an extension). */
52-
r = open_extension_release(path, extension, NULL, NULL);
52+
r = open_extension_release(path, extension, relax_extension_release_check, NULL, NULL);
5353
if (r == -ENOENT) /* We got nothing */
5454
return 0;
5555
if (r < 0)
@@ -58,7 +58,45 @@ int path_is_extension_tree(const char *path, const char *extension) {
5858
return 1;
5959
}
6060

61-
int open_extension_release(const char *root, const char *extension, char **ret_path, int *ret_fd) {
61+
static int extension_release_strict_xattr_value(int extension_release_fd, const char *extension_release_dir_path, const char *filename) {
62+
int r;
63+
64+
assert(extension_release_fd >= 0);
65+
assert(extension_release_dir_path);
66+
assert(filename);
67+
68+
/* No xattr or cannot parse it? Then skip this. */
69+
_cleanup_free_ char *extension_release_xattr = NULL;
70+
r = fgetxattr_malloc(extension_release_fd, "user.extension-release.strict", &extension_release_xattr);
71+
if (r < 0) {
72+
if (!ERRNO_IS_XATTR_ABSENT(r))
73+
return log_debug_errno(r,
74+
"%s/%s: Failed to read 'user.extension-release.strict' extended attribute from file, ignoring: %m",
75+
extension_release_dir_path, filename);
76+
77+
return log_debug_errno(r, "%s/%s does not have user.extension-release.strict xattr, ignoring.", extension_release_dir_path, filename);
78+
}
79+
80+
/* Explicitly set to request strict matching? Skip it. */
81+
r = parse_boolean(extension_release_xattr);
82+
if (r < 0)
83+
return log_debug_errno(r,
84+
"%s/%s: Failed to parse 'user.extension-release.strict' extended attribute from file, ignoring: %m",
85+
extension_release_dir_path, filename);
86+
if (r > 0) {
87+
log_debug("%s/%s: 'user.extension-release.strict' attribute is true, ignoring file.",
88+
extension_release_dir_path, filename);
89+
return true;
90+
}
91+
92+
log_debug("%s/%s: 'user.extension-release.strict' attribute is false%s",
93+
extension_release_dir_path, filename,
94+
special_glyph(SPECIAL_GLYPH_ELLIPSIS));
95+
96+
return false;
97+
}
98+
99+
int open_extension_release(const char *root, const char *extension, bool relax_extension_release_check, char **ret_path, int *ret_fd) {
62100
_cleanup_free_ char *q = NULL;
63101
int r, fd;
64102

@@ -123,34 +161,14 @@ int open_extension_release(const char *root, const char *extension, char **ret_p
123161
continue;
124162
}
125163

126-
/* No xattr or cannot parse it? Then skip this. */
127-
_cleanup_free_ char *extension_release_xattr = NULL;
128-
k = fgetxattr_malloc(extension_release_fd, "user.extension-release.strict", &extension_release_xattr);
129-
if (k < 0 && !ERRNO_IS_XATTR_ABSENT(k))
130-
log_debug_errno(k,
131-
"%s/%s: Failed to read 'user.extension-release.strict' extended attribute from file: %m",
132-
extension_release_dir_path, de->d_name);
133-
if (k < 0) {
134-
log_debug("%s/%s does not have user.extension-release.strict xattr, ignoring.", extension_release_dir_path, de->d_name);
135-
continue;
164+
if (!relax_extension_release_check) {
165+
k = extension_release_strict_xattr_value(extension_release_fd,
166+
extension_release_dir_path,
167+
de->d_name);
168+
if (k != 0)
169+
continue;
136170
}
137171

138-
/* Explicitly set to request strict matching? Skip it. */
139-
k = parse_boolean(extension_release_xattr);
140-
if (k < 0)
141-
log_debug_errno(k,
142-
"%s/%s: Failed to parse 'user.extension-release.strict' extended attribute from file: %m",
143-
extension_release_dir_path, de->d_name);
144-
else if (k > 0)
145-
log_debug("%s/%s: 'user.extension-release.strict' attribute is true, ignoring file.",
146-
extension_release_dir_path, de->d_name);
147-
if (k != 0)
148-
continue;
149-
150-
log_debug("%s/%s: 'user.extension-release.strict' attribute is false%s",
151-
extension_release_dir_path, de->d_name,
152-
special_glyph(SPECIAL_GLYPH_ELLIPSIS));
153-
154172
/* We already found what we were looking for, but there's another candidate?
155173
* We treat this as an error, as we want to enforce that there are no ambiguities
156174
* in case we are in the fallback path.*/
@@ -207,16 +225,16 @@ int open_extension_release(const char *root, const char *extension, char **ret_p
207225
return 0;
208226
}
209227

210-
int fopen_extension_release(const char *root, const char *extension, char **ret_path, FILE **ret_file) {
228+
int fopen_extension_release(const char *root, const char *extension, bool relax_extension_release_check, char **ret_path, FILE **ret_file) {
211229
_cleanup_free_ char *p = NULL;
212230
_cleanup_close_ int fd = -1;
213231
FILE *f;
214232
int r;
215233

216234
if (!ret_file)
217-
return open_extension_release(root, extension, ret_path, NULL);
235+
return open_extension_release(root, extension, relax_extension_release_check, ret_path, NULL);
218236

219-
r = open_extension_release(root, extension, ret_path ? &p : NULL, &fd);
237+
r = open_extension_release(root, extension, relax_extension_release_check, ret_path ? &p : NULL, &fd);
220238
if (r < 0)
221239
return r;
222240

@@ -231,24 +249,24 @@ int fopen_extension_release(const char *root, const char *extension, char **ret_
231249
return 0;
232250
}
233251

234-
static int parse_release_internal(const char *root, const char *extension, va_list ap) {
252+
static int parse_release_internal(const char *root, bool relax_extension_release_check, const char *extension, va_list ap) {
235253
_cleanup_fclose_ FILE *f = NULL;
236254
_cleanup_free_ char *p = NULL;
237255
int r;
238256

239-
r = fopen_extension_release(root, extension, &p, &f);
257+
r = fopen_extension_release(root, extension, relax_extension_release_check, &p, &f);
240258
if (r < 0)
241259
return r;
242260

243261
return parse_env_filev(f, p, ap);
244262
}
245263

246-
int _parse_extension_release(const char *root, const char *extension, ...) {
264+
int _parse_extension_release(const char *root, bool relax_extension_release_check, const char *extension, ...) {
247265
va_list ap;
248266
int r;
249267

250268
va_start(ap, extension);
251-
r = parse_release_internal(root, extension, ap);
269+
r = parse_release_internal(root, relax_extension_release_check, extension, ap);
252270
va_end(ap);
253271

254272
return r;
@@ -259,7 +277,7 @@ int _parse_os_release(const char *root, ...) {
259277
int r;
260278

261279
va_start(ap, root);
262-
r = parse_release_internal(root, NULL, ap);
280+
r = parse_release_internal(root, /* relax_extension_release_check= */ false, NULL, ap);
263281
va_end(ap);
264282

265283
return r;
@@ -306,12 +324,12 @@ int load_os_release_pairs_with_prefix(const char *root, const char *prefix, char
306324
return 0;
307325
}
308326

309-
int load_extension_release_pairs(const char *root, const char *extension, char ***ret) {
327+
int load_extension_release_pairs(const char *root, const char *extension, bool relax_extension_release_check, char ***ret) {
310328
_cleanup_fclose_ FILE *f = NULL;
311329
_cleanup_free_ char *p = NULL;
312330
int r;
313331

314-
r = fopen_extension_release(root, extension, &p, &f);
332+
r = fopen_extension_release(root, extension, relax_extension_release_check, &p, &f);
315333
if (r < 0)
316334
return r;
317335

src/basic/os-util.h

+9-9
Original file line numberDiff line numberDiff line change
@@ -8,27 +8,27 @@
88

99
bool image_name_is_valid(const char *s) _pure_;
1010

11-
int path_is_extension_tree(const char *path, const char *extension);
11+
int path_is_extension_tree(const char *path, const char *extension, bool relax_extension_release_check);
1212
static inline int path_is_os_tree(const char *path) {
13-
return path_is_extension_tree(path, NULL);
13+
return path_is_extension_tree(path, NULL, false);
1414
}
1515

16-
int open_extension_release(const char *root, const char *extension, char **ret_path, int *ret_fd);
16+
int open_extension_release(const char *root, const char *extension, bool relax_extension_release_check, char **ret_path, int *ret_fd);
1717
static inline int open_os_release(const char *root, char **ret_path, int *ret_fd) {
18-
return open_extension_release(root, NULL, ret_path, ret_fd);
18+
return open_extension_release(root, NULL, false, ret_path, ret_fd);
1919
}
2020

21-
int fopen_extension_release(const char *root, const char *extension, char **ret_path, FILE **ret_file);
21+
int fopen_extension_release(const char *root, const char *extension, bool relax_extension_release_check, char **ret_path, FILE **ret_file);
2222
static inline int fopen_os_release(const char *root, char **ret_path, FILE **ret_file) {
23-
return fopen_extension_release(root, NULL, ret_path, ret_file);
23+
return fopen_extension_release(root, NULL, false, ret_path, ret_file);
2424
}
2525

26-
int _parse_extension_release(const char *root, const char *extension, ...) _sentinel_;
26+
int _parse_extension_release(const char *root, bool relax_extension_release_check, const char *extension, ...) _sentinel_;
2727
int _parse_os_release(const char *root, ...) _sentinel_;
28-
#define parse_extension_release(root, extension, ...) _parse_extension_release(root, extension, __VA_ARGS__, NULL)
28+
#define parse_extension_release(root, relax_extension_release_check, extension, ...) _parse_extension_release(root, relax_extension_release_check, extension, __VA_ARGS__, NULL)
2929
#define parse_os_release(root, ...) _parse_os_release(root, __VA_ARGS__, NULL)
3030

31-
int load_extension_release_pairs(const char *root, const char *extension, char ***ret);
31+
int load_extension_release_pairs(const char *root, const char *extension, bool relax_extension_release_check, char ***ret);
3232
int load_os_release_pairs(const char *root, char ***ret);
3333
int load_os_release_pairs_with_prefix(const char *root, const char *prefix, char ***ret);
3434

src/core/namespace.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -1382,7 +1382,7 @@ static int apply_one_mount(
13821382
if (isempty(host_os_release_id))
13831383
return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "'ID' field not found or empty in 'os-release' data of OS tree '%s': %m", empty_to_root(root_directory));
13841384

1385-
r = load_extension_release_pairs(mount_entry_source(m), extension_name, &extension_release);
1385+
r = load_extension_release_pairs(mount_entry_source(m), extension_name, /* relax_extension_release_check= */ false, &extension_release);
13861386
if (r == -ENOENT && m->ignore)
13871387
return 0;
13881388
if (r < 0)

0 commit comments

Comments
 (0)