1
0
mirror of https://github.com/systemd/systemd synced 2025-10-08 13:14:45 +02:00

Compare commits

...

10 Commits

Author SHA1 Message Date
Yu Watanabe
48e0f7bc2f
core: fix owner check of PIDFile=, and update document (#38115)
Closes #38108.
2025-07-08 23:58:19 +09:00
Yu Watanabe
4fef8b916e
A few changes related to linking and bitfields (#38118) 2025-07-08 23:57:44 +09:00
Zbigniew Jędrzejewski-Szmek
6eb805f42a meson: drop -ffunction-sections -fdata-sections
I added them in 41afb5eb7214727301132aedc381831fbfc78e37 without too
much explanation. Most likely the idea was to get rid of unused code
in libsystemd.so [1]. But now that I'm testing this, it doesn't seem
to have an effect. LTO is needed to get rid of unused functions, and
it's enough to have LTO without those options. Those options might have
some downsides [2], so let's disable them since there are doubts and no
particularly good reason to have them.

But keep the -Wl,--gc-sections option. Without this, libsystemd.so
grows a little:
-rwxr-xr-x 1 zbyszek zbyszek 5532424 07-08 13:24 build/libsystemd.so.0.40.0-orig
-rwxr-xr-x 1 zbyszek zbyszek 5614472 07-08 13:26 build/libsystemd.so.0.40.0-no-sections
-rwxr-xr-x 1 zbyszek zbyszek 5532392 07-08 13:27 build/libsystemd.so.0.40.0

Let's apply the --gc-sections option always to make the debug and final
builds more similar.

We need to verify that distro packages don't unexpectedly grow after this.

[1] https://unix.stackexchange.com/a/715901
[2] https://stackoverflow.com/a/36033811
2025-07-08 14:51:56 +02:00
Zbigniew Jędrzejewski-Szmek
048a94c8f6 basic/stdio-util: use a fixed message in xsprintf
We put the name of the variable in the message, but it is a local variable
and the name does not have global meaning. We end up with pointless copies
of the error string:

$ strings build/libsystemd.so.0.40.0 | grep 'big enough'
xsprintf: p[] must be big enough
xsprintf: error[] must be big enough
xsprintf: prefix[] must be big enough
xsprintf: pty[] must be big enough
xsprintf: mode[] must be big enough
xsprintf: t[] must be big enough
xsprintf: s[] must be big enough
xsprintf: spid[] must be big enough
xsprintf: header_priority[] must be big enough
xsprintf: header_pid[] must be big enough
xsprintf: path[] must be big enough
xsprintf: buf[] must be big enough

The error message already shows the file, line, and function name, which
is enough to identify the problem:

  Assertion 'xsprintf: buffer too small' failed at src/test/test-string-util.c:20, function test_xsprintf(). Aborting.
2025-07-08 13:02:37 +02:00
Zbigniew Jędrzejewski-Szmek
1e99c4e2be test-string-util: add a small test for xsprintf 2025-07-08 13:02:37 +02:00
Zbigniew Jędrzejewski-Szmek
c179466616 Merge shared/exec-directory-util.? into basic/unit-def.?
Suggested in
https://github.com/systemd/systemd/pull/35892#discussion_r2180322856.

This is a tiny amount of code and does not warrant having a separate file
and spawning a separate instance of the compiler during the build.

Note: it took me a while to confirm that the contents of that table and
function don't end up in libsystemd.so. The issue is that they _are_ present in
it, unless LTO is used. We actually use link_whole[libbasic_static] for
libsystemd, so we end up with all that code there. LTO is needed to clean
that up.
2025-07-08 12:57:33 +02:00
Yu Watanabe
293cc8866d man: mention relative PIDFile= in user service is prefixed with $XDG_RUNTIME_DIR 2025-07-08 18:02:38 +09:00
Yu Watanabe
7e26912677 core: allow to use PIDFile= in user session services
Fixes #38108.

Co-authored-by: 铝箔 <38349409+Sodium-Aluminate@users.noreply.github.com>
2025-07-08 18:02:34 +09:00
Zbigniew Jędrzejewski-Szmek
f283459b9f shared/open-file: add line break
We don't generally parenthesize additions, so drop that too.
2025-07-08 10:22:59 +02:00
Zbigniew Jędrzejewski-Szmek
d9a460b2b6 Adjust bitfields in struct Condition
As is usually the case, the bitfields don't create the expected space savings,
because the field that follows needs to be aligned. But we don't want to fully
drop the bitfields here, because then ConditionType and ConditionResult are
each 4 bytes, and the whole struct grows from 32 to 40 bytes (on amd64). We
potentially have lots of little Conditions and that'd waste some memory.

Make each of the four fields one byte. This still allows the compiler to
generate simpler code without changing the struct size:

E.g. in condition_test:
                 c->result = CONDITION_ERROR;
-   78fab:      48 8b 45 e8             mov    -0x18(%rbp),%rax
-   78faf:      0f b6 50 01             movzbl 0x1(%rax),%edx
-   78fb3:      83 e2 03                and    $0x3,%edx
-   78fb6:      83 ca 0c                or     $0xc,%edx
-   78fb9:      88 50 01                mov    %dl,0x1(%rax)
+   78f8b:      48 8b 45 e8             mov    -0x18(%rbp),%rax
+   78f8f:      c6 40 03 03             movb   $0x3,0x3(%rax)
2025-07-08 10:22:59 +02:00
14 changed files with 62 additions and 64 deletions

View File

@ -357,15 +357,17 @@
<varlistentry>
<term><varname>PIDFile=</varname></term>
<listitem><para>Takes a path referring to the PID file of the service. Usage of this option is recommended for
services where <varname>Type=</varname> is set to <option>forking</option>. The path specified typically points
to a file below <filename>/run/</filename>. If a relative path is specified it is hence prefixed with
<filename>/run/</filename>. The service manager will read the PID of the main process of the service from this
file after start-up of the service. The service manager will not write to the file configured here, although it
will remove the file after the service has shut down if it still exists. The PID file does not need to be owned
by a privileged user, but if it is owned by an unprivileged user additional safety restrictions are enforced:
the file may not be a symlink to a file owned by a different user (neither directly nor indirectly), and the
PID file must refer to a process already belonging to the service.</para>
<listitem><para>Takes a path referring to the PID file of the service. Usage of this option is
recommended for services where <varname>Type=</varname> is set to <option>forking</option>. The path
specified typically points to a file below <filename>/run/</filename>. If a relative path is
specified for system service, then it is hence prefixed with <filename>/run/</filename>, and prefixed
with <filename>$XDG_RUNTIME_DIR</filename> if specified in a user service. The service manager will
read the PID of the main process of the service from this file after start-up of the service. The
service manager will not write to the file configured here, although it will remove the file after
the service has shut down if it still exists. The PID file does not need to be owned by a privileged
user, but if it is owned by an unprivileged user additional safety restrictions are enforced: the
file may not be a symlink to a file owned by a different user (neither directly nor indirectly), and
the PID file must refer to a process already belonging to the service.</para>
<para>Note that PID files should be avoided in modern projects. Use <option>Type=notify</option>,
<option>Type=notify-reload</option> or <option>Type=simple</option> where possible, which does not

View File

@ -484,6 +484,7 @@ possible_link_flags = [
'-Wl,--fatal-warnings',
'-Wl,-z,now',
'-Wl,-z,relro',
'-Wl,--gc-sections',
]
if get_option('b_sanitize') == 'none'
@ -503,15 +504,6 @@ possible_cc_flags = [
'-fvisibility=hidden',
]
if get_option('buildtype') != 'debug'
possible_cc_flags += [
'-ffunction-sections',
'-fdata-sections',
]
possible_link_flags += '-Wl,--gc-sections'
endif
if get_option('mode') == 'developer'
possible_cc_flags += '-fno-omit-frame-pointer'
endif

View File

@ -19,7 +19,7 @@ static inline char* snprintf_ok(char *buf, size_t len, const char *format, ...)
}
#define xsprintf(buf, fmt, ...) \
assert_message_se(snprintf_ok(buf, ELEMENTSOF(buf), fmt, ##__VA_ARGS__), "xsprintf: " #buf "[] must be big enough")
assert_message_se(snprintf_ok(buf, ELEMENTSOF(buf), fmt, ##__VA_ARGS__), "xsprintf: buffer too small")
#define VA_FORMAT_ADVANCE(format, ap) \
do { \

View File

@ -361,6 +361,17 @@ static const char* const job_mode_table[_JOB_MODE_MAX] = {
DEFINE_STRING_TABLE_LOOKUP(job_mode, JobMode);
/* This table maps ExecDirectoryType to the setting it is configured with in the unit */
static const char* const exec_directory_type_table[_EXEC_DIRECTORY_TYPE_MAX] = {
[EXEC_DIRECTORY_RUNTIME] = "RuntimeDirectory",
[EXEC_DIRECTORY_STATE] = "StateDirectory",
[EXEC_DIRECTORY_CACHE] = "CacheDirectory",
[EXEC_DIRECTORY_LOGS] = "LogsDirectory",
[EXEC_DIRECTORY_CONFIGURATION] = "ConfigurationDirectory",
};
DEFINE_STRING_TABLE_LOOKUP(exec_directory_type, ExecDirectoryType);
Glyph unit_active_state_to_glyph(UnitActiveState state) {
static const Glyph map[_UNIT_ACTIVE_STATE_MAX] = {
[UNIT_ACTIVE] = GLYPH_BLACK_CIRCLE,

View File

@ -296,6 +296,16 @@ typedef enum JobMode {
_JOB_MODE_INVALID = -EINVAL,
} JobMode;
typedef enum ExecDirectoryType {
EXEC_DIRECTORY_RUNTIME,
EXEC_DIRECTORY_STATE,
EXEC_DIRECTORY_CACHE,
EXEC_DIRECTORY_LOGS,
EXEC_DIRECTORY_CONFIGURATION,
_EXEC_DIRECTORY_TYPE_MAX,
_EXEC_DIRECTORY_TYPE_INVALID = -EINVAL,
} ExecDirectoryType;
char* unit_dbus_path_from_name(const char *name);
int unit_name_from_dbus_path(const char *path, char **name);
@ -361,4 +371,7 @@ NotifyAccess notify_access_from_string(const char *s) _pure_;
const char* job_mode_to_string(JobMode t) _const_;
JobMode job_mode_from_string(const char *s) _pure_;
const char* exec_directory_type_to_string(ExecDirectoryType i) _const_;
ExecDirectoryType exec_directory_type_from_string(const char *s) _pure_;
Glyph unit_active_state_to_glyph(UnitActiveState state);

View File

@ -7,7 +7,6 @@
#include "cgroup-util.h"
#include "core-forward.h"
#include "cpu-set-util.h"
#include "exec-directory-util.h"
#include "exec-util.h"
#include "list.h"
#include "log-context.h"

View File

@ -1204,11 +1204,13 @@ static int service_load_pid_file(Service *s, bool may_warn) {
if (fstat(fileno(f), &st) < 0)
return log_unit_error_errno(UNIT(s), errno, "Failed to fstat() PID file '%s': %m", s->pid_file);
if (st.st_uid != 0)
if (st.st_uid != getuid())
return log_unit_error_errno(UNIT(s), SYNTHETIC_ERRNO(EPERM),
"New main PID "PID_FMT" from PID file does not belong to service, and PID file is not owned by root. Refusing.", pidref.pid);
"New main PID "PID_FMT" from PID file does not belong to service, and PID file is owned by "UID_FMT" (must be owned by "UID_FMT"). Refusing.",
pidref.pid, st.st_uid, getuid());
log_unit_debug(UNIT(s), "New main PID "PID_FMT" does not belong to service, accepting anyway since PID file is owned by root.", pidref.pid);
log_unit_debug(UNIT(s), "New main PID "PID_FMT" does not belong to service, accepting anyway since PID file is owned by "UID_FMT".",
pidref.pid, st.st_uid);
}
if (s->main_pid_known) {

View File

@ -58,12 +58,13 @@ typedef enum ConditionResult {
} ConditionResult;
typedef struct Condition {
/* Use bitfields for ConditionType and ConditionResult to keep the whole struct in 32 bytes. */
ConditionType type:8;
bool trigger:1;
bool negate:1;
bool trigger;
bool negate;
ConditionResult result:6;
ConditionResult result:8;
char *parameter;

View File

@ -1,15 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "exec-directory-util.h"
#include "string-table.h"
/* This table maps ExecDirectoryType to the setting it is configured with in the unit */
static const char* const exec_directory_type_table[_EXEC_DIRECTORY_TYPE_MAX] = {
[EXEC_DIRECTORY_RUNTIME] = "RuntimeDirectory",
[EXEC_DIRECTORY_STATE] = "StateDirectory",
[EXEC_DIRECTORY_CACHE] = "CacheDirectory",
[EXEC_DIRECTORY_LOGS] = "LogsDirectory",
[EXEC_DIRECTORY_CONFIGURATION] = "ConfigurationDirectory",
};
DEFINE_STRING_TABLE_LOOKUP(exec_directory_type, ExecDirectoryType);

View File

@ -1,19 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include <errno.h>
#include "macro-fundamental.h"
typedef enum ExecDirectoryType {
EXEC_DIRECTORY_RUNTIME,
EXEC_DIRECTORY_STATE,
EXEC_DIRECTORY_CACHE,
EXEC_DIRECTORY_LOGS,
EXEC_DIRECTORY_CONFIGURATION,
_EXEC_DIRECTORY_TYPE_MAX,
_EXEC_DIRECTORY_TYPE_INVALID = -EINVAL,
} ExecDirectoryType;
const char* exec_directory_type_to_string(ExecDirectoryType i) _const_;
ExecDirectoryType exec_directory_type_from_string(const char *s) _pure_;

View File

@ -69,7 +69,6 @@ shared_sources = files(
'elf-util.c',
'enable-mempool.c',
'ethtool-util.c',
'exec-directory-util.c',
'exec-util.c',
'exit-status.c',
'extension-util.c',

View File

@ -76,8 +76,9 @@ int open_file_validate(const OpenFile *of) {
if (!fdname_is_valid(of->fdname))
return -EINVAL;
if ((FLAGS_SET(of->flags, OPENFILE_READ_ONLY) + FLAGS_SET(of->flags, OPENFILE_APPEND) +
FLAGS_SET(of->flags, OPENFILE_TRUNCATE)) > 1)
if (FLAGS_SET(of->flags, OPENFILE_READ_ONLY) +
FLAGS_SET(of->flags, OPENFILE_APPEND) +
FLAGS_SET(of->flags, OPENFILE_TRUNCATE) > 1)
return -EINVAL;
if ((of->flags & ~_OPENFILE_MASK_PUBLIC) != 0)

View File

@ -15,7 +15,6 @@
#include "cgroup-show.h"
#include "cpu-set-util.h"
#include "errno-util.h"
#include "exec-directory-util.h"
#include "exec-util.h"
#include "exit-status.h"
#include "extract-word.h"

View File

@ -9,6 +9,19 @@
#include "strv.h"
#include "tests.h"
TEST(xsprintf) {
char buf[5];
xsprintf(buf, "asdf");
xsprintf(buf, "%4s", "a");
xsprintf(buf, "%-4s", "a");
xsprintf(buf, "%04d", 1);
ASSERT_SIGNAL(xsprintf(buf, "asdfe"), SIGABRT);
ASSERT_SIGNAL(xsprintf(buf, "asdfefghdhdhdhdhd"), SIGABRT);
ASSERT_SIGNAL(xsprintf(buf, "%5s", "a"), SIGABRT);
}
TEST(string_erase) {
char *x;
x = strdupa_safe("");