Compare commits
No commits in common. "a6991726f80c299ac7275f4570e310e1dd5bce96" and "28365e88d0dfc6332b26120e23b2c39b7958f907" have entirely different histories.
a6991726f8
...
28365e88d0
2
TODO
2
TODO
|
@ -27,8 +27,6 @@ Features:
|
|||
nodes to /run/host, move notify socket (for sd_notify() between payload and
|
||||
container manager)
|
||||
|
||||
* make use of new glibc 2.32 APIs sigabbrev_np() and strerrorname_np().
|
||||
|
||||
* cryptsetup: if keyfile specified in crypttab is AF_UNIX socket, connect to it
|
||||
and read from it (like we do elsewhere with READ_FULL_FILE_CONNECT_SOCKET)
|
||||
|
||||
|
|
|
@ -261,42 +261,6 @@
|
|||
<xi:include href="system-only.xml" xpointer="singular"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>MountImages=</varname></term>
|
||||
|
||||
<listitem><para>This setting is similar to <varname>RootImage=</varname> in that it mounts a file
|
||||
system hierarchy from a block device node or loopback file, but the destination directory can be
|
||||
specified as well as mount options. This option expects a whitespace separated list of mount
|
||||
definitions. Each definition consists of a colon-separated tuple of source path and destination
|
||||
directory. Each mount definition may be prefixed with <literal>-</literal>, in which case it will be
|
||||
ignored when its source path does not exist. The source argument is a path to a block device node or
|
||||
regular file. If source or destination contain a <literal>:</literal>, it needs to be escaped as
|
||||
<literal>\:</literal>.
|
||||
The device node or file system image file needs to follow the same rules as specified
|
||||
for <varname>RootImage=</varname>. Any mounts created with this option are specific to the unit, and
|
||||
are not visible in the host's mount table.</para>
|
||||
|
||||
<para>These settings may be used more than once, each usage appends to the unit's list of mount
|
||||
paths. If the empty string is assigned, the entire list of mount paths defined prior to this is
|
||||
reset.</para>
|
||||
|
||||
<para>Note that the destination directory must exist or systemd must be able to create it. Thus, it
|
||||
is not possible to use those options for mount points nested underneath paths specified in
|
||||
<varname>InaccessiblePaths=</varname>, or under <filename>/home/</filename> and other protected
|
||||
directories if <varname>ProtectHome=yes</varname> is specified.</para>
|
||||
|
||||
<para>When <varname>DevicePolicy=</varname> is set to <literal>closed</literal> or
|
||||
<literal>strict</literal>, or set to <literal>auto</literal> and <varname>DeviceAllow=</varname> is
|
||||
set, then this setting adds <filename>/dev/loop-control</filename> with <constant>rw</constant> mode,
|
||||
<literal>block-loop</literal> and <literal>block-blkext</literal> with <constant>rwm</constant> mode
|
||||
to <varname>DeviceAllow=</varname>. See
|
||||
<citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
||||
for the details about <varname>DevicePolicy=</varname> or <varname>DeviceAllow=</varname>. Also, see
|
||||
<varname>PrivateDevices=</varname> below, as it may change the setting of
|
||||
<varname>DevicePolicy=</varname>.</para>
|
||||
|
||||
<xi:include href="system-only.xml" xpointer="singular"/></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
|
@ -2427,9 +2391,7 @@ StandardInputData=SWNrIHNpdHplIGRhIHVuJyBlc3NlIEtsb3BzLAp1ZmYgZWVtYWwga2xvcHAncy
|
|||
so that they are automatically established prior to the unit starting up. Note that when this option
|
||||
is used log output of this service does not appear in the regular
|
||||
<citerefentry><refentrytitle>journalctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
|
||||
output, unless the <option>--namespace=</option> option is used.</para>
|
||||
|
||||
<xi:include href="system-only.xml" xpointer="singular"/></listitem>
|
||||
output, unless the <option>--namespace=</option> option is used.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
|
|
|
@ -86,30 +86,25 @@ int extract_first_word(const char **p, char **ret, const char *separators, Extra
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (flags & (EXTRACT_CUNESCAPE|EXTRACT_UNESCAPE_SEPARATORS)) {
|
||||
if (flags & EXTRACT_CUNESCAPE) {
|
||||
bool eight_bit = false;
|
||||
char32_t u;
|
||||
|
||||
if ((flags & EXTRACT_CUNESCAPE) &&
|
||||
(r = cunescape_one(*p, (size_t) -1, &u, &eight_bit, false)) >= 0) {
|
||||
/* A valid escaped sequence */
|
||||
assert(r >= 1);
|
||||
|
||||
r = cunescape_one(*p, (size_t) -1, &u, &eight_bit, false);
|
||||
if (r < 0) {
|
||||
if (flags & EXTRACT_CUNESCAPE_RELAX) {
|
||||
s[sz++] = '\\';
|
||||
s[sz++] = c;
|
||||
} else
|
||||
return -EINVAL;
|
||||
} else {
|
||||
(*p) += r - 1;
|
||||
|
||||
if (eight_bit)
|
||||
s[sz++] = u;
|
||||
else
|
||||
sz += utf8_encode_unichar(s + sz, u);
|
||||
} else if ((flags & EXTRACT_UNESCAPE_SEPARATORS) &&
|
||||
strchr(separators, **p))
|
||||
/* An escaped separator char */
|
||||
s[sz++] = c;
|
||||
else if (flags & EXTRACT_CUNESCAPE_RELAX) {
|
||||
s[sz++] = '\\';
|
||||
s[sz++] = c;
|
||||
} else
|
||||
return -EINVAL;
|
||||
}
|
||||
} else
|
||||
s[sz++] = c;
|
||||
|
||||
|
|
|
@ -7,10 +7,9 @@ typedef enum ExtractFlags {
|
|||
EXTRACT_RELAX = 1 << 0,
|
||||
EXTRACT_CUNESCAPE = 1 << 1,
|
||||
EXTRACT_CUNESCAPE_RELAX = 1 << 2,
|
||||
EXTRACT_UNESCAPE_SEPARATORS = 1 << 3,
|
||||
EXTRACT_UNQUOTE = 1 << 4,
|
||||
EXTRACT_DONT_COALESCE_SEPARATORS = 1 << 5,
|
||||
EXTRACT_RETAIN_ESCAPE = 1 << 6,
|
||||
EXTRACT_UNQUOTE = 1 << 3,
|
||||
EXTRACT_DONT_COALESCE_SEPARATORS = 1 << 4,
|
||||
EXTRACT_RETAIN_ESCAPE = 1 << 5,
|
||||
} ExtractFlags;
|
||||
|
||||
int extract_first_word(const char **p, char **ret, const char *separators, ExtractFlags flags);
|
||||
|
|
|
@ -353,58 +353,6 @@ int strv_split_extract(char ***t, const char *s, const char *separators, Extract
|
|||
return (int) n;
|
||||
}
|
||||
|
||||
int strv_split_colon_pairs(char ***t, const char *s) {
|
||||
_cleanup_strv_free_ char **l = NULL;
|
||||
size_t n = 0, allocated = 0;
|
||||
int r;
|
||||
|
||||
assert(t);
|
||||
assert(s);
|
||||
|
||||
for (;;) {
|
||||
_cleanup_free_ char *first = NULL, *second = NULL, *tuple = NULL, *second_or_empty = NULL;
|
||||
|
||||
r = extract_first_word(&s, &tuple, NULL, EXTRACT_UNQUOTE|EXTRACT_RETAIN_ESCAPE);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
break;
|
||||
|
||||
const char *p = tuple;
|
||||
r = extract_many_words(&p, ":", EXTRACT_CUNESCAPE|EXTRACT_UNESCAPE_SEPARATORS,
|
||||
&first, &second, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
continue;
|
||||
/* Enforce that at most 2 colon-separated words are contained in each group */
|
||||
if (!isempty(p))
|
||||
return -EINVAL;
|
||||
|
||||
second_or_empty = strdup(strempty(second));
|
||||
if (!second_or_empty)
|
||||
return -ENOMEM;
|
||||
|
||||
if (!GREEDY_REALLOC(l, allocated, n + 3))
|
||||
return -ENOMEM;
|
||||
|
||||
l[n++] = TAKE_PTR(first);
|
||||
l[n++] = TAKE_PTR(second_or_empty);
|
||||
|
||||
l[n] = NULL;
|
||||
}
|
||||
|
||||
if (!l) {
|
||||
l = new0(char*, 1);
|
||||
if (!l)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
*t = TAKE_PTR(l);
|
||||
|
||||
return (int) n;
|
||||
}
|
||||
|
||||
char *strv_join_prefix(char * const *l, const char *separator, const char *prefix) {
|
||||
char * const *s;
|
||||
char *r, *e;
|
||||
|
|
|
@ -80,11 +80,6 @@ char **strv_split_newlines(const char *s);
|
|||
|
||||
int strv_split_extract(char ***t, const char *s, const char *separators, ExtractFlags flags);
|
||||
|
||||
/* Given a string containing white-space separated tuples of words themselves separated by ':',
|
||||
* returns a vector of strings. If the second element in a tuple is missing, the corresponding
|
||||
* string in the vector is an empty string. */
|
||||
int strv_split_colon_pairs(char ***t, const char *s);
|
||||
|
||||
char *strv_join_prefix(char * const *l, const char *separator, const char *prefix);
|
||||
static inline char *strv_join(char * const *l, const char *separator) {
|
||||
return strv_join_prefix(l, separator, NULL);
|
||||
|
|
|
@ -815,40 +815,6 @@ static int property_get_root_image_options(
|
|||
return sd_bus_message_close_container(reply);
|
||||
}
|
||||
|
||||
static int property_get_mount_images(
|
||||
sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *reply,
|
||||
void *userdata,
|
||||
sd_bus_error *error) {
|
||||
|
||||
ExecContext *c = userdata;
|
||||
int r;
|
||||
|
||||
assert(bus);
|
||||
assert(c);
|
||||
assert(property);
|
||||
assert(reply);
|
||||
|
||||
r = sd_bus_message_open_container(reply, 'a', "(ssb)");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
for (size_t i = 0; i < c->n_mount_images; i++) {
|
||||
r = sd_bus_message_append(
|
||||
reply, "(ssb)",
|
||||
c->mount_images[i].source,
|
||||
c->mount_images[i].destination,
|
||||
c->mount_images[i].ignore_enoent);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return sd_bus_message_close_container(reply);
|
||||
}
|
||||
|
||||
const sd_bus_vtable bus_exec_vtable[] = {
|
||||
SD_BUS_VTABLE_START(0),
|
||||
SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(ExecContext, environment), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
|
@ -897,7 +863,6 @@ const sd_bus_vtable bus_exec_vtable[] = {
|
|||
SD_BUS_PROPERTY("RootHashSignature", "ay", property_get_root_hash_sig, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("RootHashSignaturePath", "s", NULL, offsetof(ExecContext, root_hash_sig_path), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("RootVerity", "s", NULL, offsetof(ExecContext, root_verity), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("MountImages", "a(ssb)", property_get_mount_images, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("OOMScoreAdjust", "i", property_get_oom_score_adjust, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("CoredumpFilter", "t", property_get_coredump_filter, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("Nice", "i", property_get_nice, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
|
@ -2931,73 +2896,6 @@ int bus_exec_context_set_transient_property(
|
|||
return 1;
|
||||
}
|
||||
|
||||
} else if (streq(name, "MountImages")) {
|
||||
_cleanup_free_ char *format_str = NULL;
|
||||
MountImage *mount_images = NULL;
|
||||
size_t n_mount_images = 0;
|
||||
char *source, *destination;
|
||||
int permissive;
|
||||
|
||||
r = sd_bus_message_enter_container(message, 'a', "(ssb)");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
while ((r = sd_bus_message_read(message, "(ssb)", &source, &destination, &permissive)) > 0) {
|
||||
char *tuple;
|
||||
|
||||
if (!path_is_absolute(source))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Source path %s is not absolute.", source);
|
||||
if (!path_is_normalized(source))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Source path %s is not normalized.", source);
|
||||
if (!path_is_absolute(destination))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Destination path %s is not absolute.", destination);
|
||||
if (!path_is_normalized(destination))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Destination path %s is not normalized.", destination);
|
||||
|
||||
tuple = strjoin(format_str, format_str ? " " : "", permissive ? "-" : "", source, ":", destination);
|
||||
if (!tuple)
|
||||
return -ENOMEM;
|
||||
free_and_replace(format_str, tuple);
|
||||
|
||||
r = mount_image_add(&mount_images, &n_mount_images,
|
||||
&(MountImage) {
|
||||
.source = source,
|
||||
.destination = destination,
|
||||
.ignore_enoent = permissive,
|
||||
});
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_message_exit_container(message);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
if (n_mount_images == 0) {
|
||||
c->mount_images = mount_image_free_many(c->mount_images, &c->n_mount_images);
|
||||
|
||||
unit_write_settingf(u, flags, name, "%s=", name);
|
||||
} else {
|
||||
for (size_t i = 0; i < n_mount_images; ++i) {
|
||||
r = mount_image_add(&c->mount_images, &c->n_mount_images, &mount_images[i]);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
unit_write_settingf(u, flags|UNIT_ESCAPE_C|UNIT_ESCAPE_SPECIFIERS,
|
||||
name,
|
||||
"%s=%s",
|
||||
name,
|
||||
format_str);
|
||||
}
|
||||
}
|
||||
|
||||
mount_images = mount_image_free_many(mount_images, &n_mount_images);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -1932,9 +1932,6 @@ static bool exec_needs_mount_namespace(
|
|||
if (context->n_temporary_filesystems > 0)
|
||||
return true;
|
||||
|
||||
if (context->n_mount_images > 0)
|
||||
return true;
|
||||
|
||||
if (!IN_SET(context->mount_flags, 0, MS_SHARED))
|
||||
return true;
|
||||
|
||||
|
@ -2573,9 +2570,6 @@ static bool insist_on_sandboxing(
|
|||
if (root_dir || root_image)
|
||||
return true;
|
||||
|
||||
if (context->n_mount_images > 0)
|
||||
return true;
|
||||
|
||||
if (context->dynamic_user)
|
||||
return true;
|
||||
|
||||
|
@ -2675,8 +2669,6 @@ static int apply_mount_namespace(
|
|||
n_bind_mounts,
|
||||
context->temporary_filesystems,
|
||||
context->n_temporary_filesystems,
|
||||
context->mount_images,
|
||||
context->n_mount_images,
|
||||
tmp_dir,
|
||||
var_tmp_dir,
|
||||
context->log_namespace,
|
||||
|
@ -4242,7 +4234,6 @@ void exec_context_done(ExecContext *c) {
|
|||
temporary_filesystem_free_many(c->temporary_filesystems, c->n_temporary_filesystems);
|
||||
c->temporary_filesystems = NULL;
|
||||
c->n_temporary_filesystems = 0;
|
||||
c->mount_images = mount_image_free_many(c->mount_images, &c->n_mount_images);
|
||||
|
||||
cpu_set_reset(&c->cpu_set);
|
||||
numa_policy_reset(&c->numa_policy);
|
||||
|
@ -5034,12 +5025,6 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) {
|
|||
else
|
||||
fprintf(f, "%d\n", c->syscall_errno);
|
||||
}
|
||||
|
||||
for (i = 0; i < c->n_mount_images; i++)
|
||||
fprintf(f, "%sMountImages: %s%s:%s\n", prefix,
|
||||
c->mount_images[i].ignore_enoent ? "-": "",
|
||||
c->mount_images[i].source,
|
||||
c->mount_images[i].destination);
|
||||
}
|
||||
|
||||
bool exec_context_maintains_privileges(const ExecContext *c) {
|
||||
|
|
|
@ -239,8 +239,6 @@ struct ExecContext {
|
|||
size_t n_bind_mounts;
|
||||
TemporaryFileSystem *temporary_filesystems;
|
||||
size_t n_temporary_filesystems;
|
||||
MountImage *mount_images;
|
||||
size_t n_mount_images;
|
||||
|
||||
uint64_t capability_bounding_set;
|
||||
uint64_t capability_ambient_set;
|
||||
|
|
|
@ -27,7 +27,6 @@ $1.RootImageOptions, config_parse_root_image_options, 0,
|
|||
$1.RootHash, config_parse_exec_root_hash, 0, offsetof($1, exec_context)
|
||||
$1.RootHashSignature, config_parse_exec_root_hash_sig, 0, offsetof($1, exec_context)
|
||||
$1.RootVerity, config_parse_unit_path_printf, true, offsetof($1, exec_context.root_verity)
|
||||
$1.MountImages, config_parse_mount_images, 0, offsetof($1, exec_context)
|
||||
$1.User, config_parse_user_group_compat, 0, offsetof($1, exec_context.user)
|
||||
$1.Group, config_parse_user_group_compat, 0, offsetof($1, exec_context.group)
|
||||
$1.SupplementaryGroups, config_parse_user_group_strv_compat, 0, offsetof($1, exec_context.supplementary_groups)
|
||||
|
|
|
@ -4675,94 +4675,6 @@ int config_parse_bind_paths(
|
|||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_mount_images(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
unsigned section_line,
|
||||
const char *lvalue,
|
||||
int ltype,
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
_cleanup_strv_free_ char **l = NULL;
|
||||
ExecContext *c = data;
|
||||
const Unit *u = userdata;
|
||||
char **source = NULL, **destination = NULL;
|
||||
int r;
|
||||
|
||||
assert(filename);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
assert(data);
|
||||
|
||||
if (isempty(rvalue)) {
|
||||
/* Empty assignment resets the list */
|
||||
c->mount_images = mount_image_free_many(c->mount_images, &c->n_mount_images);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = strv_split_colon_pairs(&l, rvalue);
|
||||
if (r == -ENOMEM)
|
||||
return log_oom();
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse %s, ignoring: %s", lvalue, rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
STRV_FOREACH_PAIR(source, destination, l) {
|
||||
_cleanup_free_ char *sresolved = NULL, *dresolved = NULL;
|
||||
char *s = NULL;
|
||||
bool permissive = false;
|
||||
|
||||
r = unit_full_printf(u, *source, &sresolved);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, r,
|
||||
"Failed to resolve unit specifiers in \"%s\", ignoring: %m", *source);
|
||||
continue;
|
||||
}
|
||||
|
||||
s = sresolved;
|
||||
if (s[0] == '-') {
|
||||
permissive = true;
|
||||
s++;
|
||||
}
|
||||
|
||||
r = path_simplify_and_warn(s, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue);
|
||||
if (r < 0)
|
||||
continue;
|
||||
|
||||
if (isempty(*destination)) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, 0, "Missing destination in %s, ignoring: %s", lvalue, rvalue);
|
||||
continue;
|
||||
}
|
||||
|
||||
r = unit_full_printf(u, *destination, &dresolved);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, r,
|
||||
"Failed to resolve specifiers in \"%s\", ignoring: %m", *destination);
|
||||
continue;
|
||||
}
|
||||
|
||||
r = path_simplify_and_warn(dresolved, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue);
|
||||
if (r < 0)
|
||||
continue;
|
||||
|
||||
r = mount_image_add(&c->mount_images, &c->n_mount_images,
|
||||
&(MountImage) {
|
||||
.source = s,
|
||||
.destination = dresolved,
|
||||
.ignore_enoent = permissive,
|
||||
});
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_job_timeout_sec(
|
||||
const char* unit,
|
||||
const char *filename,
|
||||
|
|
|
@ -128,7 +128,6 @@ CONFIG_PARSER_PROTOTYPE(config_parse_output_restricted);
|
|||
CONFIG_PARSER_PROTOTYPE(config_parse_crash_chvt);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_timeout_abort);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_swap_priority);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_mount_images);
|
||||
|
||||
/* gperf prototypes */
|
||||
const struct ConfigPerfItem* load_fragment_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
#include "format-util.h"
|
||||
#include "fs-util.h"
|
||||
#include "label.h"
|
||||
#include "list.h"
|
||||
#include "loop-util.h"
|
||||
#include "loopback-setup.h"
|
||||
#include "mkdir.h"
|
||||
|
@ -41,7 +40,6 @@
|
|||
typedef enum MountMode {
|
||||
/* This is ordered by priority! */
|
||||
INACCESSIBLE,
|
||||
MOUNT_IMAGES,
|
||||
BIND_MOUNT,
|
||||
BIND_MOUNT_RECURSIVE,
|
||||
PRIVATE_TMP,
|
||||
|
@ -67,13 +65,12 @@ typedef struct MountEntry {
|
|||
bool nosuid:1; /* Shall set MS_NOSUID on the mount itself */
|
||||
bool applied:1; /* Already applied */
|
||||
char *path_malloc; /* Use this instead of 'path_const' if we had to allocate memory */
|
||||
const char *source_const; /* The source path, for bind mounts or images */
|
||||
const char *source_const; /* The source path, for bind mounts */
|
||||
char *source_malloc;
|
||||
const char *options_const;/* Mount options for tmpfs */
|
||||
char *options_malloc;
|
||||
unsigned long flags; /* Mount flags used by EMPTY_DIR and TMPFS. Do not include MS_RDONLY here, but please use read_only. */
|
||||
unsigned n_followed;
|
||||
LIST_FIELDS(MountEntry, mount_entry);
|
||||
} MountEntry;
|
||||
|
||||
/* If MountAPIVFS= is used, let's mount /sys and /proc into the it, but only as a fallback if the user hasn't mounted
|
||||
|
@ -208,7 +205,6 @@ static const char * const mount_mode_table[_MOUNT_MODE_MAX] = {
|
|||
[READONLY] = "read-only",
|
||||
[READWRITE] = "read-write",
|
||||
[TMPFS] = "tmpfs",
|
||||
[MOUNT_IMAGES] = "mount-images",
|
||||
[READWRITE_IMPLICIT] = "rw-implicit",
|
||||
};
|
||||
|
||||
|
@ -329,23 +325,6 @@ static int append_bind_mounts(MountEntry **p, const BindMount *binds, size_t n)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int append_mount_images(MountEntry **p, const MountImage *mount_images, size_t n) {
|
||||
assert(p);
|
||||
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
const MountImage *m = mount_images + i;
|
||||
|
||||
*((*p)++) = (MountEntry) {
|
||||
.path_const = m->destination,
|
||||
.mode = MOUNT_IMAGES,
|
||||
.source_const = m->source,
|
||||
.ignore = m->ignore_enoent,
|
||||
};
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int append_tmpfs_mounts(MountEntry **p, const TemporaryFileSystem *tmpfs, size_t n) {
|
||||
assert(p);
|
||||
|
||||
|
@ -903,61 +882,6 @@ static int mount_tmpfs(const MountEntry *m) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int mount_images(const MountEntry *m) {
|
||||
_cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL;
|
||||
_cleanup_(decrypted_image_unrefp) DecryptedImage *decrypted_image = NULL;
|
||||
_cleanup_(dissected_image_unrefp) DissectedImage *dissected_image = NULL;
|
||||
_cleanup_free_ void *root_hash_decoded = NULL;
|
||||
_cleanup_free_ char *verity_data = NULL, *hash_sig = NULL;
|
||||
DissectImageFlags dissect_image_flags = m->read_only ? DISSECT_IMAGE_READ_ONLY : 0;
|
||||
size_t root_hash_size = 0;
|
||||
int r;
|
||||
|
||||
r = verity_metadata_load(mount_entry_source(m), NULL, &root_hash_decoded, &root_hash_size, &verity_data, &hash_sig);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to load root hash: %m");
|
||||
dissect_image_flags |= verity_data ? DISSECT_IMAGE_NO_PARTITION_TABLE : 0;
|
||||
|
||||
r = loop_device_make_by_path(mount_entry_source(m),
|
||||
m->read_only ? O_RDONLY : -1 /* < 0 means writable if possible, read-only as fallback */,
|
||||
verity_data ? 0 : LO_FLAGS_PARTSCAN,
|
||||
&loop_device);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to create loop device for image: %m");
|
||||
|
||||
r = dissect_image(loop_device->fd, root_hash_decoded, root_hash_size, verity_data, NULL, dissect_image_flags, &dissected_image);
|
||||
/* No partition table? Might be a single-filesystem image, try again */
|
||||
if (!verity_data && r < 0 && r == -ENOPKG)
|
||||
r = dissect_image(loop_device->fd, root_hash_decoded, root_hash_size, verity_data, NULL, dissect_image_flags|DISSECT_IMAGE_NO_PARTITION_TABLE, &dissected_image);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to dissect image: %m");
|
||||
|
||||
r = dissected_image_decrypt(dissected_image, NULL, root_hash_decoded, root_hash_size, verity_data, hash_sig, NULL, 0, dissect_image_flags, &decrypted_image);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to decrypt dissected image: %m");
|
||||
|
||||
r = mkdir_p_label(mount_entry_path(m), 0755);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to create destination directory %s: %m", mount_entry_path(m));
|
||||
r = umount_recursive(mount_entry_path(m), 0);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to umount under destination directory %s: %m", mount_entry_path(m));
|
||||
|
||||
r = dissected_image_mount(dissected_image, mount_entry_path(m), UID_INVALID, dissect_image_flags);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to mount image: %m");
|
||||
|
||||
if (decrypted_image) {
|
||||
r = decrypted_image_relinquish(decrypted_image);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to relinquish decrypted image: %m");
|
||||
}
|
||||
|
||||
loop_device_relinquish(loop_device);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int follow_symlink(
|
||||
const char *root_directory,
|
||||
MountEntry *m) {
|
||||
|
@ -1107,9 +1031,6 @@ static int apply_mount(
|
|||
case PROCFS:
|
||||
return mount_procfs(m);
|
||||
|
||||
case MOUNT_IMAGES:
|
||||
return mount_images(m);
|
||||
|
||||
default:
|
||||
assert_not_reached("Unknown mode");
|
||||
}
|
||||
|
@ -1228,7 +1149,6 @@ static size_t namespace_calculate_mounts(
|
|||
char** empty_directories,
|
||||
size_t n_bind_mounts,
|
||||
size_t n_temporary_filesystems,
|
||||
size_t n_mount_images,
|
||||
const char* tmp_dir,
|
||||
const char* var_tmp_dir,
|
||||
const char* log_namespace,
|
||||
|
@ -1258,7 +1178,6 @@ static size_t namespace_calculate_mounts(
|
|||
strv_length(inaccessible_paths) +
|
||||
strv_length(empty_directories) +
|
||||
n_bind_mounts +
|
||||
n_mount_images +
|
||||
n_temporary_filesystems +
|
||||
ns_info->private_dev +
|
||||
(ns_info->protect_kernel_tunables ? ELEMENTSOF(protect_kernel_tunables_table) : 0) +
|
||||
|
@ -1348,8 +1267,6 @@ int setup_namespace(
|
|||
size_t n_bind_mounts,
|
||||
const TemporaryFileSystem *temporary_filesystems,
|
||||
size_t n_temporary_filesystems,
|
||||
const MountImage *mount_images,
|
||||
size_t n_mount_images,
|
||||
const char* tmp_dir,
|
||||
const char* var_tmp_dir,
|
||||
const char *log_namespace,
|
||||
|
@ -1457,7 +1374,6 @@ int setup_namespace(
|
|||
empty_directories,
|
||||
n_bind_mounts,
|
||||
n_temporary_filesystems,
|
||||
n_mount_images,
|
||||
tmp_dir, var_tmp_dir,
|
||||
log_namespace,
|
||||
protect_home, protect_system);
|
||||
|
@ -1511,10 +1427,6 @@ int setup_namespace(
|
|||
};
|
||||
}
|
||||
|
||||
r = append_mount_images(&m, mount_images, n_mount_images);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
if (ns_info->private_dev) {
|
||||
*(m++) = (MountEntry) {
|
||||
.path_const = "/dev",
|
||||
|
@ -1829,53 +1741,6 @@ int bind_mount_add(BindMount **b, size_t *n, const BindMount *item) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
MountImage* mount_image_free_many(MountImage *m, size_t *n) {
|
||||
size_t i;
|
||||
|
||||
assert(n);
|
||||
assert(m || *n == 0);
|
||||
|
||||
for (i = 0; i < *n; i++) {
|
||||
free(m[i].source);
|
||||
free(m[i].destination);
|
||||
}
|
||||
|
||||
free(m);
|
||||
*n = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int mount_image_add(MountImage **m, size_t *n, const MountImage *item) {
|
||||
_cleanup_free_ char *s = NULL, *d = NULL;
|
||||
MountImage *c;
|
||||
|
||||
assert(m);
|
||||
assert(n);
|
||||
assert(item);
|
||||
|
||||
s = strdup(item->source);
|
||||
if (!s)
|
||||
return -ENOMEM;
|
||||
|
||||
d = strdup(item->destination);
|
||||
if (!d)
|
||||
return -ENOMEM;
|
||||
|
||||
c = reallocarray(*m, *n + 1, sizeof(MountImage));
|
||||
if (!c)
|
||||
return -ENOMEM;
|
||||
|
||||
*m = c;
|
||||
|
||||
c[(*n) ++] = (MountImage) {
|
||||
.source = TAKE_PTR(s),
|
||||
.destination = TAKE_PTR(d),
|
||||
.ignore_enoent = item->ignore_enoent,
|
||||
};
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void temporary_filesystem_free_many(TemporaryFileSystem *t, size_t n) {
|
||||
size_t i;
|
||||
|
||||
|
|
|
@ -8,8 +8,6 @@
|
|||
typedef struct NamespaceInfo NamespaceInfo;
|
||||
typedef struct BindMount BindMount;
|
||||
typedef struct TemporaryFileSystem TemporaryFileSystem;
|
||||
typedef struct MountImage MountImage;
|
||||
typedef struct MountEntry MountEntry;
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
|
@ -74,12 +72,6 @@ struct TemporaryFileSystem {
|
|||
char *options;
|
||||
};
|
||||
|
||||
struct MountImage {
|
||||
char *source;
|
||||
char *destination;
|
||||
bool ignore_enoent;
|
||||
};
|
||||
|
||||
int setup_namespace(
|
||||
const char *root_directory,
|
||||
const char *root_image,
|
||||
|
@ -93,8 +85,6 @@ int setup_namespace(
|
|||
size_t n_bind_mounts,
|
||||
const TemporaryFileSystem *temporary_filesystems,
|
||||
size_t n_temporary_filesystems,
|
||||
const MountImage *mount_images,
|
||||
size_t n_mount_images,
|
||||
const char *tmp_dir,
|
||||
const char *var_tmp_dir,
|
||||
const char *log_namespace,
|
||||
|
@ -142,9 +132,6 @@ void temporary_filesystem_free_many(TemporaryFileSystem *t, size_t n);
|
|||
int temporary_filesystem_add(TemporaryFileSystem **t, size_t *n,
|
||||
const char *path, const char *options);
|
||||
|
||||
MountImage* mount_image_free_many(MountImage *m, size_t *n);
|
||||
int mount_image_add(MountImage **m, size_t *n, const MountImage *item);
|
||||
|
||||
const char* namespace_type_to_string(NamespaceType t) _const_;
|
||||
NamespaceType namespace_type_from_string(const char *s) _pure_;
|
||||
|
||||
|
|
|
@ -4527,11 +4527,11 @@ int unit_patch_contexts(Unit *u) {
|
|||
cc->device_policy == CGROUP_DEVICE_POLICY_AUTO)
|
||||
cc->device_policy = CGROUP_DEVICE_POLICY_CLOSED;
|
||||
|
||||
if ((ec->root_image || !LIST_IS_EMPTY(ec->mount_images)) &&
|
||||
if (ec->root_image &&
|
||||
(cc->device_policy != CGROUP_DEVICE_POLICY_AUTO || cc->device_allow)) {
|
||||
const char *p;
|
||||
|
||||
/* When RootImage= or MountImages= is specified, the following devices are touched. */
|
||||
/* When RootImage= is specified, the following devices are touched. */
|
||||
FOREACH_STRING(p, "/dev/loop-control", "/dev/mapper/control") {
|
||||
r = cgroup_add_device_allow(cc, p, "rw");
|
||||
if (r < 0)
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
#include "hostname-util.h"
|
||||
#include "in-addr-util.h"
|
||||
#include "ip-protocol-list.h"
|
||||
#include "libmount-util.h"
|
||||
#include "locale-util.h"
|
||||
#include "log.h"
|
||||
#include "missing_fs.h"
|
||||
|
@ -1523,65 +1522,6 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (streq(field, "MountImages")) {
|
||||
_cleanup_strv_free_ char **l = NULL;
|
||||
char **source = NULL, **destination = NULL;
|
||||
const char *p = eq;
|
||||
|
||||
r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field);
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
r = sd_bus_message_open_container(m, 'v', "a(ssb)");
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
r = sd_bus_message_open_container(m, 'a', "(ssb)");
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
r = strv_split_colon_pairs(&l, p);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse argument: %m");
|
||||
|
||||
STRV_FOREACH_PAIR(source, destination, l) {
|
||||
char *s = *source;
|
||||
bool permissive = false;
|
||||
|
||||
if (s[0] == '-') {
|
||||
permissive = true;
|
||||
s++;
|
||||
}
|
||||
|
||||
if (isempty(*destination))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Missing argument after ':': %s",
|
||||
eq);
|
||||
|
||||
r = sd_bus_message_append(m, "(ssb)", s, *destination, permissive);
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
}
|
||||
|
||||
r = sd_bus_message_close_container(m);
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
r = sd_bus_message_close_container(m);
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
r = sd_bus_message_close_container(m);
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -5408,39 +5408,6 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
|
|||
bus_print_property_value(name, expected_value, value, affinity);
|
||||
|
||||
return 1;
|
||||
} else if (streq(name, "MountImages")) {
|
||||
_cleanup_free_ char *paths = NULL;
|
||||
const char *source, *dest;
|
||||
int ignore_enoent;
|
||||
|
||||
r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ssb)");
|
||||
if (r < 0)
|
||||
return bus_log_parse_error(r);
|
||||
|
||||
while ((r = sd_bus_message_read(m, "(ssb)", &source, &dest, &ignore_enoent)) > 0) {
|
||||
_cleanup_free_ char *str = NULL;
|
||||
|
||||
if (isempty(source))
|
||||
continue;
|
||||
|
||||
if (asprintf(&str, "%s%s:%s", ignore_enoent ? "-" : "", source, dest) < 0)
|
||||
return log_oom();
|
||||
|
||||
if (!strextend_with_separator(&paths, " ", str, NULL))
|
||||
return log_oom();
|
||||
}
|
||||
if (r < 0)
|
||||
return bus_log_parse_error(r);
|
||||
|
||||
r = sd_bus_message_exit_container(m);
|
||||
if (r < 0)
|
||||
return bus_log_parse_error(r);
|
||||
|
||||
if (all || !isempty(paths))
|
||||
bus_print_property_value(name, expected_value, value, strempty(paths));
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
/* This is a private header; never even think of including this directly! */
|
||||
|
||||
#if defined(__INCLUDE_LEVEL__) && __INCLUDE_LEVEL__ <= 1 && !defined(__COVERITY__)
|
||||
#if defined(__INCLUDE_LEVEL__) && __INCLUDE_LEVEL__ <= 1
|
||||
# error "Do not include _sd-common.h directly; it is a private header."
|
||||
#endif
|
||||
|
||||
|
|
|
@ -341,46 +341,6 @@ static void test_extract_first_word(void) {
|
|||
assert_se(streq(t, "foo\\xbar"));
|
||||
free(t);
|
||||
assert_se(p == NULL);
|
||||
|
||||
p = "\\:";
|
||||
assert_se(extract_first_word(&p, &t, ":", EXTRACT_CUNESCAPE|EXTRACT_UNESCAPE_SEPARATORS) == 1);
|
||||
assert_se(streq(t, ":"));
|
||||
free(t);
|
||||
assert_se(p == NULL);
|
||||
|
||||
p = "a\\:b";
|
||||
assert_se(extract_first_word(&p, &t, ":", EXTRACT_CUNESCAPE|EXTRACT_UNESCAPE_SEPARATORS) == 1);
|
||||
assert_se(streq(t, "a:b"));
|
||||
free(t);
|
||||
assert_se(p == NULL);
|
||||
|
||||
p = "a\\ b:c";
|
||||
assert_se(extract_first_word(&p, &t, WHITESPACE ":", EXTRACT_CUNESCAPE|EXTRACT_UNESCAPE_SEPARATORS) == 1);
|
||||
assert_se(streq(t, "a b"));
|
||||
free(t);
|
||||
assert_se(extract_first_word(&p, &t, WHITESPACE ":", EXTRACT_CUNESCAPE|EXTRACT_UNESCAPE_SEPARATORS) == 1);
|
||||
assert_se(streq(t, "c"));
|
||||
free(t);
|
||||
assert_se(p == NULL);
|
||||
|
||||
p = "\\:";
|
||||
assert_se(extract_first_word(&p, &t, ":", EXTRACT_CUNESCAPE) == -EINVAL);
|
||||
|
||||
p = "a\\:b";
|
||||
assert_se(extract_first_word(&p, &t, ":", EXTRACT_CUNESCAPE) == -EINVAL);
|
||||
assert_se(extract_first_word(&p, &t, ":", EXTRACT_CUNESCAPE) == 1);
|
||||
assert_se(streq(t, "b"));
|
||||
free(t);
|
||||
|
||||
p = "a\\ b:c";
|
||||
assert_se(extract_first_word(&p, &t, WHITESPACE ":", EXTRACT_CUNESCAPE) == -EINVAL);
|
||||
assert_se(extract_first_word(&p, &t, WHITESPACE ":", EXTRACT_CUNESCAPE) == 1);
|
||||
assert_se(streq(t, "b"));
|
||||
free(t);
|
||||
assert_se(extract_first_word(&p, &t, WHITESPACE ":", EXTRACT_CUNESCAPE) == 1);
|
||||
assert_se(streq(t, "c"));
|
||||
free(t);
|
||||
assert_se(p == NULL);
|
||||
}
|
||||
|
||||
static void test_extract_first_word_and_warn(void) {
|
||||
|
@ -529,7 +489,7 @@ static void test_extract_first_word_and_warn(void) {
|
|||
|
||||
static void test_extract_many_words(void) {
|
||||
const char *p, *original;
|
||||
char *a, *b, *c, *d, *e, *f;
|
||||
char *a, *b, *c;
|
||||
|
||||
p = original = "foobar waldi piep";
|
||||
assert_se(extract_many_words(&p, NULL, 0, &a, &b, &c, NULL) == 3);
|
||||
|
@ -541,24 +501,6 @@ static void test_extract_many_words(void) {
|
|||
free(b);
|
||||
free(c);
|
||||
|
||||
p = original = "foobar:waldi:piep ba1:ba2";
|
||||
assert_se(extract_many_words(&p, ":" WHITESPACE, 0, &a, &b, &c, NULL) == 3);
|
||||
assert_se(!isempty(p));
|
||||
assert_se(streq_ptr(a, "foobar"));
|
||||
assert_se(streq_ptr(b, "waldi"));
|
||||
assert_se(streq_ptr(c, "piep"));
|
||||
assert_se(extract_many_words(&p, ":" WHITESPACE, 0, &d, &e, &f, NULL) == 2);
|
||||
assert_se(isempty(p));
|
||||
assert_se(streq_ptr(d, "ba1"));
|
||||
assert_se(streq_ptr(e, "ba2"));
|
||||
assert_se(isempty(f));
|
||||
free(a);
|
||||
free(b);
|
||||
free(c);
|
||||
free(d);
|
||||
free(e);
|
||||
free(f);
|
||||
|
||||
p = original = "'foobar' wa\"ld\"i ";
|
||||
assert_se(extract_many_words(&p, NULL, 0, &a, &b, &c, NULL) == 2);
|
||||
assert_se(isempty(p));
|
||||
|
|
|
@ -159,7 +159,6 @@ static void test_protect_kernel_logs(void) {
|
|||
NULL,
|
||||
NULL, 0,
|
||||
NULL, 0,
|
||||
NULL, 0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
|
|
|
@ -71,8 +71,6 @@ int main(int argc, char *argv[]) {
|
|||
NULL,
|
||||
&(BindMount) { .source = (char*) "/usr/bin", .destination = (char*) "/etc/systemd", .read_only = true }, 1,
|
||||
&(TemporaryFileSystem) { .path = (char*) "/var", .options = (char*) "ro" }, 1,
|
||||
NULL,
|
||||
0,
|
||||
tmp_dir,
|
||||
var_tmp_dir,
|
||||
NULL,
|
||||
|
|
|
@ -407,35 +407,6 @@ static void test_strv_split_extract(void) {
|
|||
assert_se(streq_ptr(l[5], NULL));
|
||||
}
|
||||
|
||||
static void test_strv_split_colon_pairs(void) {
|
||||
_cleanup_strv_free_ char **l = NULL;
|
||||
const char *str = "one:two three four:five six seven:eight\\:nine ten\\:eleven\\\\",
|
||||
*str_inval="one:two three:four:five";
|
||||
int r;
|
||||
|
||||
log_info("/* %s */", __func__);
|
||||
|
||||
r = strv_split_colon_pairs(&l, str);
|
||||
assert_se(r == (int) strv_length(l));
|
||||
assert_se(r == 12);
|
||||
assert_se(streq_ptr(l[0], "one"));
|
||||
assert_se(streq_ptr(l[1], "two"));
|
||||
assert_se(streq_ptr(l[2], "three"));
|
||||
assert_se(streq_ptr(l[3], ""));
|
||||
assert_se(streq_ptr(l[4], "four"));
|
||||
assert_se(streq_ptr(l[5], "five"));
|
||||
assert_se(streq_ptr(l[6], "six"));
|
||||
assert_se(streq_ptr(l[7], ""));
|
||||
assert_se(streq_ptr(l[8], "seven"));
|
||||
assert_se(streq_ptr(l[9], "eight:nine"));
|
||||
assert_se(streq_ptr(l[10], "ten:eleven\\"));
|
||||
assert_se(streq_ptr(l[11], ""));
|
||||
assert_se(streq_ptr(l[12], NULL));
|
||||
|
||||
r = strv_split_colon_pairs(&l, str_inval);
|
||||
assert_se(r == -EINVAL);
|
||||
}
|
||||
|
||||
static void test_strv_split_newlines(void) {
|
||||
unsigned i = 0;
|
||||
char **s;
|
||||
|
@ -1027,7 +998,6 @@ int main(int argc, char *argv[]) {
|
|||
test_strv_split();
|
||||
test_strv_split_empty();
|
||||
test_strv_split_extract();
|
||||
test_strv_split_colon_pairs();
|
||||
test_strv_split_newlines();
|
||||
test_strv_split_nulstr();
|
||||
test_strv_parse_nulstr();
|
||||
|
|
|
@ -155,26 +155,6 @@ journalctl -b -u testservice-50b.service | grep -F "squashfs" | grep -q -F "noat
|
|||
# Check that specifier escape is applied %%foo -> %foo
|
||||
busctl get-property org.freedesktop.systemd1 /org/freedesktop/systemd1/unit/testservice_2d50b_2eservice org.freedesktop.systemd1.Service RootImageOptions | grep -F "nosuid,dev,%foo"
|
||||
|
||||
# Now do some checks with MountImages, both by itself and in combination with RootImage, and as single FS or GPT image
|
||||
systemd-run -t --property MountImages="${image}.gpt:/run/img1 ${image}.raw:/run/img2" /usr/bin/cat /run/img1/usr/lib/os-release | grep -q -F "MARKER=1"
|
||||
systemd-run -t --property MountImages="${image}.gpt:/run/img1 ${image}.raw:/run/img2" /usr/bin/cat /run/img2/usr/lib/os-release | grep -q -F "MARKER=1"
|
||||
systemd-run -t --property MountImages="${image}.raw:/run/img2\:3" /usr/bin/cat /run/img2:3/usr/lib/os-release | grep -q -F "MARKER=1"
|
||||
systemd-run -t --property TemporaryFileSystem=/run --property RootImage=${image}.raw --property MountImages="${image}.gpt:/run/img1 ${image}.raw:/run/img2" /usr/bin/cat /usr/lib/os-release | grep -q -F "MARKER=1"
|
||||
systemd-run -t --property TemporaryFileSystem=/run --property RootImage=${image}.raw --property MountImages="${image}.gpt:/run/img1 ${image}.raw:/run/img2" /usr/bin/cat /run/img1/usr/lib/os-release | grep -q -F "MARKER=1"
|
||||
systemd-run -t --property TemporaryFileSystem=/run --property RootImage=${image}.gpt --property RootHash=${roothash} --property MountImages="${image}.gpt:/run/img1 ${image}.raw:/run/img2" /usr/bin/cat /run/img2/usr/lib/os-release | grep -q -F "MARKER=1"
|
||||
cat >/run/systemd/system/testservice-50.service <<EOF
|
||||
[Service]
|
||||
TemporaryFileSystem=/run
|
||||
RootImage=${image}.raw
|
||||
MountImages=${image}.gpt:/run/img1
|
||||
MountImages=${image}.raw:/run/img2\:3
|
||||
ExecStart=/usr/bin/cat /run/img1/usr/lib/os-release
|
||||
ExecStart=/usr/bin/cat /run/img2:3/usr/lib/os-release
|
||||
Type=oneshot
|
||||
EOF
|
||||
systemctl start testservice-50.service
|
||||
journalctl -b -u testservice-50.service | grep -q -F "MARKER=1"
|
||||
|
||||
echo OK > /testok
|
||||
|
||||
exit 0
|
||||
|
|
Loading…
Reference in New Issue