mirror of
https://github.com/systemd/systemd
synced 2025-09-23 22:04:45 +02:00
Compare commits
23 Commits
d7b34e3841
...
2e2f6a01a0
Author | SHA1 | Date | |
---|---|---|---|
![]() |
2e2f6a01a0 | ||
![]() |
5dc60faae5 | ||
![]() |
2b0bf3ccf8 | ||
![]() |
9870cfdf7f | ||
![]() |
60e3a5a252 | ||
![]() |
dea7f5cc87 | ||
![]() |
f4e1a42592 | ||
![]() |
d1ca1f7c2a | ||
![]() |
a53f024d71 | ||
![]() |
cd990847b9 | ||
![]() |
8ab0f03266 | ||
![]() |
0da425df65 | ||
![]() |
737ec51444 | ||
![]() |
a122502077 | ||
![]() |
dcfdd62184 | ||
![]() |
3ff9fa591e | ||
![]() |
827ea52125 | ||
![]() |
e49ee28522 | ||
![]() |
e2ec9c4d3a | ||
![]() |
9ecf5d9340 | ||
![]() |
3f2e15abc5 | ||
![]() |
6371e69b49 | ||
![]() |
045c5faf5a |
8
TODO
8
TODO
@ -49,6 +49,9 @@ Features:
|
||||
|
||||
* nspawn: support time namespaces
|
||||
|
||||
* systemd-firstboot: make sure to always use chase_symlinks() before
|
||||
reading/writing files
|
||||
|
||||
* add ConditionSecurity=tpm2
|
||||
|
||||
* Remove any support for booting without /usr pre-mounted in the initrd entirely.
|
||||
@ -94,8 +97,9 @@ Features:
|
||||
this, it's useful to have one that can dump contents of them, too.
|
||||
|
||||
* All tools that support --root= should also learn --image= so that they can
|
||||
operate on disk images directly. Specifically: bootctl, firstboot, tmpfiles,
|
||||
sysusers, systemctl, repart, journalctl, coredumpctl.
|
||||
operate on disk images directly. Specifically: bootctl, tmpfiles, sysusers,
|
||||
systemctl, repart, journalctl, coredumpctl. (Already done: systemd-nspawn,
|
||||
systemd-firstboot)
|
||||
|
||||
* seccomp: by default mask x32 ABI system wide on x86-64. it's on its way out
|
||||
|
||||
|
@ -180,7 +180,7 @@ strictly local context and without signatures doesn't have to deal with the
|
||||
`perMachine` or `binding` sections and can include its data exclusively in the
|
||||
regular section. A service that uses a separate, private channel for
|
||||
authenticating users (or that doesn't have a concept of authentication at all)
|
||||
does not need to to be concerned with the `secret` section of user records, as
|
||||
does not need to be concerned with the `secret` section of user records, as
|
||||
the fields included therein are only useful when executing authentication
|
||||
operations natively against JSON user records.
|
||||
|
||||
|
@ -24,7 +24,7 @@
|
||||
<title>Introduction</title>
|
||||
|
||||
<para><citerefentry><refentrytitle>systemd-homed.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||
is a system service which may be used to to create, remove, change or inspect home areas. This page
|
||||
is a system service which may be used to create, remove, change or inspect home areas. This page
|
||||
describes the D-Bus interface.
|
||||
</para>
|
||||
</refsect1>
|
||||
@ -227,7 +227,7 @@ node /org/freedesktop/home1 {
|
||||
interface.</para>
|
||||
|
||||
<para><function>CreateHome()</function> registers and creates a new home directory. This takes a fully
|
||||
specified JSON user record as argument (including the <literal>secret</literal> section. This registers
|
||||
specified JSON user record as argument (including the <literal>secret</literal> section). This registers
|
||||
the user record locally and creates a home directory matching it, depending on the settings specified
|
||||
in the record in combination with local configuration.</para>
|
||||
|
||||
|
@ -239,7 +239,7 @@ node /org/freedesktop/hostname1 {
|
||||
|
||||
<para><varname>KernelName</varname>, <varname>KernelRelease</varname>, and
|
||||
<varname>KernelVersion</varname> expose the kernel name (e.g. <literal>Linux</literal>), release
|
||||
(e.g. <literal>5.0.0-11</literal>, and version (i.e. the build number, e.g. <literal>#11</literal>) as
|
||||
(e.g. <literal>5.0.0-11</literal>), and version (i.e. the build number, e.g. <literal>#11</literal>) as
|
||||
reported by
|
||||
<citerefentry project="man-pages"><refentrytitle>uname</refentrytitle><manvolnum>2</manvolnum></citerefentry>.
|
||||
<varname>OperatingSystemPrettyName</varname>, <varname>OperatingSystemCPEName</varname>, and
|
||||
|
@ -1472,12 +1472,12 @@ node /org/freedesktop/systemd1 {
|
||||
<para>Read access is generally granted to all clients. Additionally, for unprivileged clients, some
|
||||
operations are allowed through the polkit privilege system. Operations which modify unit state
|
||||
(<function>StartUnit()</function>, <function>StopUnit()</function>, <function>KillUnit()</function>,
|
||||
<function>RestartUnit()</function> and similar, <function>SetProperty</function>) require
|
||||
<function>RestartUnit()</function> and similar, <function>SetProperty()</function>) require
|
||||
<interfacename>org.freedesktop.systemd1.manage-units</interfacename>. Operations which modify unit file
|
||||
enablement state (<function>EnableUnitFiles()</function>, <function>DisableUnitFiles()</function>,
|
||||
<function>ReenableUnitFiles()</function>, <function>LinkUnitFiles()</function>,
|
||||
<function>PresetUnitFiles</function>, <function>MaskUnitFiles</function>, and similar) require
|
||||
<interfacename>org.freedesktop.systemd1.manage-unit-files</interfacename>). Operations which modify the
|
||||
<interfacename>org.freedesktop.systemd1.manage-unit-files</interfacename>. Operations which modify the
|
||||
exported environment (<function>SetEnvironment()</function>, <function>UnsetEnvironment()</function>,
|
||||
<function>UnsetAndSetEnvironment()</function>) require
|
||||
<interfacename>org.freedesktop.systemd1.set-environment</interfacename>. <function>Reload()</function>
|
||||
|
@ -140,7 +140,7 @@
|
||||
|
||||
<row>
|
||||
<entry><constant>root-secondary</constant></entry>
|
||||
<entry>Root file system partition of the secondary architecture of the local architecture; usually the matching 32bit architecture for the local 64bit architecture)</entry>
|
||||
<entry>Root file system partition of the secondary architecture of the local architecture (usually the matching 32bit architecture for the local 64bit architecture)</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
|
@ -332,7 +332,7 @@
|
||||
information, in particular it should not be used for security-relevant decisions. That's because the
|
||||
executable might have been replaced or removed by the time the value can be processed. Moreover, the
|
||||
kernel exports this information in an ambiguous way (i.e. a deleted executable cannot be safely
|
||||
distinguished from one whose name suffix is <literal> (deleted)</literal>.</para>
|
||||
distinguished from one whose name suffix is <literal> (deleted)</literal>).</para>
|
||||
|
||||
<para><function>sd_bus_creds_get_cmdline()</function> will
|
||||
retrieve an array of command line arguments (as stored in
|
||||
|
@ -79,7 +79,7 @@
|
||||
<constant>POLLIN</constant>, <constant>POLLOUT</constant>, … events, or negative on error.
|
||||
</para>
|
||||
|
||||
<para><function>sd_bus_get_timeout()</function> returns the timeout in µs to pass to to
|
||||
<para><function>sd_bus_get_timeout()</function> returns the timeout in µs to pass to
|
||||
<function>poll()</function> or a similar call when waiting for events on the specified bus
|
||||
connection. The returned timeout may be zero, in which case a subsequent I/O polling call
|
||||
should be invoked in non-blocking mode. The returned timeout may be
|
||||
|
@ -131,7 +131,7 @@
|
||||
automatically as the code block is left:</para>
|
||||
|
||||
<programlisting>{
|
||||
__attribute__((cleanup(sd_event_unrefp)) sd_event *event = NULL;
|
||||
__attribute__((cleanup(sd_event_unrefp))) sd_event *event = NULL;
|
||||
int r;
|
||||
…
|
||||
r = sd_event_default(&event);
|
||||
|
@ -112,7 +112,7 @@
|
||||
code block is left:</para>
|
||||
|
||||
<programlisting>{
|
||||
__attribute__((cleanup(sd_login_monitor_unrefp)) sd_login_monitor *m = NULL;
|
||||
__attribute__((cleanup(sd_login_monitor_unrefp))) sd_login_monitor *m = NULL;
|
||||
int r;
|
||||
…
|
||||
r = sd_login_monitor_default(&m);
|
||||
|
@ -343,7 +343,7 @@
|
||||
boots. <citerefentry><refentrytitle>bootctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>'s
|
||||
<option>set-default</option> and <option>set-oneshot</option> commands make use of these variables. The boot
|
||||
loader modifies <varname>LoaderEntryDefault</varname> on request, when the <keycap>d</keycap> key is used, see
|
||||
above.)</para></listitem>
|
||||
above.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
|
@ -98,6 +98,18 @@
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--image=<replaceable>path</replaceable></option></term>
|
||||
<listitem><para>Takes a path to a disk image file or block device node. If specified all operations
|
||||
are applied to file system in the indicated disk image. This is similar to <option>--root=</option>
|
||||
but operates on file systems stored in disk images or block devices. The disk image should either
|
||||
contain just a file system or a set of file systems within a GPT partition table, following the
|
||||
<ulink url="https://systemd.io/DISCOVERABLE_PARTITIONS">Discoverable Partitions
|
||||
Specification</ulink>. For further information on supported disk images, see
|
||||
<citerefentry><refentrytitle>systemd-nspawn</refentrytitle><manvolnum>1</manvolnum></citerefentry>'s
|
||||
switch of the same name.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--locale=<replaceable>LOCALE</replaceable></option></term>
|
||||
<term><option>--locale-messages=<replaceable>LOCALE</replaceable></option></term>
|
||||
@ -247,6 +259,14 @@
|
||||
option should not be used lightly.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--welcome=</option></term>
|
||||
|
||||
<listitem><para>Takes a boolean argument. By default when prompting the user for configuration
|
||||
options a brief welcome text is shown before the first question is asked. Pass false to this option
|
||||
to turn off the welcome text.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<xi:include href="standard-options.xml" xpointer="help" />
|
||||
<xi:include href="standard-options.xml" xpointer="version" />
|
||||
</variablelist>
|
||||
|
@ -558,7 +558,7 @@
|
||||
With option <option>yes</option> systemd-nspawn waits for the
|
||||
<literal>READY=1</literal> message from the init process in the container
|
||||
before sending its own to systemd. For more details about notifications
|
||||
see <citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>).</para></listitem>
|
||||
see <citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
|
@ -1699,7 +1699,7 @@ RestrictNamespaces=~cgroup net</programlisting>
|
||||
<option>shared</option> mount propagation is used, but — as mentioned — as <option>slave</option> is applied
|
||||
first, propagation from the unit's processes to the host is still turned off.</para>
|
||||
|
||||
<para>It is not recommended to to use <option>private</option> mount propagation for units, as this means
|
||||
<para>It is not recommended to use <option>private</option> mount propagation for units, as this means
|
||||
temporary mounts (such as removable media) of the host will stay mounted and thus indefinitely busy in forked
|
||||
off processes, as unmount propagation events won't be received by the file system namespace of the unit.</para>
|
||||
|
||||
|
@ -204,7 +204,11 @@
|
||||
system that merges multiple mount points). See
|
||||
<varname>After=</varname> and <varname>Requires=</varname> in
|
||||
<citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
||||
for details.</para></listitem>
|
||||
for details.</para>
|
||||
|
||||
<para>Note that this option always applies to the created mount unit
|
||||
only regardless whether <option>x-systemd.automount</option> has been
|
||||
specified.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
@ -223,7 +227,11 @@
|
||||
unit.
|
||||
See <varname>Before=</varname> and <varname>After=</varname> in
|
||||
<citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
||||
for details.</para></listitem>
|
||||
for details.</para>
|
||||
|
||||
<para>Note that these options always apply to the created mount unit
|
||||
only regardless whether <option>x-systemd.automount</option> has been
|
||||
specified.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mount.h>
|
||||
|
||||
#include "fd-util.h"
|
||||
#include "missing_fs.h"
|
||||
@ -169,3 +170,16 @@ int fd_is_network_ns(int fd) {
|
||||
|
||||
return r == CLONE_NEWNET;
|
||||
}
|
||||
|
||||
int detach_mount_namespace(void) {
|
||||
|
||||
/* Detaches the mount namespace, disabling propagation from our namespace to the host */
|
||||
|
||||
if (unshare(CLONE_NEWNS) < 0)
|
||||
return -errno;
|
||||
|
||||
if (mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL) < 0)
|
||||
return -errno;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -7,3 +7,5 @@ int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *
|
||||
int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd);
|
||||
|
||||
int fd_is_network_ns(int fd);
|
||||
|
||||
int detach_mount_namespace(void);
|
||||
|
@ -223,11 +223,9 @@ int machine_id_commit(const char *root) {
|
||||
return log_error_errno(r, "Can't fetch current mount namespace: %m");
|
||||
|
||||
/* Switch to a new mount namespace, isolate ourself and unmount etc_machine_id in our new namespace */
|
||||
if (unshare(CLONE_NEWNS) < 0)
|
||||
return log_error_errno(errno, "Failed to enter new namespace: %m");
|
||||
|
||||
if (mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL) < 0)
|
||||
return log_error_errno(errno, "Couldn't make-rslave / mountpoint in our private namespace: %m");
|
||||
r = detach_mount_namespace();
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to set up new mount namespace: %m");
|
||||
|
||||
if (umount(etc_machine_id) < 0)
|
||||
return log_error_errno(errno, "Failed to unmount transient %s file in our private namespace: %m", etc_machine_id);
|
||||
|
@ -1017,8 +1017,11 @@ static void mount_enter_mounting(Mount *m) {
|
||||
|
||||
/* Create the source directory for bind-mounts if needed */
|
||||
p = get_mount_parameters_fragment(m);
|
||||
if (p && mount_is_bind(p))
|
||||
(void) mkdir_p_label(p->what, m->directory_mode);
|
||||
if (p && mount_is_bind(p)) {
|
||||
r = mkdir_p_label(p->what, m->directory_mode);
|
||||
if (r < 0)
|
||||
log_unit_error_errno(UNIT(m), r, "Failed to make bind mount source '%s': %m", p->what);
|
||||
}
|
||||
|
||||
if (p) {
|
||||
_cleanup_free_ char *opts = NULL;
|
||||
|
@ -1034,7 +1034,7 @@ static int apply_mount(
|
||||
/* Hmm, either the source or the destination are missing. Let's see if we can create the destination, then try again */
|
||||
|
||||
if (stat(what, &st) < 0)
|
||||
log_debug_errno(errno, "Mount point source '%s' is not accessible: %m", what);
|
||||
log_error_errno(errno, "Mount point source '%s' is not accessible: %m", what);
|
||||
else {
|
||||
int q;
|
||||
|
||||
@ -1046,7 +1046,7 @@ static int apply_mount(
|
||||
q = touch(mount_entry_path(m));
|
||||
|
||||
if (q < 0)
|
||||
log_debug_errno(q, "Failed to create destination mount point node '%s': %m", mount_entry_path(m));
|
||||
log_error_errno(q, "Failed to create destination mount point node '%s': %m", mount_entry_path(m));
|
||||
else
|
||||
try_again = true;
|
||||
}
|
||||
@ -1060,7 +1060,7 @@ static int apply_mount(
|
||||
}
|
||||
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to mount %s to %s: %m", what, mount_entry_path(m));
|
||||
return log_error_errno(r, "Failed to mount %s to %s: %m", what, mount_entry_path(m));
|
||||
}
|
||||
|
||||
log_debug("Successfully mounted %s to %s", what, mount_entry_path(m));
|
||||
|
@ -258,7 +258,7 @@ int unit_add_name(Unit *u, const char *text) {
|
||||
t = unit_name_to_type(name);
|
||||
if (t < 0)
|
||||
return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EINVAL),
|
||||
"failed to to derive unit type from name '%s': %m", name);
|
||||
"failed to derive unit type from name '%s': %m", name);
|
||||
|
||||
if (u->type != _UNIT_TYPE_INVALID && t != u->type)
|
||||
return log_unit_debug_errno(u, SYNTHETIC_ERRNO(EINVAL),
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <getopt.h>
|
||||
#include <linux/loop.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "sd-id128.h"
|
||||
@ -9,6 +10,7 @@
|
||||
#include "alloc-util.h"
|
||||
#include "ask-password-api.h"
|
||||
#include "copy.h"
|
||||
#include "dissect-image.h"
|
||||
#include "env-file.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
@ -17,9 +19,12 @@
|
||||
#include "kbd-util.h"
|
||||
#include "libcrypt-util.h"
|
||||
#include "locale-util.h"
|
||||
#include "loop-util.h"
|
||||
#include "main-func.h"
|
||||
#include "memory-util.h"
|
||||
#include "mkdir.h"
|
||||
#include "mount-util.h"
|
||||
#include "namespace-util.h"
|
||||
#include "os-util.h"
|
||||
#include "parse-util.h"
|
||||
#include "path-util.h"
|
||||
@ -31,10 +36,12 @@
|
||||
#include "terminal-util.h"
|
||||
#include "time-util.h"
|
||||
#include "tmpfile-util-label.h"
|
||||
#include "tmpfile-util.h"
|
||||
#include "umask-util.h"
|
||||
#include "user-util.h"
|
||||
|
||||
static char *arg_root = NULL;
|
||||
static char *arg_image = NULL;
|
||||
static char *arg_locale = NULL; /* $LANG */
|
||||
static char *arg_keymap = NULL;
|
||||
static char *arg_locale_messages = NULL; /* $LC_MESSAGES */
|
||||
@ -55,8 +62,10 @@ static bool arg_copy_root_password = false;
|
||||
static bool arg_force = false;
|
||||
static bool arg_delete_root_password = false;
|
||||
static bool arg_root_password_is_hashed = false;
|
||||
static bool arg_welcome = true;
|
||||
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_root, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_image, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_locale, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_locale_messages, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_keymap, freep);
|
||||
@ -85,6 +94,9 @@ static void print_welcome(void) {
|
||||
const char *pn;
|
||||
int r;
|
||||
|
||||
if (!arg_welcome)
|
||||
return;
|
||||
|
||||
if (done)
|
||||
return;
|
||||
|
||||
@ -826,6 +838,75 @@ static int process_kernel_cmdline(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int setup_image(char **ret_mount_dir, LoopDevice **ret_loop_device, DecryptedImage **ret_decrypted_image) {
|
||||
DissectImageFlags f = DISSECT_IMAGE_REQUIRE_ROOT|DISSECT_IMAGE_VALIDATE_OS|DISSECT_IMAGE_RELAX_VAR_CHECK|DISSECT_IMAGE_FSCK;
|
||||
_cleanup_(loop_device_unrefp) LoopDevice *d = NULL;
|
||||
_cleanup_(decrypted_image_unrefp) DecryptedImage *decrypted_image = NULL;
|
||||
_cleanup_(dissected_image_unrefp) DissectedImage *dissected_image = NULL;
|
||||
_cleanup_(rmdir_and_freep) char *mount_dir = NULL;
|
||||
_cleanup_free_ char *temp = NULL;
|
||||
int r;
|
||||
|
||||
if (!arg_image) {
|
||||
*ret_mount_dir = NULL;
|
||||
*ret_decrypted_image = NULL;
|
||||
*ret_loop_device = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(!arg_root);
|
||||
|
||||
r = tempfn_random_child(NULL, "firstboot", &temp);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to generate temporary mount directory: %m");
|
||||
|
||||
r = loop_device_make_by_path(arg_image, O_RDWR, LO_FLAGS_PARTSCAN, &d);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to set up loopback device: %m");
|
||||
|
||||
r = dissect_image_and_warn(d->fd, arg_image, NULL, 0, NULL, f, &dissected_image);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = dissected_image_decrypt_interactively(dissected_image, NULL, NULL, 0, NULL, NULL, NULL, 0, f, &decrypted_image);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = detach_mount_namespace();
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to detach mount namespace: %m");
|
||||
|
||||
mount_dir = strdup(temp);
|
||||
if (!mount_dir)
|
||||
return log_oom();
|
||||
|
||||
r = mkdir_p(mount_dir, 0700);
|
||||
if (r < 0) {
|
||||
mount_dir = mfree(mount_dir);
|
||||
return log_error_errno(r, "Failed to create mount point: %m");
|
||||
}
|
||||
|
||||
r = dissected_image_mount(dissected_image, mount_dir, UID_INVALID, f);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to mount image: %m");
|
||||
|
||||
if (decrypted_image) {
|
||||
r = decrypted_image_relinquish(decrypted_image);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to relinquish DM devices: %m");
|
||||
}
|
||||
|
||||
loop_device_relinquish(d);
|
||||
|
||||
arg_root = TAKE_PTR(temp);
|
||||
|
||||
*ret_mount_dir = TAKE_PTR(mount_dir);
|
||||
*ret_decrypted_image = TAKE_PTR(decrypted_image);
|
||||
*ret_loop_device = TAKE_PTR(d);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int help(void) {
|
||||
_cleanup_free_ char *link = NULL;
|
||||
int r;
|
||||
@ -839,6 +920,7 @@ static int help(void) {
|
||||
" -h --help Show this help\n"
|
||||
" --version Show package version\n"
|
||||
" --root=PATH Operate on an alternate filesystem root\n"
|
||||
" --image=PATH Operate on an alternate filesystem image\n"
|
||||
" --locale=LOCALE Set primary locale (LANG=)\n"
|
||||
" --locale-messages=LOCALE Set message locale (LC_MESSAGES=)\n"
|
||||
" --keymap=KEYMAP Set keymap\n"
|
||||
@ -862,6 +944,7 @@ static int help(void) {
|
||||
" --setup-machine-id Generate a new random machine ID\n"
|
||||
" --force Overwrite existing files\n"
|
||||
" --delete-root-password Delete root password\n"
|
||||
" --welcome=no Disable the welcome text\n"
|
||||
"\nSee the %s for details.\n"
|
||||
, program_invocation_short_name
|
||||
, link
|
||||
@ -875,6 +958,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
enum {
|
||||
ARG_VERSION = 0x100,
|
||||
ARG_ROOT,
|
||||
ARG_IMAGE,
|
||||
ARG_LOCALE,
|
||||
ARG_LOCALE_MESSAGES,
|
||||
ARG_KEYMAP,
|
||||
@ -899,12 +983,14 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
ARG_SETUP_MACHINE_ID,
|
||||
ARG_FORCE,
|
||||
ARG_DELETE_ROOT_PASSWORD,
|
||||
ARG_WELCOME,
|
||||
};
|
||||
|
||||
static const struct option options[] = {
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "version", no_argument, NULL, ARG_VERSION },
|
||||
{ "root", required_argument, NULL, ARG_ROOT },
|
||||
{ "image", required_argument, NULL, ARG_IMAGE },
|
||||
{ "locale", required_argument, NULL, ARG_LOCALE },
|
||||
{ "locale-messages", required_argument, NULL, ARG_LOCALE_MESSAGES },
|
||||
{ "keymap", required_argument, NULL, ARG_KEYMAP },
|
||||
@ -929,6 +1015,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
{ "setup-machine-id", no_argument, NULL, ARG_SETUP_MACHINE_ID },
|
||||
{ "force", no_argument, NULL, ARG_FORCE },
|
||||
{ "delete-root-password", no_argument, NULL, ARG_DELETE_ROOT_PASSWORD },
|
||||
{ "welcome", required_argument, NULL, ARG_WELCOME },
|
||||
{}
|
||||
};
|
||||
|
||||
@ -953,6 +1040,12 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
return r;
|
||||
break;
|
||||
|
||||
case ARG_IMAGE:
|
||||
r = parse_path_argument_and_warn(optarg, false, &arg_image);
|
||||
if (r < 0)
|
||||
return r;
|
||||
break;
|
||||
|
||||
case ARG_LOCALE:
|
||||
r = free_and_strdup(&arg_locale, optarg);
|
||||
if (r < 0)
|
||||
@ -1086,7 +1179,6 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
break;
|
||||
|
||||
case ARG_SETUP_MACHINE_ID:
|
||||
|
||||
r = sd_id128_randomize(&arg_machine_id);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to generate randomized machine ID: %m");
|
||||
@ -1101,6 +1193,14 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
arg_delete_root_password = true;
|
||||
break;
|
||||
|
||||
case ARG_WELCOME:
|
||||
r = parse_boolean(optarg);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse --welcome= argument: %s", optarg);
|
||||
|
||||
arg_welcome = r;
|
||||
break;
|
||||
|
||||
case '?':
|
||||
return -EINVAL;
|
||||
|
||||
@ -1120,11 +1220,16 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"--delete-root-password cannot be combined with other root password options");
|
||||
|
||||
if (arg_image && arg_root)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Please specify either --root= or --image=, the combination of both is not supported.");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int run(int argc, char *argv[]) {
|
||||
bool enabled;
|
||||
_cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL;
|
||||
_cleanup_(decrypted_image_unrefp) DecryptedImage *decrypted_image = NULL;
|
||||
_cleanup_(umount_and_rmdir_and_freep) char *unlink_dir = NULL;
|
||||
int r;
|
||||
|
||||
r = parse_argv(argc, argv);
|
||||
@ -1135,11 +1240,23 @@ static int run(int argc, char *argv[]) {
|
||||
|
||||
umask(0022);
|
||||
|
||||
r = proc_cmdline_get_bool("systemd.firstboot", &enabled);
|
||||
if (!arg_root && !arg_image) {
|
||||
bool enabled;
|
||||
|
||||
/* If we are called without --root=/--image= let's honour the systemd.firstboot kernel
|
||||
* command line option, because we are called to provision the host with basic settings (as
|
||||
* opposed to some other file system tree/image) */
|
||||
|
||||
r = proc_cmdline_get_bool("systemd.firstboot", &enabled);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse systemd.firstboot= kernel command line argument, ignoring: %m");
|
||||
if (r > 0 && !enabled)
|
||||
return 0; /* disabled */
|
||||
}
|
||||
|
||||
r = setup_image(&unlink_dir, &loop_device, &decrypted_image);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse systemd.firstboot= kernel command line argument, ignoring: %m");
|
||||
if (r > 0 && !enabled)
|
||||
return 0; /* disabled */
|
||||
return r;
|
||||
|
||||
r = process_locale();
|
||||
if (r < 0)
|
||||
|
@ -314,6 +314,29 @@ static int write_requires_mounts_for(FILE *f, const char *opts) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int write_extra_dependencies(FILE *f, const char *opts) {
|
||||
int r;
|
||||
|
||||
assert(f);
|
||||
|
||||
if (opts) {
|
||||
r = write_after(f, opts);
|
||||
if (r < 0)
|
||||
return r;
|
||||
r = write_requires_after(f, opts);
|
||||
if (r < 0)
|
||||
return r;
|
||||
r = write_before(f, opts);
|
||||
if (r < 0)
|
||||
return r;
|
||||
r = write_requires_mounts_for(f, opts);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int add_mount(
|
||||
const char *dest,
|
||||
const char *what,
|
||||
@ -406,20 +429,9 @@ static int add_mount(
|
||||
SET_FLAG(flags, NOFAIL, true);
|
||||
}
|
||||
|
||||
if (!(flags & AUTOMOUNT) && opts) {
|
||||
r = write_after(f, opts);
|
||||
if (r < 0)
|
||||
return r;
|
||||
r = write_requires_after(f, opts);
|
||||
if (r < 0)
|
||||
return r;
|
||||
r = write_before(f, opts);
|
||||
if (r < 0)
|
||||
return r;
|
||||
r = write_requires_mounts_for(f, opts);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
r = write_extra_dependencies(f, opts);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (passno != 0) {
|
||||
r = generator_write_fsck_deps(f, dest, what, where, fstype);
|
||||
@ -530,21 +542,6 @@ static int add_mount(
|
||||
"Documentation=man:fstab(5) man:systemd-fstab-generator(8)\n",
|
||||
source);
|
||||
|
||||
if (opts) {
|
||||
r = write_after(f, opts);
|
||||
if (r < 0)
|
||||
return r;
|
||||
r = write_requires_after(f, opts);
|
||||
if (r < 0)
|
||||
return r;
|
||||
r = write_before(f, opts);
|
||||
if (r < 0)
|
||||
return r;
|
||||
r = write_requires_mounts_for(f, opts);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
fprintf(f,
|
||||
"\n"
|
||||
"[Automount]\n"
|
||||
|
@ -852,8 +852,6 @@ int compress_stream_zstd(int fdf, int fdt, uint64_t max_bytes) {
|
||||
size_t in_allocsize, out_allocsize;
|
||||
size_t z;
|
||||
uint64_t left = max_bytes, in_bytes = 0;
|
||||
/* This can be used in the future to add uncompressed size to the header */
|
||||
uint64_t in_totalsize = 0;
|
||||
|
||||
assert(fdf >= 0);
|
||||
assert(fdt >= 0);
|
||||
@ -867,11 +865,6 @@ int compress_stream_zstd(int fdf, int fdt, uint64_t max_bytes) {
|
||||
if (!cctx || !out_buff || !in_buff)
|
||||
return -ENOMEM;
|
||||
|
||||
if (in_totalsize) {
|
||||
z = ZSTD_CCtx_setPledgedSrcSize(cctx, in_totalsize);
|
||||
if (z)
|
||||
log_debug("Failed to enable ZSTD input size, ignoring: %s", ZSTD_getErrorName(z));
|
||||
}
|
||||
z = ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 1);
|
||||
if (ZSTD_isError(z))
|
||||
log_debug("Failed to enable ZSTD checksum, ignoring: %s", ZSTD_getErrorName(z));
|
||||
|
@ -315,7 +315,7 @@ static int server_read_dev_kmsg(Server *s) {
|
||||
if (IN_SET(errno, EAGAIN, EINTR, EPIPE))
|
||||
return 0;
|
||||
|
||||
return log_error_errno(errno, "Failed to read from kernel: %m");
|
||||
return log_error_errno(errno, "Failed to read from /dev/kmsg: %m");
|
||||
}
|
||||
|
||||
dev_kmsg_record(s, buffer, l);
|
||||
|
@ -327,7 +327,7 @@ int config_parse_arp_ip_target_address(
|
||||
r = extract_first_word(&rvalue, &n, NULL, 0);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, r,
|
||||
"Failed to parse Bond ARP ip target address, ignoring assignment: %s",
|
||||
"Failed to parse Bond ARP IP target address, ignoring assignment: %s",
|
||||
rvalue);
|
||||
return 0;
|
||||
}
|
||||
@ -337,7 +337,7 @@ int config_parse_arp_ip_target_address(
|
||||
r = in_addr_from_string(AF_INET, n, &ip);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, r,
|
||||
"Bond ARP ip target address is invalid, ignoring assignment: %s", n);
|
||||
"Bond ARP IP target address is invalid, ignoring assignment: %s", n);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -347,7 +347,7 @@ int config_parse_arp_ip_target_address(
|
||||
|
||||
if (ordered_set_size(b->arp_ip_targets) >= NETDEV_BOND_ARP_TARGETS_MAX) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, 0,
|
||||
"Too many ARP ip targets are specified. The maximum number is %d. Ignoring assignment: %s",
|
||||
"Too many ARP IP targets are specified. The maximum number is %d. Ignoring assignment: %s",
|
||||
NETDEV_BOND_ARP_TARGETS_MAX, n);
|
||||
continue;
|
||||
}
|
||||
@ -355,10 +355,10 @@ int config_parse_arp_ip_target_address(
|
||||
r = ordered_set_put(b->arp_ip_targets, UINT32_TO_PTR(ip.in.s_addr));
|
||||
if (r == -EEXIST)
|
||||
log_syntax(unit, LOG_WARNING, filename, line, r,
|
||||
"Bond ARP ip target address is duplicated, ignoring assignment: %s", n);
|
||||
"Bond ARP IP target address is duplicated, ignoring assignment: %s", n);
|
||||
if (r < 0)
|
||||
log_syntax(unit, LOG_ERR, filename, line, r,
|
||||
"Failed to store bond ARP ip target address '%s', ignoring assignment: %m", n);
|
||||
"Failed to store bond ARP IP target address '%s', ignoring assignment: %m", n);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1025,7 +1025,7 @@ static int dhcp_lease_ip_change(sd_dhcp_client *client, Link *link) {
|
||||
|
||||
link->dhcp_lease_old = TAKE_PTR(link->dhcp_lease);
|
||||
|
||||
/* On ip address change, to keep the connectability, we would like to assign new address and
|
||||
/* On IP address change, to keep the connectability, we would like to assign new address and
|
||||
* routes, and then release old lease. There are two possible success paths:
|
||||
*
|
||||
* 1. new address and routes are configured.
|
||||
@ -1066,12 +1066,12 @@ static int dhcp_server_is_deny_listed(Link *link, sd_dhcp_client *client) {
|
||||
|
||||
r = sd_dhcp_lease_get_server_identifier(lease, &addr);
|
||||
if (r < 0)
|
||||
return log_link_debug_errno(link, r, "Failed to get DHCP server ip address: %m");
|
||||
return log_link_debug_errno(link, r, "Failed to get DHCP server IP address: %m");
|
||||
|
||||
if (set_contains(link->network->dhcp_deny_listed_ip, UINT32_TO_PTR(addr.s_addr))) {
|
||||
log_struct(LOG_DEBUG,
|
||||
LOG_LINK_INTERFACE(link),
|
||||
LOG_LINK_MESSAGE(link, "DHCPv4 ip '%u.%u.%u.%u' found in deny-listed ip addresses, ignoring offer",
|
||||
LOG_LINK_MESSAGE(link, "DHCPv4 IP '%u.%u.%u.%u' found in deny-listed IP addresses, ignoring offer",
|
||||
ADDRESS_FMT_VAL(addr)));
|
||||
return true;
|
||||
}
|
||||
@ -1094,12 +1094,12 @@ static int dhcp_server_is_allow_listed(Link *link, sd_dhcp_client *client) {
|
||||
|
||||
r = sd_dhcp_lease_get_server_identifier(lease, &addr);
|
||||
if (r < 0)
|
||||
return log_link_debug_errno(link, r, "Failed to get DHCP server ip address: %m");
|
||||
return log_link_debug_errno(link, r, "Failed to get DHCP server IP address: %m");
|
||||
|
||||
if (set_contains(link->network->dhcp_allow_listed_ip, UINT32_TO_PTR(addr.s_addr))) {
|
||||
log_struct(LOG_DEBUG,
|
||||
LOG_LINK_INTERFACE(link),
|
||||
LOG_LINK_MESSAGE(link, "DHCPv4 ip '%u.%u.%u.%u' found in allow-listed ip addresses, accepting offer",
|
||||
LOG_LINK_MESSAGE(link, "DHCPv4 IP '%u.%u.%u.%u' found in allow-listed IP addresses, accepting offer",
|
||||
ADDRESS_FMT_VAL(addr)));
|
||||
return true;
|
||||
}
|
||||
@ -1520,7 +1520,7 @@ int dhcp4_configure(Link *link) {
|
||||
if (link->network->ip_service_type > 0) {
|
||||
r = sd_dhcp_client_set_service_type(link->dhcp_client, link->network->ip_service_type);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set ip service type: %m");
|
||||
return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set IP service type: %m");
|
||||
}
|
||||
|
||||
if (link->network->dhcp_fallback_lease_lifetime > 0) {
|
||||
|
@ -506,17 +506,17 @@ int routing_policy_rule_configure(RoutingPolicyRule *rule, Link *link, link_netl
|
||||
if (rule->tos > 0) {
|
||||
r = sd_rtnl_message_routing_policy_rule_set_tos(m, rule->tos);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Could not set ip rule tos: %m");
|
||||
return log_link_error_errno(link, r, "Could not set IP rule TOS: %m");
|
||||
}
|
||||
|
||||
if (rule->table < 256) {
|
||||
r = sd_rtnl_message_routing_policy_rule_set_table(m, rule->table);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Could not set ip rule table: %m");
|
||||
return log_link_error_errno(link, r, "Could not set IP rule table: %m");
|
||||
} else {
|
||||
r = sd_rtnl_message_routing_policy_rule_set_table(m, RT_TABLE_UNSPEC);
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Could not set ip rule table: %m");
|
||||
return log_link_error_errno(link, r, "Could not set IP rule table: %m");
|
||||
|
||||
r = sd_netlink_message_append_u32(m, FRA_TABLE, rule->table);
|
||||
if (r < 0)
|
||||
@ -698,7 +698,7 @@ int config_parse_routing_policy_rule_tos(
|
||||
|
||||
r = safe_atou8(rvalue, &n->tos);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse RPDB rule tos, ignoring: %s", rvalue);
|
||||
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse RPDB rule TOS, ignoring: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1372,7 +1372,7 @@ int routing_policy_load_rules(const char *state_file, Set **rules) {
|
||||
} else if (streq(a, "tos")) {
|
||||
r = safe_atou8(b, &rule->tos);
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Failed to parse RPDB rule tos, ignoring: %s", b);
|
||||
log_error_errno(r, "Failed to parse RPDB rule TOS, ignoring: %s", b);
|
||||
continue;
|
||||
}
|
||||
} else if (streq(a, "table")) {
|
||||
|
@ -204,7 +204,7 @@ static int unit_file_find_dirs(
|
||||
type = unit_name_to_type(name);
|
||||
if (type < 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Failed to to derive unit type from unit name: %s",
|
||||
"Failed to derive unit type from unit name: %s",
|
||||
name);
|
||||
|
||||
if (is_instance) {
|
||||
@ -254,7 +254,7 @@ int unit_file_find_dropin_paths(
|
||||
type = unit_name_to_type(n);
|
||||
if (type < 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Failed to to derive unit type from unit name: %s", n);
|
||||
"Failed to derive unit type from unit name: %s", n);
|
||||
|
||||
/* Special top level drop in for "<unit type>.<suffix>". Add this last as it's the most generic
|
||||
* and should be able to be overridden by more specific drop-ins. */
|
||||
|
@ -1435,7 +1435,7 @@ enum nl80211_commands {
|
||||
* rates as defined by IEEE 802.11 7.3.2.2 but without the length
|
||||
* restriction (at most %NL80211_MAX_SUPP_RATES).
|
||||
* @NL80211_ATTR_STA_VLAN: interface index of VLAN interface to move station
|
||||
* to, or the AP interface the station was originally added to to.
|
||||
* to, or the AP interface the station was originally added to.
|
||||
* @NL80211_ATTR_STA_INFO: information about a station, part of station info
|
||||
* given for %NL80211_CMD_GET_STATION, nested attribute containing
|
||||
* info as possible, see &enum nl80211_sta_info.
|
||||
|
@ -58,8 +58,8 @@ int umount_recursive(const char *prefix, int flags) {
|
||||
if (!path_startswith(path, prefix))
|
||||
continue;
|
||||
|
||||
if (umount2(path, flags) < 0) {
|
||||
r = log_debug_errno(errno, "Failed to umount %s: %m", path);
|
||||
if (umount2(path, flags | UMOUNT_NOFOLLOW) < 0) {
|
||||
log_debug_errno(errno, "Failed to umount %s, ignoring: %m", path);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -70,7 +70,6 @@ int umount_recursive(const char *prefix, int flags) {
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
} while (again);
|
||||
|
||||
return n;
|
||||
|
@ -3,7 +3,9 @@
|
||||
|
||||
#include <mntent.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "errno-util.h"
|
||||
#include "macro.h"
|
||||
|
||||
/* 4MB for contents of regular files, 64k inodes for directories, symbolic links and device specials,
|
||||
@ -53,3 +55,12 @@ int mount_option_mangle(
|
||||
char **ret_remaining_options);
|
||||
|
||||
int mode_to_inaccessible_node(const char *runtime_dir, mode_t mode, char **dest);
|
||||
|
||||
/* Useful for usage with _cleanup_(), unmounts, removes a directory and frees the pointer */
|
||||
static inline void umount_and_rmdir_and_free(char *p) {
|
||||
PROTECT_ERRNO;
|
||||
(void) umount_recursive(p, 0);
|
||||
(void) rmdir(p);
|
||||
free(p);
|
||||
}
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(char*, umount_and_rmdir_and_free);
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "env-util.h"
|
||||
#include "fs-util.h"
|
||||
#include "log.h"
|
||||
#include "namespace-util.h"
|
||||
#include "path-util.h"
|
||||
#include "random-util.h"
|
||||
#include "strv.h"
|
||||
@ -137,10 +138,7 @@ bool have_namespaces(void) {
|
||||
|
||||
if (pid == 0) {
|
||||
/* child */
|
||||
if (unshare(CLONE_NEWNS) < 0)
|
||||
_exit(EXIT_FAILURE);
|
||||
|
||||
if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL) < 0)
|
||||
if (detach_mount_namespace() < 0)
|
||||
_exit(EXIT_FAILURE);
|
||||
|
||||
_exit(EXIT_SUCCESS);
|
||||
|
@ -71,7 +71,7 @@ static int write_hibernate_location_info(const HibernateLocation *hibernate_loca
|
||||
return 0;
|
||||
}
|
||||
|
||||
return log_debug_errno(errno, "/sys/power/resume_offset not writeable: %m");
|
||||
return log_debug_errno(errno, "/sys/power/resume_offset not writable: %m");
|
||||
}
|
||||
|
||||
xsprintf(offset_str, "%" PRIu64, hibernate_location->offset);
|
||||
|
@ -636,7 +636,7 @@ static void test_setpriority_closest(void) {
|
||||
q = getpriority(PRIO_PROCESS, 0);
|
||||
assert_se(errno == 0 && p == q);
|
||||
|
||||
/* It should also be possible to to set the nice level to one higher */
|
||||
/* It should also be possible to set the nice level to one higher */
|
||||
if (p < PRIO_MAX-1) {
|
||||
assert_se(setpriority_closest(++p) > 0);
|
||||
|
||||
@ -645,7 +645,7 @@ static void test_setpriority_closest(void) {
|
||||
assert_se(errno == 0 && p == q);
|
||||
}
|
||||
|
||||
/* It should also be possible to to set the nice level to two higher */
|
||||
/* It should also be possible to set the nice level to two higher */
|
||||
if (p < PRIO_MAX-1) {
|
||||
assert_se(setpriority_closest(++p) > 0);
|
||||
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "log.h"
|
||||
#include "main-func.h"
|
||||
#include "mkdir.h"
|
||||
#include "namespace-util.h"
|
||||
#include "selinux-util.h"
|
||||
#include "signal-util.h"
|
||||
#include "string-util.h"
|
||||
@ -36,15 +37,13 @@ static int fake_filesystems(void) {
|
||||
{ "test/run", "/etc/udev/rules.d", "Failed to mount empty /etc/udev/rules.d", true },
|
||||
{ "test/run", UDEVLIBEXECDIR "/rules.d", "Failed to mount empty " UDEVLIBEXECDIR "/rules.d", true },
|
||||
};
|
||||
unsigned i;
|
||||
int r;
|
||||
|
||||
if (unshare(CLONE_NEWNS) < 0)
|
||||
return log_error_errno(errno, "Failed to call unshare(): %m");
|
||||
r = detach_mount_namespace();
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to detach mount namespace: %m");
|
||||
|
||||
if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL) < 0)
|
||||
return log_error_errno(errno, "Failed to mount / as private: %m");
|
||||
|
||||
for (i = 0; i < ELEMENTSOF(fakefss); i++)
|
||||
for (size_t i = 0; i < ELEMENTSOF(fakefss); i++)
|
||||
if (mount(fakefss[i].src, fakefss[i].target, NULL, MS_BIND, NULL) < 0) {
|
||||
log_full_errno(fakefss[i].ignore_mount_error ? LOG_DEBUG : LOG_ERR, errno, "%s: %m", fakefss[i].error);
|
||||
if (!fakefss[i].ignore_mount_error)
|
||||
|
@ -67,7 +67,7 @@ static void test_xdg_desktop_parse(unsigned i, const char *s) {
|
||||
case 0:
|
||||
assert_se(streq(service->exec_string, "/bin/sleep 100"));
|
||||
assert_se(strv_equal(service->only_show_in, STRV_MAKE("A", "B")));
|
||||
assert_se(strv_equal(service->not_show_in, STRV_MAKE("C", "", "D\\;", "E")));
|
||||
assert_se(strv_equal(service->not_show_in, STRV_MAKE("C", "D\\;", "E")));
|
||||
assert_se(!service->hidden);
|
||||
break;
|
||||
case 1:
|
||||
@ -81,14 +81,12 @@ static void test_xdg_desktop_parse(unsigned i, const char *s) {
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
size_t i;
|
||||
|
||||
test_setup_logging(LOG_DEBUG);
|
||||
|
||||
test_translate_name();
|
||||
test_xdg_format_exec_start();
|
||||
|
||||
for (i = 0; i < ELEMENTSOF(xdg_desktop_file); i++)
|
||||
for (size_t i = 0; i < ELEMENTSOF(xdg_desktop_file); i++)
|
||||
test_xdg_desktop_parse(i, xdg_desktop_file[i]);
|
||||
|
||||
return 0;
|
||||
|
@ -182,6 +182,40 @@ static int xdg_config_parse_string(
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int strv_strndup_unescape_and_push(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
char ***sv,
|
||||
size_t *n_allocated,
|
||||
size_t *n,
|
||||
const char *start,
|
||||
const char *end) {
|
||||
|
||||
if (end == start)
|
||||
return 0;
|
||||
|
||||
_cleanup_free_ char *copy = NULL;
|
||||
int r;
|
||||
|
||||
copy = strndup(start, end - start);
|
||||
if (!copy)
|
||||
return log_oom();
|
||||
|
||||
r = xdg_unescape_string(unit, filename, line, copy);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!greedy_realloc((void**) sv, n_allocated, *n + 2, sizeof(char*))) /* One extra for NULL */
|
||||
return log_oom();
|
||||
|
||||
(*sv)[*n] = TAKE_PTR(copy);
|
||||
(*sv)[*n + 1] = NULL;
|
||||
(*n)++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xdg_config_parse_strv(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
@ -194,9 +228,7 @@ static int xdg_config_parse_strv(
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
char ***sv = data;
|
||||
const char *start;
|
||||
const char *end;
|
||||
char ***ret_sv = data;
|
||||
int r;
|
||||
|
||||
assert(filename);
|
||||
@ -205,23 +237,25 @@ static int xdg_config_parse_strv(
|
||||
assert(data);
|
||||
|
||||
/* XDG does not allow duplicate definitions. */
|
||||
if (*sv) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, 0, "Key %s was defined multiple times, ignoring.", lvalue);
|
||||
if (*ret_sv) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, 0, "Key %s was already defined, ignoring.", lvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*sv = strv_new(NULL);
|
||||
if (!*sv)
|
||||
size_t n = 0, n_allocated = 0;
|
||||
_cleanup_strv_free_ char **sv = NULL;
|
||||
|
||||
if (!GREEDY_REALLOC0(sv, n_allocated, 1))
|
||||
return log_oom();
|
||||
|
||||
/* We cannot use strv_split because it does not handle escaping correctly. */
|
||||
start = rvalue;
|
||||
const char *start = rvalue, *end;
|
||||
|
||||
for (end = start; *end; end++) {
|
||||
if (*end == '\\') {
|
||||
/* Move forward, and ensure it is a valid escape. */
|
||||
end++;
|
||||
if (strchr("sntr\\;", *end) == NULL) {
|
||||
if (!strchr("sntr\\;", *end)) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, 0, "Undefined escape sequence \\%c.", *end);
|
||||
return 0;
|
||||
}
|
||||
@ -229,29 +263,24 @@ static int xdg_config_parse_strv(
|
||||
}
|
||||
|
||||
if (*end == ';') {
|
||||
_cleanup_free_ char *copy = NULL;
|
||||
|
||||
copy = strndup(start, end - start);
|
||||
if (!copy)
|
||||
return log_oom();
|
||||
r = xdg_unescape_string(unit, filename, line, copy);
|
||||
r = strv_strndup_unescape_and_push(unit, filename, line,
|
||||
&sv, &n_allocated, &n,
|
||||
start, end);
|
||||
if (r < 0)
|
||||
return r;
|
||||
r = strv_consume(sv, TAKE_PTR(copy));
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
start = end + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Any trailing entry should be ignored if it is empty. */
|
||||
if (end > start) {
|
||||
r = strv_extend(sv, start);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
}
|
||||
/* Handle the trailing entry after the last separator */
|
||||
r = strv_strndup_unescape_and_push(unit, filename, line,
|
||||
&sv, &n_allocated, &n,
|
||||
start, end);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*ret_sv = TAKE_PTR(sv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
BIN
test/fuzz/fuzz-network-parser/oss-fuzz-23950
Normal file
BIN
test/fuzz/fuzz-network-parser/oss-fuzz-23950
Normal file
Binary file not shown.
BIN
test/fuzz/fuzz-xdg-desktop/oss-fuzz-22812
Normal file
BIN
test/fuzz/fuzz-xdg-desktop/oss-fuzz-22812
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user