Compare commits

..

24 Commits

Author SHA1 Message Date
Lennart Poettering 49d5aae503
Merge pull request #15934 from keszybz/docs-and-test-fix
A few sundry documentation and code fixes
2020-05-27 15:16:24 +02:00
Lennart Poettering 6d02412d51
Merge pull request #15928 from poettering/kill-mode-warnings
warn on KillMode=none, inform about left-over processes on stop and warn about sysv services
2020-05-27 15:05:41 +02:00
Chris Kerr 8aa36b1ddd man: Fix typo in suggested permissions
The user and group name is 'systemd-network' not 'systemd-networkd'
2020-05-27 15:03:25 +02:00
Lennart Poettering 2b5f708985 run: when waiting for unit, also check if no job is pending anymore
This is a fix-up for a7c71d214c37797d82de2f66cfe0a0a79c3a5c92: since we
now don't wait for the job to finish anymore right after enqueuing it,
we should not exit our ptyfwd logic before the unit is back to inactive
*and* no job pending anymore.
2020-05-27 15:01:07 +02:00
Lennart Poettering 518a9bd689
Merge pull request #15853 from poettering/tmp-argument
support the Debian-style tmp= argument in crypttab
2020-05-27 14:51:50 +02:00
Frantisek Sumsal ffbb0fb9cb meson: support building fuzzers with meson <0.48.0 2020-05-27 12:27:45 +02:00
Chris Down 4793c31083 service: Display updated WatchdogUSec from sd_notify
Suppose a service has WatchdogSec set to 2 seconds in its unit file. I
then start the service and WatchdogUSec is set correctly:

    % systemctl --user show psi-notify -p WatchdogUSec
    WatchdogUSec=2s

Now I call `sd_notify(0, "WATCHDOG_USEC=10000000")`. The new timer seems
to have taken effect, since I only send `WATCHDOG=1` every 4 seconds,
and systemd isn't triggering the watchdog handler. However, `systemctl
show` still shows WatchdogUSec as 2s:

    % systemctl --user show psi-notify -p WatchdogUSec
    WatchdogUSec=2s

This seems surprising, since this "original" watchdog timer isn't the
one taking effect any more. This patch makes it so that we instead
display the new watchdog timer after sd_notify(WATCHDOG_USEC):

    % systemctl --user show psi-notify -p WatchdogUSec
    WatchdogUSec=10s

Fixes #15726.
2020-05-27 09:09:40 +02:00
Zbigniew Jędrzejewski-Szmek dde5c821bf shared/efi-loader: remove check that uses absolute tick value
sd-boot uses rdtsc to set those timestamps. There is no guarantee that the tsc
has any particular absolute value.

On my VM:
$ head /sys/firmware/efi/efivars/LoaderTime*
==> /sys/firmware/efi/efivars/LoaderTimeExecUSec-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f <==
4397904074
==> /sys/firmware/efi/efivars/LoaderTimeInitUSec-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f <==
4396386839
==> /sys/firmware/efi/efivars/LoaderTimeMenuUSec-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f <==
4396392521

$ build/test-boot-timestamps
...
LoaderTimeExecUSec=4396386839 too large, refusing.
Failed to read EFI loader data: Input/output error
Assertion 'q >= 0' failed at src/test/test-boot-timestamps.c:84, function main(). Aborting.

(with patch)
$ build/test-boot-timestamps
...
EFI Loader: start=1h 13min 16.386s exit=1h 13min 17.904s duration=1.517s
Firmware began 1h 13min 17.904074s before kernel.
Loader began 1.517235s before kernel.
Firmware began Tue 2020-05-26 11:04:13 CEST.
Loader began Tue 2020-05-26 12:17:30 CEST.
Kernel began Tue 2020-05-26 12:17:31 CEST.
2020-05-27 09:02:53 +02:00
Zbigniew Jędrzejewski-Szmek 24b4597064 core: minor simplification 2020-05-27 09:02:53 +02:00
Zbigniew Jędrzejewski-Szmek 40fd0a77c6 userwork: remove trailing comma in message 2020-05-27 09:02:53 +02:00
Zbigniew Jędrzejewski-Szmek 1414090854 core: add forgotten return in error path
If we get an error here, this is most likely oom, and we should not continue.
2020-05-27 09:02:53 +02:00
Zbigniew Jędrzejewski-Szmek 3035a7c577 core: update comment about sysv compat
We don't want people to consider that part deprecated.

Follow-up for 6589a56972.
2020-05-27 09:02:09 +02:00
Frantisek Sumsal 2991fa41e4 test: create public images by default
Let's create new images public by default and then symlink/copy them
into the respective private directories afterwards, not the other way
around. This should fix a nasty race condition in parallel runs where
one tests attempts to copy the backing public image at the same moment
another test is already modifying it.
2020-05-27 08:41:02 +02:00
Lennart Poettering effefa30de update TODO 2020-05-26 23:52:34 +02:00
Lennart Poettering 0e42cbe254 sysv: generate warning for every SysV service lacking a native systemd unit
It's 2020, let's tighten the screws a bit and start warning about
left-over SysV services that still have no native systemd unit file.
2020-05-26 23:52:30 +02:00
Lennart Poettering 470ab28d07 sysv: use structured initialization 2020-05-26 23:52:26 +02:00
Lennart Poettering c8aa4b5b86 core: voidify one function return 2020-05-26 23:52:22 +02:00
Lennart Poettering b0cea477d4 core: some more structured initialization 2020-05-26 23:52:18 +02:00
Lennart Poettering 4c42543429 core: also log about left-over processes during unit stop
Only log at LOG_INFO level, i.e. make this informational. During start
let's leave it at LOG_WARNING though.

Of course, it's ugly leaving processes around like that either in start
or in stop, but at start its more dangerous than on stop, so be tougher
there.
2020-05-26 23:52:13 +02:00
Lennart Poettering 021acbc188 units: remove KillMode=process in our regular gettys
In our regular gettys the actual shell commands live the the session
scope anyway (as long as logind is used). Hence, let's avoid
KillMode=process, it serves no purpose and is simply unsafe since it
disables systemd's own process lifecycle management.
2020-05-26 23:52:09 +02:00
Lennart Poettering 9b52e0d81a man: document that KillMode=none is a bad idea 2020-05-26 23:51:51 +02:00
Lennart Poettering d068765b68 core: warn if KillMode=none is used 2020-05-26 23:50:54 +02:00
Lennart Poettering 53ac130b51 cryptsetup: support tmp= file system argument
Let's catch up with Debian a bit more.

This also changes the default from ext2 to ext4.

Fixes: #952
2020-05-26 17:11:34 +02:00
Lennart Poettering 92a08691c2 fstab-util: prefix return parameters with ret_ 2020-05-26 17:10:54 +02:00
28 changed files with 253 additions and 137 deletions

2
TODO
View File

@ -19,6 +19,8 @@ Janitorial Clean-ups:
Features:
* if /usr/bin/swapoff fails due to OOM, log a friendly explanatory message about it
* build short web pages out of each catalog entry, build them along with man
pages, and include hyperlinks to them in the journal output

View File

@ -393,18 +393,17 @@
</varlistentry>
<varlistentry>
<term><option>tmp</option></term>
<term><option>tmp=</option></term>
<listitem><para>The encrypted block device will be prepared
for using it as <filename>/tmp</filename>; it will be
formatted using
<citerefentry project='man-pages'><refentrytitle>mke2fs</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
This option implies <option>plain</option>.</para>
<listitem><para>The encrypted block device will be prepared for using it as
<filename>/tmp/</filename>; it will be formatted using <citerefentry
project='man-pages'><refentrytitle>mkfs</refentrytitle><manvolnum>8</manvolnum></citerefentry>. Takes
a file system type as argument, such as <literal>ext4</literal>, <literal>xfs</literal> or
<literal>btrfs</literal>. If no argument is specified defaults to <literal>ext4</literal>. This
option implies <option>plain</option>.</para>
<para>WARNING: Using the <option>tmp</option> option will
destroy the contents of the named partition during every boot,
so make sure the underlying block device is specified
correctly.</para></listitem>
<para>WARNING: Using the <option>tmp</option> option will destroy the contents of the named partition
during every boot, so make sure the underlying block device is specified correctly.</para></listitem>
</varlistentry>
<varlistentry>

View File

@ -61,28 +61,25 @@
<varlistentry>
<term><varname>KillMode=</varname></term>
<listitem><para>Specifies how processes of this unit shall be
killed. One of
<option>control-group</option>,
<option>process</option>,
<option>mixed</option>,
<listitem><para>Specifies how processes of this unit shall be killed. One of
<option>control-group</option>, <option>mixed</option>, <option>process</option>,
<option>none</option>.</para>
<para>If set to <option>control-group</option>, all remaining
processes in the control group of this unit will be killed on
unit stop (for services: after the stop command is executed,
as configured with <varname>ExecStop=</varname>). If set to
<option>process</option>, only the main process itself is
killed. If set to <option>mixed</option>, the
<constant>SIGTERM</constant> signal (see below) is sent to the
main process while the subsequent <constant>SIGKILL</constant>
signal (see below) is sent to all remaining processes of the
unit's control group. If set to <option>none</option>, no
process is killed. In this case, only the stop command will be
executed on unit stop, but no process will be killed otherwise.
Processes remaining alive after stop are left in their control
group and the control group continues to exist after stop
unless it is empty.</para>
<para>If set to <option>control-group</option>, all remaining processes in the control group of this
unit will be killed on unit stop (for services: after the stop command is executed, as configured
with <varname>ExecStop=</varname>). If set to <option>mixed</option>, the
<constant>SIGTERM</constant> signal (see below) is sent to the main process while the subsequent
<constant>SIGKILL</constant> signal (see below) is sent to all remaining processes of the unit's
control group. If set to <option>process</option>, only the main process itself is killed (not
recommended!). If set to <option>none</option>, no process is killed (strongly recommended
against!). In this case, only the stop command will be executed on unit stop, but no process will be
killed otherwise. Processes remaining alive after stop are left in their control group and the
control group continues to exist after stop unless empty.</para>
<para>Note that it is not recommended to set <varname>KillMode=</varname> to
<constant>process</constant> or even <constant>none</constant>, as this allows processes to escape
the service manager's lifecycle and resource management, and to remain running even while their
service is considered stopped and is assumed to not consume any resources.</para>
<para>Processes will first be terminated via <constant>SIGTERM</constant> (unless the signal to send
is changed via <varname>KillSignal=</varname> or <varname>RestartKillSignal=</varname>). Optionally,

View File

@ -1550,7 +1550,7 @@
already existing public-key cryptography, for post-quantum
resistance.
Note that because this information is secret, you may want to set
the permissions of the .netdev file to be owned by <literal>root:systemd-networkd</literal>
the permissions of the .netdev file to be owned by <literal>root:systemd-network</literal>
with a <literal>0640</literal> file mode.</para>
</listitem>
</varlistentry>

View File

@ -28,6 +28,7 @@ static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_restart, service_restart, Servi
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_notify_access, notify_access, NotifyAccess);
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_emergency_action, emergency_action, EmergencyAction);
static BUS_DEFINE_PROPERTY_GET(property_get_timeout_abort_usec, "t", Service, service_timeout_abort_usec);
static BUS_DEFINE_PROPERTY_GET(property_get_watchdog_usec, "t", Service, service_get_watchdog_usec);
static int property_get_exit_status_set(
sd_bus *bus,
@ -101,7 +102,7 @@ const sd_bus_vtable bus_service_vtable[] = {
SD_BUS_PROPERTY("TimeoutStopUSec", "t", bus_property_get_usec, offsetof(Service, timeout_stop_usec), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("TimeoutAbortUSec", "t", property_get_timeout_abort_usec, 0, 0),
SD_BUS_PROPERTY("RuntimeMaxUSec", "t", bus_property_get_usec, offsetof(Service, runtime_max_usec), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("WatchdogUSec", "t", bus_property_get_usec, offsetof(Service, watchdog_usec), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("WatchdogUSec", "t", property_get_watchdog_usec, 0, 0),
BUS_PROPERTY_DUAL_TIMESTAMP("WatchdogTimestamp", offsetof(Service, watchdog_timestamp), 0),
SD_BUS_PROPERTY("PermissionsStartOnly", "b", bus_property_get_bool, offsetof(Service, permissions_start_only), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN), /* 😷 deprecated */
SD_BUS_PROPERTY("RootDirectoryStartOnly", "b", bus_property_get_bool, offsetof(Service, root_directory_start_only), SD_BUS_VTABLE_PROPERTY_CONST),

View File

@ -117,7 +117,6 @@ DEFINE_CONFIG_PARSE_ENUM(config_parse_device_policy, cgroup_device_policy, CGrou
DEFINE_CONFIG_PARSE_ENUM(config_parse_exec_keyring_mode, exec_keyring_mode, ExecKeyringMode, "Failed to parse keyring mode");
DEFINE_CONFIG_PARSE_ENUM(config_parse_exec_utmp_mode, exec_utmp_mode, ExecUtmpMode, "Failed to parse utmp mode");
DEFINE_CONFIG_PARSE_ENUM(config_parse_job_mode, job_mode, JobMode, "Failed to parse job mode");
DEFINE_CONFIG_PARSE_ENUM(config_parse_kill_mode, kill_mode, KillMode, "Failed to parse kill mode");
DEFINE_CONFIG_PARSE_ENUM(config_parse_notify_access, notify_access, NotifyAccess, "Failed to parse notify access specifier");
DEFINE_CONFIG_PARSE_ENUM(config_parse_protect_home, protect_home, ProtectHome, "Failed to parse protect home value");
DEFINE_CONFIG_PARSE_ENUM(config_parse_protect_system, protect_system, ProtectSystem, "Failed to parse protect system value");
@ -631,6 +630,48 @@ int config_parse_exec_coredump_filter(
return 0;
}
int config_parse_kill_mode(
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) {
KillMode *k = data, m;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
if (isempty(rvalue)) {
*k = KILL_CONTROL_GROUP;
return 0;
}
m = kill_mode_from_string(rvalue);
if (m < 0) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Failed to parse kill mode specification, ignoring: %s", rvalue);
return 0;
}
if (m == KILL_NONE)
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Unit configured to use KillMode=none. "
"This is unsafe, as it disables systemd's process life-cycle management for the service. "
"Please update your service to use a safer KillMode=, such as 'mixed' or 'control-group'. "
"Support for KillMode=none is deprecated and will eventually be removed.");
*k = m;
return 0;
}
int config_parse_exec(
const char *unit,
const char *filename,
@ -4782,7 +4823,7 @@ int unit_load_fragment(Unit *u) {
&u->manager->unit_name_map,
&u->manager->unit_path_cache);
if (r < 0)
log_error_errno(r, "Failed to rebuild name map: %m");
return log_error_errno(r, "Failed to rebuild name map: %m");
r = unit_file_find_fragment(u->manager->unit_id_map,
u->manager->unit_name_map,

View File

@ -517,7 +517,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
} else if (!value) {
const char *target;
/* SysV compatibility */
/* Compatible with SysV, but supported independently even if SysV compatiblity is disabled. */
target = runlevel_to_target(key);
if (target)
return free_and_strdup_warn(&arg_default_unit, target);

View File

@ -679,18 +679,12 @@ static int manager_setup_prefix(Manager *m) {
[EXEC_DIRECTORY_CONFIGURATION] = { SD_PATH_USER_CONFIGURATION, NULL },
};
const struct table_entry *p;
ExecDirectoryType i;
int r;
assert(m);
if (MANAGER_IS_SYSTEM(m))
p = paths_system;
else
p = paths_user;
const struct table_entry *p = MANAGER_IS_SYSTEM(m) ? paths_system : paths_user;
int r;
for (i = 0; i < _EXEC_DIRECTORY_TYPE_MAX; i++) {
for (ExecDirectoryType i = 0; i < _EXEC_DIRECTORY_TYPE_MAX; i++) {
r = sd_path_lookup(p[i].type, p[i].suffix, &m->prefix[i]);
if (r < 0)
return r;
@ -1344,15 +1338,12 @@ static void manager_clear_jobs_and_units(Manager *m) {
}
Manager* manager_free(Manager *m) {
ExecDirectoryType dt;
UnitType c;
if (!m)
return NULL;
manager_clear_jobs_and_units(m);
for (c = 0; c < _UNIT_TYPE_MAX; c++)
for (UnitType c = 0; c < _UNIT_TYPE_MAX; c++)
if (unit_vtable[c]->shutdown)
unit_vtable[c]->shutdown(m);
@ -1423,22 +1414,20 @@ Manager* manager_free(Manager *m) {
hashmap_free(m->uid_refs);
hashmap_free(m->gid_refs);
for (dt = 0; dt < _EXEC_DIRECTORY_TYPE_MAX; dt++)
for (ExecDirectoryType dt = 0; dt < _EXEC_DIRECTORY_TYPE_MAX; dt++)
m->prefix[dt] = mfree(m->prefix[dt]);
return mfree(m);
}
static void manager_enumerate_perpetual(Manager *m) {
UnitType c;
assert(m);
if (m->test_run_flags == MANAGER_TEST_RUN_MINIMAL)
return;
/* Let's ask every type to load all units from disk/kernel that it might know */
for (c = 0; c < _UNIT_TYPE_MAX; c++) {
for (UnitType c = 0; c < _UNIT_TYPE_MAX; c++) {
if (!unit_type_supported(c)) {
log_debug("Unit type .%s is not supported on this system.", unit_type_to_string(c));
continue;
@ -1450,15 +1439,13 @@ static void manager_enumerate_perpetual(Manager *m) {
}
static void manager_enumerate(Manager *m) {
UnitType c;
assert(m);
if (m->test_run_flags == MANAGER_TEST_RUN_MINIMAL)
return;
/* Let's ask every type to load all units from disk/kernel that it might know */
for (c = 0; c < _UNIT_TYPE_MAX; c++) {
for (UnitType c = 0; c < _UNIT_TYPE_MAX; c++) {
if (!unit_type_supported(c)) {
log_debug("Unit type .%s is not supported on this system.", unit_type_to_string(c));
continue;

View File

@ -863,6 +863,8 @@ static void mount_enter_dead(Mount *m, MountResult f) {
m->result = f;
unit_log_result(UNIT(m), m->result == MOUNT_SUCCESS, mount_result_to_string(m->result));
unit_warn_leftover_processes(UNIT(m), unit_log_leftover_process_stop);
mount_set_state(m, m->result != MOUNT_SUCCESS ? MOUNT_FAILED : MOUNT_DEAD);
m->exec_runtime = exec_runtime_unref(m->exec_runtime, true);
@ -1008,7 +1010,7 @@ static void mount_enter_mounting(Mount *m) {
(void) mkdir_p_label(m->where, m->directory_mode);
unit_warn_if_dir_nonempty(UNIT(m), m->where);
unit_warn_leftover_processes(UNIT(m));
unit_warn_leftover_processes(UNIT(m), unit_log_leftover_process_start);
m->control_command_id = MOUNT_EXEC_MOUNT;
m->control_command = m->exec_command + MOUNT_EXEC_MOUNT;

View File

@ -198,15 +198,6 @@ static void service_stop_watchdog(Service *s) {
s->watchdog_timestamp = DUAL_TIMESTAMP_NULL;
}
static usec_t service_get_watchdog_usec(Service *s) {
assert(s);
if (s->watchdog_override_enable)
return s->watchdog_override_usec;
return s->watchdog_original_usec;
}
static void service_start_watchdog(Service *s) {
usec_t watchdog_usec;
int r;
@ -447,14 +438,17 @@ static int service_add_fd_store(Service *s, int fd, const char *name, bool do_po
}
}
fs = new0(ServiceFDStore, 1);
fs = new(ServiceFDStore, 1);
if (!fs)
return -ENOMEM;
fs->fd = fd;
fs->service = s;
fs->do_poll = do_poll;
fs->fdname = strdup(name ?: "stored");
*fs = (ServiceFDStore) {
.fd = fd,
.service = s,
.do_poll = do_poll,
.fdname = strdup(name ?: "stored"),
};
if (!fs->fdname) {
free(fs);
return -ENOMEM;
@ -1755,6 +1749,7 @@ static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart)
unit_log_failure(UNIT(s), service_result_to_string(s->result));
end_state = SERVICE_FAILED;
}
unit_warn_leftover_processes(UNIT(s), unit_log_leftover_process_stop);
if (!allow_restart)
log_unit_debug(UNIT(s), "Service restart not allowed.");
@ -2081,15 +2076,16 @@ static int service_adverse_to_leftover_processes(Service *s) {
assert(s);
/* KillMode=mixed and control group are used to indicate that all process should be killed off.
* SendSIGKILL is used for services that require a clean shutdown. These are typically database
* service where a SigKilled process would result in a lengthy recovery and who's shutdown or
* startup time is quite variable (so Timeout settings aren't of use).
* SendSIGKILL= is used for services that require a clean shutdown. These are typically database
* service where a SigKilled process would result in a lengthy recovery and who's shutdown or startup
* time is quite variable (so Timeout settings aren't of use).
*
* Here we take these two factors and refuse to start a service if there are existing processes
* within a control group. Databases, while generally having some protection against multiple
* instances running, lets not stress the rigor of these. Also ExecStartPre parts of the service
* instances running, lets not stress the rigor of these. Also ExecStartPre= parts of the service
* aren't as rigoriously written to protect aganst against multiple use. */
if (unit_warn_leftover_processes(UNIT(s)) &&
if (unit_warn_leftover_processes(UNIT(s), unit_log_leftover_process_start) > 0 &&
IN_SET(s->kill_context.kill_mode, KILL_MIXED, KILL_CONTROL_GROUP) &&
!s->kill_context.send_sigkill)
return log_unit_error_errno(UNIT(s), SYNTHETIC_ERRNO(EBUSY),

View File

@ -200,6 +200,11 @@ static inline usec_t service_timeout_abort_usec(Service *s) {
return s->timeout_abort_set ? s->timeout_abort_usec : s->timeout_stop_usec;
}
static inline usec_t service_get_watchdog_usec(Service *s) {
assert(s);
return s->watchdog_override_enable ? s->watchdog_override_usec : s->watchdog_original_usec;
}
extern const UnitVTable service_vtable;
int service_set_socket_fd(Service *s, int fd, struct Socket *socket, bool selinux_context_net);

View File

@ -2035,6 +2035,8 @@ static void socket_enter_dead(Socket *s, SocketResult f) {
else
unit_log_failure(UNIT(s), socket_result_to_string(s->result));
unit_warn_leftover_processes(UNIT(s), unit_log_leftover_process_stop);
socket_set_state(s, s->result != SOCKET_SUCCESS ? SOCKET_FAILED : SOCKET_DEAD);
s->exec_runtime = exec_runtime_unref(s->exec_runtime, true);
@ -2237,7 +2239,7 @@ static void socket_enter_start_pre(Socket *s) {
socket_unwatch_control_pid(s);
unit_warn_leftover_processes(UNIT(s));
unit_warn_leftover_processes(UNIT(s), unit_log_leftover_process_start);
s->control_command_id = SOCKET_EXEC_START_PRE;
s->control_command = s->exec_command[SOCKET_EXEC_START_PRE];

View File

@ -701,6 +701,7 @@ static void swap_enter_dead(Swap *s, SwapResult f) {
s->result = f;
unit_log_result(UNIT(s), s->result == SWAP_SUCCESS, swap_result_to_string(s->result));
unit_warn_leftover_processes(UNIT(s), unit_log_leftover_process_stop);
swap_set_state(s, s->result != SWAP_SUCCESS ? SWAP_FAILED : SWAP_DEAD);
s->exec_runtime = exec_runtime_unref(s->exec_runtime, true);
@ -788,7 +789,7 @@ static void swap_enter_activating(Swap *s) {
assert(s);
unit_warn_leftover_processes(UNIT(s));
unit_warn_leftover_processes(UNIT(s), unit_log_leftover_process_start);
s->control_command_id = SWAP_EXEC_ACTIVATE;
s->control_command = s->exec_command + SWAP_EXEC_ACTIVATE;

View File

@ -4971,7 +4971,7 @@ int unit_kill_context(
if (!pid_set)
return -ENOMEM;
cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path,
(void) cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path,
SIGHUP,
CGROUP_IGNORE_SELF,
pid_set,
@ -5861,14 +5861,20 @@ int unit_prepare_exec(Unit *u) {
return 0;
}
static int log_leftover(pid_t pid, int sig, void *userdata) {
static bool ignore_leftover_process(const char *comm) {
return comm && comm[0] == '('; /* Most likely our own helper process (PAM?), ignore */
}
int unit_log_leftover_process_start(pid_t pid, int sig, void *userdata) {
_cleanup_free_ char *comm = NULL;
(void) get_process_comm(pid, &comm);
if (comm && comm[0] == '(') /* Most likely our own helper process (PAM?), ignore */
if (ignore_leftover_process(comm))
return 0;
/* During start we print a warning */
log_unit_warning(userdata,
"Found left-over process " PID_FMT " (%s) in control group while starting unit. Ignoring.\n"
"This usually indicates unclean termination of a previous run, or service implementation deficiencies.",
@ -5877,7 +5883,24 @@ static int log_leftover(pid_t pid, int sig, void *userdata) {
return 1;
}
int unit_warn_leftover_processes(Unit *u) {
int unit_log_leftover_process_stop(pid_t pid, int sig, void *userdata) {
_cleanup_free_ char *comm = NULL;
(void) get_process_comm(pid, &comm);
if (ignore_leftover_process(comm))
return 0;
/* During stop we only print an informational message */
log_unit_info(userdata,
"Unit process " PID_FMT " (%s) remains running after unit stopped.",
pid, strna(comm));
return 1;
}
int unit_warn_leftover_processes(Unit *u, cg_kill_log_func_t log_func) {
assert(u);
(void) unit_pick_cgroup_path(u);
@ -5885,7 +5908,7 @@ int unit_warn_leftover_processes(Unit *u) {
if (!u->cgroup_path)
return 0;
return cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, 0, 0, NULL, log_leftover, u);
return cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, 0, 0, NULL, log_func, u);
}
bool unit_needs_console(Unit *u) {

View File

@ -846,7 +846,9 @@ void unit_unlink_state_files(Unit *u);
int unit_prepare_exec(Unit *u);
int unit_warn_leftover_processes(Unit *u);
int unit_log_leftover_process_start(pid_t pid, int sig, void *userdata);
int unit_log_leftover_process_stop(pid_t pid, int sig, void *userdata);
int unit_warn_leftover_processes(Unit *u, cg_kill_log_func_t log_func);
bool unit_needs_console(Unit *u);

View File

@ -237,18 +237,18 @@ static int create_disk(
_cleanup_free_ char *n = NULL, *d = NULL, *u = NULL, *e = NULL,
*keydev_mount = NULL, *keyfile_timeout_value = NULL,
*filtered = NULL, *u_escaped = NULL, *name_escaped = NULL, *header_path = NULL, *password_buffer = NULL;
*filtered = NULL, *u_escaped = NULL, *name_escaped = NULL, *header_path = NULL, *password_buffer = NULL,
*tmp_fstype = NULL;
_cleanup_fclose_ FILE *f = NULL;
const char *dmname;
bool noauto, nofail, tmp, swap, netdev, attach_in_initrd;
int r, detached_header, keyfile_can_timeout;
bool noauto, nofail, swap, netdev, attach_in_initrd;
int r, detached_header, keyfile_can_timeout, tmp;
assert(name);
assert(device);
noauto = fstab_test_yes_no_option(options, "noauto\0" "auto\0");
nofail = fstab_test_yes_no_option(options, "nofail\0" "fail\0");
tmp = fstab_test_option(options, "tmp\0");
swap = fstab_test_option(options, "swap\0");
netdev = fstab_test_option(options, "_netdev\0");
attach_in_initrd = fstab_test_option(options, "x-initrd.attach\0");
@ -261,6 +261,10 @@ static int create_disk(
if (detached_header < 0)
return log_error_errno(detached_header, "Failed to parse header= option value: %m");
tmp = fstab_filter_options(options, "tmp\0", NULL, &tmp_fstype, NULL);
if (tmp < 0)
return log_error_errno(tmp, "Failed to parse tmp= option value: %m");
if (tmp && swap)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Device '%s' cannot be both 'tmp' and 'swap'. Ignoring.",
@ -371,10 +375,19 @@ static int create_disk(
if (r < 0)
return r;
if (tmp)
if (tmp) {
_cleanup_free_ char *tmp_fstype_escaped = NULL;
if (tmp_fstype) {
tmp_fstype_escaped = specifier_escape(tmp_fstype);
if (!tmp_fstype_escaped)
return log_oom();
}
fprintf(f,
"ExecStartPost=" ROOTLIBEXECDIR "/systemd-makefs ext2 '/dev/mapper/%s'\n",
name_escaped);
"ExecStartPost=" ROOTLIBEXECDIR "/systemd-makefs '%s' '/dev/mapper/%s'\n",
tmp_fstype_escaped ?: "ext4", name_escaped);
}
if (swap)
fprintf(f,

View File

@ -78,7 +78,6 @@ STATIC_DESTRUCTOR_REGISTER(arg_pkcs11_uri, freep);
loud
quiet
keyscript=
tmp= (the version without argument is supported)
initramfs
*/
@ -232,7 +231,8 @@ static int parse_one_option(const char *option) {
} else if (STR_IN_SET(option, "tcrypt-veracrypt", "veracrypt")) {
arg_type = CRYPT_TCRYPT;
arg_tcrypt_veracrypt = true;
} else if (STR_IN_SET(option, "plain", "swap", "tmp"))
} else if (STR_IN_SET(option, "plain", "swap", "tmp") ||
startswith(option, "tmp="))
arg_type = CRYPT_PLAIN;
else if ((val = startswith(option, "timeout="))) {

View File

@ -978,8 +978,11 @@ typedef struct RunContext {
PTYForward *forward;
sd_bus_slot *match;
/* The exit data of the unit */
/* Current state of the unit */
char *active_state;
bool has_job;
/* The exit data of the unit */
uint64_t inactive_exit_usec;
uint64_t inactive_enter_usec;
char *result;
@ -1010,7 +1013,7 @@ static void run_context_check_done(RunContext *c) {
assert(c);
if (c->match)
done = STRPTR_IN_SET(c->active_state, "inactive", "failed");
done = STRPTR_IN_SET(c->active_state, "inactive", "failed") && !c->has_job;
else
done = true;
@ -1021,6 +1024,20 @@ static void run_context_check_done(RunContext *c) {
sd_event_exit(c->event, EXIT_SUCCESS);
}
static int map_job(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
bool *b = userdata;
const char *job;
uint32_t id;
int r;
r = sd_bus_message_read(m, "(uo)", &id, &job);
if (r < 0)
return r;
*b = id != 0 || !streq(job, "/");
return 0;
}
static int run_context_update(RunContext *c, const char *path) {
static const struct bus_properties_map map[] = {
@ -1035,6 +1052,7 @@ static int run_context_update(RunContext *c, const char *path) {
{ "IPEgressBytes", "t", NULL, offsetof(RunContext, ip_egress_bytes) },
{ "IOReadBytes", "t", NULL, offsetof(RunContext, io_read_bytes) },
{ "IOWriteBytes", "t", NULL, offsetof(RunContext, io_write_bytes) },
{ "Job", "(uo)", map_job, offsetof(RunContext, has_job) },
{}
};

View File

@ -531,15 +531,11 @@ int efi_loader_get_boot_usec(usec_t *firmware, usec_t *loader) {
if (r < 0)
return log_debug_errno(r, "Failed to read LoaderTimeExecUSec: %m");
if (y == 0 || y < x)
if (y == 0 || y < x || y - x > USEC_PER_HOUR)
return log_debug_errno(SYNTHETIC_ERRNO(EIO),
"Bad LoaderTimeInitUSec=%"PRIu64", LoaderTimeExecUSec=%" PRIu64"; refusing.",
x, y);
if (y > USEC_PER_HOUR)
return log_debug_errno(SYNTHETIC_ERRNO(EIO),
"LoaderTimeExecUSec=%"PRIu64" too large, refusing.", x);
*firmware = x;
*loader = y;

View File

@ -80,7 +80,7 @@ int fstab_is_mount_point(const char *mount) {
}
int fstab_filter_options(const char *opts, const char *names,
const char **namefound, char **value, char **filtered) {
const char **ret_namefound, char **ret_value, char **ret_filtered) {
const char *name, *n = NULL, *x;
_cleanup_strv_free_ char **stor = NULL;
_cleanup_free_ char *v = NULL, **strv = NULL;
@ -92,7 +92,7 @@ int fstab_filter_options(const char *opts, const char *names,
/* If !value and !filtered, this function is not allowed to fail. */
if (!filtered) {
if (!ret_filtered) {
const char *word, *state;
size_t l;
@ -108,7 +108,7 @@ int fstab_filter_options(const char *opts, const char *names,
x = word + strlen(name);
if (IN_SET(*x, '\0', '=', ',')) {
n = name;
if (value) {
if (ret_value) {
free(v);
if (IN_SET(*x, '\0', ','))
v = NULL;
@ -145,7 +145,7 @@ int fstab_filter_options(const char *opts, const char *names,
found:
/* Keep the last occurrence found */
n = name;
if (value) {
if (ret_value) {
free(v);
if (*x == '\0')
v = NULL;
@ -162,19 +162,19 @@ int fstab_filter_options(const char *opts, const char *names,
}
answer:
if (namefound)
*namefound = n;
if (filtered) {
if (ret_namefound)
*ret_namefound = n;
if (ret_filtered) {
char *f;
f = strv_join(strv, ",");
if (!f)
return -ENOMEM;
*filtered = f;
*ret_filtered = f;
}
if (value)
*value = TAKE_PTR(v);
if (ret_value)
*ret_value = TAKE_PTR(v);
return !!n;
}

View File

@ -788,19 +788,25 @@ static int enumerate_sysv(const LookupPaths *lp, Hashmap *all_services) {
if (!fpath)
return log_oom();
service = new0(SysvStub, 1);
log_warning("SysV service '%s' lacks a native systemd unit file. "
"Automatically generating a unit file for compatibility. "
"Please update package to include a native systemd unit file, in order to make it more safe and robust.", fpath);
service = new(SysvStub, 1);
if (!service)
return log_oom();
service->sysv_start_priority = -1;
service->name = TAKE_PTR(name);
service->path = TAKE_PTR(fpath);
*service = (SysvStub) {
.sysv_start_priority = -1,
.name = TAKE_PTR(name),
.path = TAKE_PTR(fpath),
};
r = hashmap_put(all_services, service->name, service);
if (r < 0)
return log_oom();
service = NULL;
TAKE_PTR(service);
}
}

View File

@ -724,7 +724,7 @@ static int run(int argc, char *argv[]) {
last_busy_usec = n;
else if (listen_idle_usec != USEC_INFINITY && n >= usec_add(last_busy_usec, listen_idle_usec)) {
char buf[FORMAT_TIMESPAN_MAX];
log_debug("Exiting worker, been idle for %s, .",
log_debug("Exiting worker, been idle for %s.",
format_timespan(buf, sizeof(buf), usec_sub_unsigned(n, last_busy_usec), 0));
break;
}

View File

@ -1,5 +1,13 @@
# SPDX-License-Identifier: LGPL-2.1+
# The 'optimization' option was introduced in meson 0.48.0, so let's keep
# the code compatible with older versions as well
if meson.version().version_compare('>=0.48.0')
optimization = '--optimization=@0@'.format(get_option('optimization'))
else
optimization = ''
endif
sanitize_address_undefined = custom_target(
'sanitize-address-undefined-fuzzers',
output : 'sanitize-address-undefined-fuzzers',
@ -7,8 +15,7 @@ sanitize_address_undefined = custom_target(
project_source_root,
'@OUTPUT@',
'fuzzers',
'-Db_lundef=false -Db_sanitize=address,undefined ' +
'--optimization=@0@'.format(get_option('optimization')),
'-Db_lundef=false -Db_sanitize=address,undefined @0@'.format(optimization),
' '.join(cc.cmd_array()),
cxx_cmd])

View File

@ -678,6 +678,7 @@ cleanup_loopdev() {
if [ -n "${LOOPDEV}" ]; then
ddebug "losetup -d $LOOPDEV"
losetup -d "${LOOPDEV}"
unset LOOPDEV
fi
}
@ -698,8 +699,7 @@ create_empty_image() {
rm -f "$IMAGE_PRIVATE" "$IMAGE_PUBLIC"
# Create the blank file to use as a root filesystem
truncate -s "${_size}M" "$IMAGE_PRIVATE"
ln -vs "$(realpath $IMAGE_PRIVATE)" "$IMAGE_PUBLIC"
truncate -s "${_size}M" "$IMAGE_PUBLIC"
LOOPDEV=$(losetup --show -P -f "$IMAGE_PUBLIC")
[ -b "$LOOPDEV" ] || return 1
@ -2005,16 +2005,26 @@ test_setup() {
if [ -e "$IMAGE_PRIVATE" ]; then
echo "Reusing existing image $IMAGE_PRIVATE → $(realpath $IMAGE_PRIVATE)"
mount_initdir
elif [ -e "$IMAGE_PUBLIC" ]; then
else
if [ ! -e "$IMAGE_PUBLIC" ]; then
# Create the backing public image, but then completely unmount
# it and drop the loopback device responsible for it, since we're
# going to symlink/copy the image and mount it again from
# elsewhere.
test_create_image
test_setup_cleanup
umount_loopback
cleanup_loopdev
fi
echo "Reusing existing cached image $IMAGE_PUBLIC → $(realpath $IMAGE_PUBLIC)"
if [ ${TEST_PARALLELIZE} -ne 0 ]; then
cp -v "$(realpath $IMAGE_PUBLIC)" "$IMAGE_PRIVATE"
else
ln -sv "$(realpath $IMAGE_PUBLIC)" "$IMAGE_PRIVATE"
fi
mount_initdir
else
test_create_image
fi
setup_nspawn_root

View File

@ -30,7 +30,9 @@ UtmpIdentifier=cons
TTYPath=/dev/console
TTYReset=yes
TTYVHangup=yes
m4_ifdef(`ENABLE_LOGIND',,
KillMode=process
)m4_dnl
IgnoreSIGPIPE=no
SendSIGHUP=yes

View File

@ -36,6 +36,8 @@ UtmpIdentifier=pts/%I
TTYPath=/dev/pts/%I
TTYReset=yes
TTYVHangup=yes
m4_ifdef(`ENABLE_LOGIND',,
KillMode=process
)m4_dnl
IgnoreSIGPIPE=no
SendSIGHUP=yes

View File

@ -47,7 +47,9 @@ TTYPath=/dev/%I
TTYReset=yes
TTYVHangup=yes
TTYVTDisallocate=yes
m4_ifdef(`ENABLE_LOGIND',,
KillMode=process
)m4_dnl
IgnoreSIGPIPE=no
SendSIGHUP=yes

View File

@ -40,7 +40,9 @@ UtmpIdentifier=%I
TTYPath=/dev/%I
TTYReset=yes
TTYVHangup=yes
m4_ifdef(`ENABLE_LOGIND',,
KillMode=process
)m4_dnl
IgnoreSIGPIPE=no
SendSIGHUP=yes