1
0
mirror of https://github.com/systemd/systemd synced 2025-10-09 21:54:44 +02:00

Compare commits

..

17 Commits

Author SHA1 Message Date
Yu Watanabe
ffe8f21302 basic/include: replace _Static_assert() with static_assert()
If one of the header is included in a C++ source file, then using
_Static_assert() triggers compile error for some reasons.
Let's use static_assert(), which can be used by both C and C++ code.
2025-07-06 22:02:18 +09:00
Luca Boccassi
a8f8b3efb5 ci: add test timeout multiplier for ppc64le
The slow tests have timed out at least a couple of times,
so add a multiplier

1252/1633 systemd:libsystemd / test-sd-device      TIMEOUT 30.04s killed by signal 15 SIGTERM
1633/1633 systemd:libsystemd / test-journal-verify TIMEOUT 90.01s killed by signal 15 SIGTERM

Follow-up for 8a1d1341444aaf143108e0ca85741c779014d8b2
2025-07-06 12:35:01 +01:00
Yu Watanabe
2643cb1ade core: rename ExecContext.ioprio_set -> .ioprio_is_set
To make it not conflict with syscall ioprio_set().
This is important as we have
```
 #define ioprio_set missing_ioprio_set
```
in missing_syscall.h.
2025-07-06 13:31:40 +02:00
Yu Watanabe
c56e251d3f analyze: include unistd.h
The source file uses symbols e.g. execl(), execvp(), _exit(), and so on,
without including unistd.h.

Continuation of 4f18ff2e29b8054f30b084abcabf5f689f4b340b.

Follow-up for 9a08000d186396bc8bcb8fe057720417543c3bf0.
2025-07-06 13:31:17 +02:00
Yu Watanabe
8d29f31bf6 namespace-util,nsresource: explicitly include sched.h
These source files uses symbols provided by sched.h, e.g.
setns(), unshare(), CLONE_NEWNS, and friends, but they do not explicitly
include sched.h. Currently, it is included indirectly via missing_syscall.h,
which is included by e.g. pidfd-util.h.
Let's explicitly include headers that provides symbols used in the code.

This is similar to 4f18ff2e29b8054f30b084abcabf5f689f4b340b, but for sched.h.
2025-07-06 13:28:46 +02:00
Yu Watanabe
cfba9b9eab tree-wide: several cleanups for reading/writing /proc/sys/fs/nr_open
- use unsigned for the return value of read_nr_open(), as it does not
  fail, and the kernel internally uses unsigned for the value,
- when bumping the value by PID1, let's start from the kernel's maximum
  value defined in fs/file.c. The maximum value should be mostly an API
  of the kernel, but may changed in a future, hence still try several
  times if we fail to bump the value.

Co-authored-by: Jared Baur <jaredbaur@fastmail.com>
Co-authored-by: John Rinehart <johnrichardrinehart@gmail.com>
2025-07-06 13:22:56 +02:00
Luca Boccassi
6cc01c8cc4 ukify: fix parsing uname version with '+'
Debian started using '+' in the kernel uname version, which fails the
regex in ukify. Fix it.
2025-07-06 10:49:22 +01:00
Yu Watanabe
ebfd56975e
cgroup-util: clean up skip_{slices,session,user_manager} (#38089) 2025-07-06 16:37:28 +09:00
Yu Watanabe
b0d40944b3
hwdb: fix typo in 70-maker-tools.hwdb, and add the file to meson.build (#38090) 2025-07-06 16:31:23 +09:00
Yu Watanabe
e7f04514c1
meson fixlets (#38086)
Some fixes for issues found while doing a minimal aarch64 cross build
2025-07-06 16:27:31 +09:00
AsciiWolf
225de2729d hwdb: fix typo in 70-maker-tools.hwdb 2025-07-05 23:44:08 +02:00
AsciiWolf
cdbc500faa
hwdb: add 70-maker-tools.hwdb to meson.build
The hwdb file was not added there in 3dcb56f5e0fe4d937a003bf89496a27b52c5c69e for some reason
2025-07-05 23:32:09 +02:00
Mike Yuan
b6fde0875b
core/cgroup: drop outdated comment 2025-07-05 22:26:23 +02:00
Mike Yuan
d33104eba2
cgroup-util: clean up skip_{slices,session,user_manager}
Let's avoid obscure memcmp()s in skip_* and instead use
strndupa() to extract the bits we care and call usual
string routines on it.
2025-07-05 22:26:23 +02:00
Mike Yuan
68c703872c
string-table: drop unneeded initialization 2025-07-05 22:26:23 +02:00
Luca Boccassi
163e666204 meson: call qemu with -machine virt on aarch64
'qemu-system-aarch64 -device help' fails when no machine is specified.
Use the 'virt' type which seems to be what everyone uses for VMs.
2025-07-05 20:21:51 +01:00
Luca Boccassi
ec0bbbd2a9 meson: do not reference variable unless feature that defines it is enabled
SYSTEMD_LANGUAGE_FALLBACK_MAP is used by the localed test, and
language_fallback_map is defined by the localed meson.
If the feature is disabled, the test is not built so the env var
is not needed, and the meson variable is not defined so the build
fails.
2025-07-05 20:21:00 +01:00
27 changed files with 116 additions and 140 deletions

View File

@ -91,11 +91,18 @@ for phase in "${PHASES[@]}"; do
mv /etc/machine-id /etc/machine-id.bak mv /etc/machine-id /etc/machine-id.bak
fi fi
fi fi
# On ppc64le the workers are slower and some slow tests time out
MESON_TEST_ARGS=()
if [[ "$(uname -m)" != "x86_64" ]] && [[ "$(uname -m)" != "aarch64" ]]; then
MESON_TEST_ARGS+=(--timeout-multiplier=3)
fi
MESON_ARGS+=(--fatal-meson-warnings) MESON_ARGS+=(--fatal-meson-warnings)
run_meson -Dnobody-group=nogroup --werror -Dtests=unsafe -Dslow-tests=true -Dfuzz-tests=true "${MESON_ARGS[@]}" build run_meson -Dnobody-group=nogroup --werror -Dtests=unsafe -Dslow-tests=true -Dfuzz-tests=true "${MESON_ARGS[@]}" build
ninja -C build -v ninja -C build -v
# Ensure setting a timezone (like the reproducible build tests do) does not break time/date unit tests # Ensure setting a timezone (like the reproducible build tests do) does not break time/date unit tests
TZ=GMT+12 meson test -C build --print-errorlogs TZ=GMT+12 meson test "${MESON_TEST_ARGS[@]}" -C build --print-errorlogs
;; ;;
RUN_ASAN_UBSAN|RUN_GCC_ASAN_UBSAN|RUN_CLANG_ASAN_UBSAN|RUN_CLANG_ASAN_UBSAN_NO_DEPS) RUN_ASAN_UBSAN|RUN_GCC_ASAN_UBSAN|RUN_CLANG_ASAN_UBSAN|RUN_CLANG_ASAN_UBSAN_NO_DEPS)
MESON_ARGS=(--optimization=1) MESON_ARGS=(--optimization=1)

View File

@ -68,5 +68,5 @@ usb:v2B71p000E*
# PowerSpec Ultra 3DPrinter # PowerSpec Ultra 3DPrinter
usb:v0315p0001* usb:v0315p0001*
usb:v2B71p00F6* usb:v2B71p00F6*
usb:v2B71p00FF usb:v2B71p00FF*
ID_MAKER_TOOL=1 ID_MAKER_TOOL=1

View File

@ -31,6 +31,7 @@ hwdb_files_test = files(
'70-cameras.hwdb', '70-cameras.hwdb',
'70-hardware-wallets.hwdb', '70-hardware-wallets.hwdb',
'70-joystick.hwdb', '70-joystick.hwdb',
'70-maker-tools.hwdb',
'70-mouse.hwdb', '70-mouse.hwdb',
'70-pda.hwdb', '70-pda.hwdb',
'70-pointingstick.hwdb', '70-pointingstick.hwdb',

View File

@ -2,6 +2,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h>
#include "sd-bus.h" #include "sd-bus.h"

View File

@ -933,28 +933,19 @@ int cg_path_decode_unit(const char *cgroup, char **ret_unit) {
} }
static bool valid_slice_name(const char *p, size_t n) { static bool valid_slice_name(const char *p, size_t n) {
assert(p || n == 0);
if (!p)
return false;
if (n < STRLEN("x.slice")) if (n < STRLEN("x.slice"))
return false; return false;
if (memcmp(p + n - 6, ".slice", 6) == 0) { char *c = strndupa_safe(p, n);
char buf[n+1], *c; if (!endswith(c, ".slice"))
return false;
memcpy(buf, p, n); return unit_name_is_valid(cg_unescape(c), UNIT_NAME_PLAIN);
buf[n] = 0;
c = cg_unescape(buf);
return unit_name_is_valid(c, UNIT_NAME_PLAIN);
}
return false;
} }
static const char *skip_slices(const char *p) { static const char* skip_slices(const char *p) {
assert(p); assert(p);
/* Skips over all slice assignments */ /* Skips over all slice assignments */
@ -1005,7 +996,7 @@ int cg_path_get_unit_path(const char *path, char **ret) {
if (!path_copy) if (!path_copy)
return -ENOMEM; return -ENOMEM;
unit_name = (char *)skip_slices(path_copy); unit_name = (char*) skip_slices(path_copy);
unit_name[strcspn(unit_name, "/")] = 0; unit_name[strcspn(unit_name, "/")] = 0;
if (!unit_name_is_valid(cg_unescape(unit_name), UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE)) if (!unit_name_is_valid(cg_unescape(unit_name), UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE))
@ -1052,12 +1043,11 @@ int cg_pidref_get_unit(const PidRef *pidref, char **ret) {
return 0; return 0;
} }
/** static const char* skip_session(const char *p) {
* Skip session-*.scope, but require it to be there.
*/
static const char *skip_session(const char *p) {
size_t n; size_t n;
/* Skip session-*.scope, but require it to be there. */
if (isempty(p)) if (isempty(p))
return NULL; return NULL;
@ -1067,34 +1057,29 @@ static const char *skip_session(const char *p) {
if (n < STRLEN("session-x.scope")) if (n < STRLEN("session-x.scope"))
return NULL; return NULL;
if (memcmp(p, "session-", 8) == 0 && memcmp(p + n - 6, ".scope", 6) == 0) { const char *s = startswith(p, "session-");
char buf[n - 8 - 6 + 1]; if (!s)
return NULL;
memcpy(buf, p + 8, n - 8 - 6); /* Note that session scopes never need unescaping, since they cannot conflict with the kernel's
buf[n - 8 - 6] = 0; * own names, hence we don't need to call cg_unescape() here. */
char *f = strndupa_safe(s, p + n - s),
*e = endswith(f, ".scope");
if (!e)
return NULL;
*e = '\0';
/* Note that session scopes never need unescaping, if (!session_id_valid(f))
* since they cannot conflict with the kernel's own return NULL;
* names, hence we don't need to call cg_unescape()
* here. */
if (!session_id_valid(buf)) return skip_leading_slash(p + n);
return NULL;
p += n;
p += strspn(p, "/");
return p;
}
return NULL;
} }
/** static const char* skip_user_manager(const char *p) {
* Skip user@*.service or capsule@*.service, but require either of them to be there.
*/
static const char *skip_user_manager(const char *p) {
size_t n; size_t n;
/* Skip user@*.service or capsule@*.service, but require either of them to be there. */
if (isempty(p)) if (isempty(p))
return NULL; return NULL;
@ -1119,26 +1104,14 @@ static const char *skip_user_manager(const char *p) {
/* Note that user manager services never need unescaping, since they cannot conflict with the /* Note that user manager services never need unescaping, since they cannot conflict with the
* kernel's own names, hence we don't need to call cg_unescape() here. Prudently check validity of * kernel's own names, hence we don't need to call cg_unescape() here. Prudently check validity of
* instance names, they should be always valid as we validate them upon unit start. */ * instance names, they should be always valid as we validate them upon unit start. */
if (startswith(unit_name, "user@")) { if (!(startswith(unit_name, "user@") && parse_uid(i, NULL) >= 0) &&
if (parse_uid(i, NULL) < 0) !(startswith(unit_name, "capsule@") && capsule_name_is_valid(i) > 0))
return NULL; return NULL;
p += n; return skip_leading_slash(p + n);
p += strspn(p, "/");
return p;
} else if (startswith(unit_name, "capsule@")) {
if (capsule_name_is_valid(i) <= 0)
return NULL;
p += n;
p += strspn(p, "/");
return p;
}
return NULL;
} }
static const char *skip_user_prefix(const char *path) { static const char* skip_user_prefix(const char *path) {
const char *e, *t; const char *e, *t;
assert(path); assert(path);

View File

@ -226,7 +226,7 @@ int cg_pid_get_user_slice(pid_t pid, char **ret_slice);
int cg_path_decode_unit(const char *cgroup, char **ret_unit); int cg_path_decode_unit(const char *cgroup, char **ret_unit);
bool cg_needs_escape(const char *p); bool cg_needs_escape(const char *p) _pure_;
int cg_escape(const char *p, char **ret); int cg_escape(const char *p, char **ret);
char* cg_unescape(const char *p) _pure_; char* cg_unescape(const char *p) _pure_;

View File

@ -990,7 +990,7 @@ int fd_verify_safe_flags_full(int fd, int extra_flags) {
return flags & (O_ACCMODE_STRICT | extra_flags); /* return the flags variable, but remove the noise */ return flags & (O_ACCMODE_STRICT | extra_flags); /* return the flags variable, but remove the noise */
} }
int read_nr_open(void) { unsigned read_nr_open(void) {
_cleanup_free_ char *nr_open = NULL; _cleanup_free_ char *nr_open = NULL;
int r; int r;
@ -1001,9 +1001,9 @@ int read_nr_open(void) {
if (r < 0) if (r < 0)
log_debug_errno(r, "Failed to read /proc/sys/fs/nr_open, ignoring: %m"); log_debug_errno(r, "Failed to read /proc/sys/fs/nr_open, ignoring: %m");
else { else {
int v; unsigned v;
r = safe_atoi(nr_open, &v); r = safe_atou(nr_open, &v);
if (r < 0) if (r < 0)
log_debug_errno(r, "Failed to parse /proc/sys/fs/nr_open value '%s', ignoring: %m", nr_open); log_debug_errno(r, "Failed to parse /proc/sys/fs/nr_open value '%s', ignoring: %m", nr_open);
else else
@ -1011,7 +1011,7 @@ int read_nr_open(void) {
} }
/* If we fail, fall back to the hard-coded kernel limit of 1024 * 1024. */ /* If we fail, fall back to the hard-coded kernel limit of 1024 * 1024. */
return 1024 * 1024; return NR_OPEN_DEFAULT;
} }
int fd_get_diskseq(int fd, uint64_t *ret) { int fd_get_diskseq(int fd, uint64_t *ret) {

View File

@ -50,6 +50,13 @@
* around the problems with musl's definition. */ * around the problems with musl's definition. */
#define O_ACCMODE_STRICT (O_RDONLY|O_WRONLY|O_RDWR) #define O_ACCMODE_STRICT (O_RDONLY|O_WRONLY|O_RDWR)
/* The default, minimum, and maximum values of /proc/sys/fs/nr_open. See kernel's fs/file.c.
* These values have been unchanged since kernel-2.6.26:
* https://github.com/torvalds/linux/commit/eceea0b3df05ed262ae32e0c6340cc7a3626632d */
#define NR_OPEN_DEFAULT ((unsigned) (1024 * 1024))
#define NR_OPEN_MINIMUM ((unsigned) (sizeof(long) * 8))
#define NR_OPEN_MAXIMUM ((unsigned) (CONST_MIN((size_t) INT_MAX, SIZE_MAX / __SIZEOF_POINTER__) & ~(sizeof(long) * 8 - 1)))
int close_nointr(int fd); int close_nointr(int fd);
int safe_close(int fd); int safe_close(int fd);
void safe_close_pair(int p[static 2]); void safe_close_pair(int p[static 2]);
@ -148,7 +155,7 @@ static inline int fd_verify_safe_flags(int fd) {
return fd_verify_safe_flags_full(fd, 0); return fd_verify_safe_flags_full(fd, 0);
} }
int read_nr_open(void); unsigned read_nr_open(void);
int fd_get_diskseq(int fd, uint64_t *ret); int fd_get_diskseq(int fd, uint64_t *ret);
int path_is_root_at(int dir_fd, const char *path); int path_is_root_at(int dir_fd, const char *path);

View File

@ -8,19 +8,21 @@
#include_next <sched.h> #include_next <sched.h>
#include <assert.h>
/* 769071ac9f20b6a447410c7eaa55d1a5233ef40c (5.8), /* 769071ac9f20b6a447410c7eaa55d1a5233ef40c (5.8),
* defined in sched.h since glibc-2.36. */ * defined in sched.h since glibc-2.36. */
#ifndef CLONE_NEWTIME #ifndef CLONE_NEWTIME
# define CLONE_NEWTIME 0x00000080 # define CLONE_NEWTIME 0x00000080
#else #else
_Static_assert(CLONE_NEWTIME == 0x00000080, ""); static_assert(CLONE_NEWTIME == 0x00000080, "");
#endif #endif
/* Not exposed yet. Defined at include/linux/sched.h */ /* Not exposed yet. Defined at include/linux/sched.h */
#ifndef PF_KTHREAD #ifndef PF_KTHREAD
# define PF_KTHREAD 0x00200000 # define PF_KTHREAD 0x00200000
#else #else
_Static_assert(PF_KTHREAD == 0x00200000, ""); static_assert(PF_KTHREAD == 0x00200000, "");
#endif #endif
/* The maximum thread/process name length including trailing NUL byte. This mimics the kernel definition of /* The maximum thread/process name length including trailing NUL byte. This mimics the kernel definition of
@ -31,5 +33,5 @@ _Static_assert(PF_KTHREAD == 0x00200000, "");
#ifndef TASK_COMM_LEN #ifndef TASK_COMM_LEN
# define TASK_COMM_LEN 16 # define TASK_COMM_LEN 16
#else #else
_Static_assert(TASK_COMM_LEN == 16, ""); static_assert(TASK_COMM_LEN == 16, "");
#endif #endif

View File

@ -3,16 +3,18 @@
#include_next <sys/mman.h> #include_next <sys/mman.h>
#include <assert.h>
/* since glibc-2.38 */ /* since glibc-2.38 */
#ifndef MFD_NOEXEC_SEAL #ifndef MFD_NOEXEC_SEAL
# define MFD_NOEXEC_SEAL 0x0008U # define MFD_NOEXEC_SEAL 0x0008U
#else #else
_Static_assert(MFD_NOEXEC_SEAL == 0x0008U, ""); static_assert(MFD_NOEXEC_SEAL == 0x0008U, "");
#endif #endif
/* since glibc-2.38 */ /* since glibc-2.38 */
#ifndef MFD_EXEC #ifndef MFD_EXEC
# define MFD_EXEC 0x0010U # define MFD_EXEC 0x0010U
#else #else
_Static_assert(MFD_EXEC == 0x0010U, ""); static_assert(MFD_EXEC == 0x0010U, "");
#endif #endif

View File

@ -3,9 +3,11 @@
#include_next <sys/random.h> #include_next <sys/random.h>
#include <assert.h>
/* Defined since glibc-2.32. */ /* Defined since glibc-2.32. */
#ifndef GRND_INSECURE #ifndef GRND_INSECURE
# define GRND_INSECURE 0x0004 # define GRND_INSECURE 0x0004
#else #else
_Static_assert(GRND_INSECURE == 0x0004, ""); static_assert(GRND_INSECURE == 0x0004, "");
#endif #endif

View File

@ -3,9 +3,11 @@
#include_next <sys/wait.h> #include_next <sys/wait.h>
#include <assert.h>
/* since glibc-2.36 */ /* since glibc-2.36 */
#ifndef P_PIDFD #ifndef P_PIDFD
# define P_PIDFD 3 # define P_PIDFD 3
#else #else
_Static_assert(P_PIDFD == 3, ""); static_assert(P_PIDFD == 3, "");
#endif #endif

View File

@ -1,6 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <fcntl.h> #include <fcntl.h>
#include <sched.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/mount.h> #include <sys/mount.h>
#include <unistd.h> #include <unistd.h>

View File

@ -42,6 +42,7 @@ int string_table_lookup_to_string_fallback(const char * const *table, size_t len
if (i < 0 || i > (ssize_t) max) if (i < 0 || i > (ssize_t) max)
return -ERANGE; return -ERANGE;
if (i < (ssize_t) len && table[i]) { if (i < (ssize_t) len && table[i]) {
s = strdup(table[i]); s = strdup(table[i]);
if (!s) if (!s)
@ -54,14 +55,14 @@ int string_table_lookup_to_string_fallback(const char * const *table, size_t len
} }
ssize_t string_table_lookup_from_string_fallback(const char * const *table, size_t len, const char *s, size_t max) { ssize_t string_table_lookup_from_string_fallback(const char * const *table, size_t len, const char *s, size_t max) {
unsigned u = 0;
if (!s) if (!s)
return -EINVAL; return -EINVAL;
ssize_t i = string_table_lookup_from_string(table, len, s); ssize_t i = string_table_lookup_from_string(table, len, s);
if (i >= 0) if (i >= 0)
return i; return i;
unsigned u;
if (safe_atou(s, &u) < 0) if (safe_atou(s, &u) < 0)
return -EINVAL; return -EINVAL;
if (u > max) if (u > max)

View File

@ -1993,8 +1993,7 @@ static int unit_watch_cgroup(Unit *u) {
assert(u); assert(u);
/* Watches the "cgroups.events" attribute of this unit's cgroup for "empty" events, but only if /* Watches the "cgroups.events" attribute of this unit's cgroup for "empty" events. */
* cgroupv2 is available. */
CGroupRuntime *crt = unit_get_cgroup_runtime(u); CGroupRuntime *crt = unit_get_cgroup_runtime(u);
if (!crt || !crt->cgroup_path) if (!crt || !crt->cgroup_path)
@ -2038,8 +2037,7 @@ static int unit_watch_cgroup_memory(Unit *u) {
assert(u); assert(u);
/* Watches the "memory.events" attribute of this unit's cgroup for "oom_kill" events, but only if /* Watches the "memory.events" attribute of this unit's cgroup for "oom_kill" events. */
* cgroupv2 is available. */
CGroupRuntime *crt = unit_get_cgroup_runtime(u); CGroupRuntime *crt = unit_get_cgroup_runtime(u);
if (!crt || !crt->cgroup_path) if (!crt || !crt->cgroup_path)

View File

@ -3028,7 +3028,7 @@ int bus_exec_context_set_transient_property(
return r; return r;
c->ioprio = ioprio_normalize(ioprio_prio_value(q, ioprio_prio_data(c->ioprio))); c->ioprio = ioprio_normalize(ioprio_prio_value(q, ioprio_prio_data(c->ioprio)));
c->ioprio_set = true; c->ioprio_is_set = true;
unit_write_settingf(u, flags, name, "IOSchedulingClass=%s", s); unit_write_settingf(u, flags, name, "IOSchedulingClass=%s", s);
} }
@ -3047,7 +3047,7 @@ int bus_exec_context_set_transient_property(
if (!UNIT_WRITE_FLAGS_NOOP(flags)) { if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
c->ioprio = ioprio_normalize(ioprio_prio_value(ioprio_prio_class(c->ioprio), p)); c->ioprio = ioprio_normalize(ioprio_prio_value(ioprio_prio_class(c->ioprio), p));
c->ioprio_set = true; c->ioprio_is_set = true;
unit_write_settingf(u, flags, name, "IOSchedulingPriority=%i", p); unit_write_settingf(u, flags, name, "IOSchedulingPriority=%i", p);
} }

View File

@ -5137,7 +5137,7 @@ int exec_invoke(
} }
} }
if (context->ioprio_set) if (context->ioprio_is_set)
if (ioprio_set(IOPRIO_WHO_PROCESS, 0, context->ioprio) < 0) { if (ioprio_set(IOPRIO_WHO_PROCESS, 0, context->ioprio) < 0) {
*exit_status = EXIT_IOPRIO; *exit_status = EXIT_IOPRIO;
return log_error_errno(errno, "Failed to set up IO scheduling priority: %m"); return log_error_errno(errno, "Failed to set up IO scheduling priority: %m");

View File

@ -1253,16 +1253,13 @@ static int exec_parameters_serialize(const ExecParameters *p, const ExecContext
} }
static int exec_parameters_deserialize(ExecParameters *p, FILE *f, FDSet *fds) { static int exec_parameters_deserialize(ExecParameters *p, FILE *f, FDSet *fds) {
int r, nr_open; int r;
assert(p); assert(p);
assert(f); assert(f);
assert(fds); assert(fds);
nr_open = read_nr_open(); unsigned nr_open = MAX(read_nr_open(), NR_OPEN_MINIMUM);
if (nr_open < 3)
nr_open = HIGH_RLIMIT_NOFILE;
assert(nr_open > 0); /* For compilers/static analyzers */
for (;;) { for (;;) {
_cleanup_free_ char *l = NULL; _cleanup_free_ char *l = NULL;
@ -1290,7 +1287,7 @@ static int exec_parameters_deserialize(ExecParameters *p, FILE *f, FDSet *fds) {
if (r < 0) if (r < 0)
return r; return r;
if (p->n_socket_fds > (size_t) nr_open) if (p->n_socket_fds > nr_open)
return -EINVAL; /* too many, someone is playing games with us */ return -EINVAL; /* too many, someone is playing games with us */
} else if ((val = startswith(l, "exec-parameters-n-storage-fds="))) { } else if ((val = startswith(l, "exec-parameters-n-storage-fds="))) {
if (p->fds) if (p->fds)
@ -1300,7 +1297,7 @@ static int exec_parameters_deserialize(ExecParameters *p, FILE *f, FDSet *fds) {
if (r < 0) if (r < 0)
return r; return r;
if (p->n_storage_fds > (size_t) nr_open) if (p->n_storage_fds > nr_open)
return -EINVAL; /* too many, someone is playing games with us */ return -EINVAL; /* too many, someone is playing games with us */
} else if ((val = startswith(l, "exec-parameters-n-extra-fds="))) { } else if ((val = startswith(l, "exec-parameters-n-extra-fds="))) {
if (p->fds) if (p->fds)
@ -1310,7 +1307,7 @@ static int exec_parameters_deserialize(ExecParameters *p, FILE *f, FDSet *fds) {
if (r < 0) if (r < 0)
return r; return r;
if (p->n_extra_fds > (size_t) nr_open) if (p->n_extra_fds > nr_open)
return -EINVAL; /* too many, someone is playing games with us */ return -EINVAL; /* too many, someone is playing games with us */
} else if ((val = startswith(l, "exec-parameters-fds="))) { } else if ((val = startswith(l, "exec-parameters-fds="))) {
if (p->n_socket_fds + p->n_storage_fds + p->n_extra_fds == 0) if (p->n_socket_fds + p->n_storage_fds + p->n_extra_fds == 0)
@ -1318,7 +1315,7 @@ static int exec_parameters_deserialize(ExecParameters *p, FILE *f, FDSet *fds) {
SYNTHETIC_ERRNO(EINVAL), SYNTHETIC_ERRNO(EINVAL),
"Got exec-parameters-fds= without " "Got exec-parameters-fds= without "
"prior exec-parameters-n-socket-fds= or exec-parameters-n-storage-fds= or exec-parameters-n-extra-fds="); "prior exec-parameters-n-socket-fds= or exec-parameters-n-storage-fds= or exec-parameters-n-extra-fds=");
if (p->n_socket_fds + p->n_storage_fds + p->n_extra_fds > (size_t) nr_open) if (p->n_socket_fds + p->n_storage_fds + p->n_extra_fds > nr_open)
return -EINVAL; /* too many, someone is playing games with us */ return -EINVAL; /* too many, someone is playing games with us */
if (p->fds) if (p->fds)
@ -1894,7 +1891,7 @@ static int exec_context_serialize(const ExecContext *c, FILE *f) {
return r; return r;
} }
if (c->ioprio_set) { if (c->ioprio_is_set) {
r = serialize_item_format(f, "exec-context-ioprio", "%d", c->ioprio); r = serialize_item_format(f, "exec-context-ioprio", "%d", c->ioprio);
if (r < 0) if (r < 0)
return r; return r;
@ -2859,7 +2856,7 @@ static int exec_context_deserialize(ExecContext *c, FILE *f) {
r = safe_atoi(val, &c->ioprio); r = safe_atoi(val, &c->ioprio);
if (r < 0) if (r < 0)
return r; return r;
c->ioprio_set = true; c->ioprio_is_set = true;
} else if ((val = startswith(l, "exec-context-cpu-scheduling-policy="))) { } else if ((val = startswith(l, "exec-context-cpu-scheduling-policy="))) {
c->cpu_sched_policy = sched_policy_from_string(val); c->cpu_sched_policy = sched_policy_from_string(val);
if (c->cpu_sched_policy < 0) if (c->cpu_sched_policy < 0)

View File

@ -1245,7 +1245,7 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) {
prefix, rlimit_to_string(i), c->rlimit[i]->rlim_cur); prefix, rlimit_to_string(i), c->rlimit[i]->rlim_cur);
} }
if (c->ioprio_set) { if (c->ioprio_is_set) {
_cleanup_free_ char *class_str = NULL; _cleanup_free_ char *class_str = NULL;
r = ioprio_class_to_string_alloc(ioprio_prio_class(c->ioprio), &class_str); r = ioprio_class_to_string_alloc(ioprio_prio_class(c->ioprio), &class_str);
@ -1607,7 +1607,7 @@ int exec_context_get_effective_ioprio(const ExecContext *c) {
assert(c); assert(c);
if (c->ioprio_set) if (c->ioprio_is_set)
return c->ioprio; return c->ioprio;
p = ioprio_get(IOPRIO_WHO_PROCESS, 0); p = ioprio_get(IOPRIO_WHO_PROCESS, 0);

View File

@ -190,7 +190,7 @@ typedef struct ExecContext {
bool oom_score_adjust_set:1; bool oom_score_adjust_set:1;
bool coredump_filter_set:1; bool coredump_filter_set:1;
bool nice_set:1; bool nice_set:1;
bool ioprio_set:1; bool ioprio_is_set:1;
bool cpu_sched_set:1; bool cpu_sched_set:1;
/* This is not exposed to the user but available internally. We need it to make sure that whenever we /* This is not exposed to the user but available internally. We need it to make sure that whenever we

View File

@ -1450,7 +1450,7 @@ int config_parse_exec_io_class(
assert(rvalue); assert(rvalue);
if (isempty(rvalue)) { if (isempty(rvalue)) {
c->ioprio_set = false; c->ioprio_is_set = false;
c->ioprio = IOPRIO_DEFAULT_CLASS_AND_PRIO; c->ioprio = IOPRIO_DEFAULT_CLASS_AND_PRIO;
return 0; return 0;
} }
@ -1462,7 +1462,7 @@ int config_parse_exec_io_class(
} }
c->ioprio = ioprio_normalize(ioprio_prio_value(x, ioprio_prio_data(c->ioprio))); c->ioprio = ioprio_normalize(ioprio_prio_value(x, ioprio_prio_data(c->ioprio)));
c->ioprio_set = true; c->ioprio_is_set = true;
return 0; return 0;
} }
@ -1487,7 +1487,7 @@ int config_parse_exec_io_priority(
assert(rvalue); assert(rvalue);
if (isempty(rvalue)) { if (isempty(rvalue)) {
c->ioprio_set = false; c->ioprio_is_set = false;
c->ioprio = IOPRIO_DEFAULT_CLASS_AND_PRIO; c->ioprio = IOPRIO_DEFAULT_CLASS_AND_PRIO;
return 0; return 0;
} }
@ -1499,7 +1499,7 @@ int config_parse_exec_io_priority(
} }
c->ioprio = ioprio_normalize(ioprio_prio_value(ioprio_prio_class(c->ioprio), i)); c->ioprio = ioprio_normalize(ioprio_prio_value(ioprio_prio_class(c->ioprio), i));
c->ioprio_set = true; c->ioprio_is_set = true;
return 0; return 0;
} }

View File

@ -1275,38 +1275,20 @@ static void bump_file_max_and_nr_open(void) {
#endif #endif
#if BUMP_PROC_SYS_FS_NR_OPEN #if BUMP_PROC_SYS_FS_NR_OPEN
int v = INT_MAX; /* The kernel enforces maximum and minimum values on the fs.nr_open, but they are not directly
* exposed, but hardcoded in fs/file.c. Hopefully, these values will not be changed, but not sure.
* Let's first try the hardcoded maximum value, and if it does not work, try the half of it. */
/* Argh! The kernel enforces maximum and minimum values on the fs.nr_open, but we don't really know for (unsigned v = NR_OPEN_MAXIMUM; v >= NR_OPEN_MINIMUM; v /= 2) {
* what they are. The expression by which the maximum is determined is dependent on the architecture, unsigned k = read_nr_open();
* and is something we don't really want to copy to userspace, as it is dependent on implementation
* details of the kernel. Since the kernel doesn't expose the maximum value to us, we can only try
* and hope. Hence, let's start with INT_MAX, and then keep halving the value until we find one that
* works. Ugly? Yes, absolutely, but kernel APIs are kernel APIs, so what do can we do... 🤯 */
for (;;) {
int k;
v &= ~(__SIZEOF_POINTER__ - 1); /* Round down to next multiple of the pointer size */
if (v < 1024) {
log_warning("Can't bump fs.nr_open, value too small.");
break;
}
k = read_nr_open();
if (k < 0) {
log_error_errno(k, "Failed to read fs.nr_open: %m");
break;
}
if (k >= v) { /* Already larger */ if (k >= v) { /* Already larger */
log_debug("Skipping bump, value is already larger."); log_debug("Skipping bump, value is already larger.");
break; break;
} }
r = sysctl_writef("fs/nr_open", "%i", v); r = sysctl_writef("fs/nr_open", "%u", v);
if (r == -EINVAL) { if (r == -EINVAL) {
log_debug("Couldn't write fs.nr_open as %i, halving it.", v); log_debug("Couldn't write fs.nr_open as %u, halving it.", v);
v /= 2;
continue; continue;
} }
if (r < 0) { if (r < 0) {
@ -1314,7 +1296,7 @@ static void bump_file_max_and_nr_open(void) {
break; break;
} }
log_debug("Successfully bumped fs.nr_open to %i", v); log_debug("Successfully bumped fs.nr_open to %u", v);
break; break;
} }
#endif #endif
@ -1322,10 +1304,10 @@ static void bump_file_max_and_nr_open(void) {
static int bump_rlimit_nofile(const struct rlimit *saved_rlimit) { static int bump_rlimit_nofile(const struct rlimit *saved_rlimit) {
struct rlimit new_rlimit; struct rlimit new_rlimit;
int r, nr; int r;
/* Get the underlying absolute limit the kernel enforces */ /* Get the underlying absolute limit the kernel enforces */
nr = read_nr_open(); unsigned nr = read_nr_open();
/* Calculate the new limits to use for us. Never lower from what we inherited. */ /* Calculate the new limits to use for us. Never lower from what we inherited. */
new_rlimit = (struct rlimit) { new_rlimit = (struct rlimit) {
@ -2690,14 +2672,8 @@ static void fallback_rlimit_nofile(const struct rlimit *saved_rlimit_nofile) {
* (and thus use poll()/epoll instead of select(), the way everybody should) can * (and thus use poll()/epoll instead of select(), the way everybody should) can
* explicitly opt into high fds by bumping their soft limit beyond 1024, to the hard limit * explicitly opt into high fds by bumping their soft limit beyond 1024, to the hard limit
* we pass. */ * we pass. */
if (arg_runtime_scope == RUNTIME_SCOPE_SYSTEM) { if (arg_runtime_scope == RUNTIME_SCOPE_SYSTEM)
int nr; rl->rlim_max = MIN((rlim_t) read_nr_open(), MAX(rl->rlim_max, (rlim_t) HIGH_RLIMIT_NOFILE));
/* Get the underlying absolute limit the kernel enforces */
nr = read_nr_open();
rl->rlim_max = MIN((rlim_t) nr, MAX(rl->rlim_max, (rlim_t) HIGH_RLIMIT_NOFILE));
}
/* If for some reason we were invoked with a soft limit above 1024 (which should never /* If for some reason we were invoked with a soft limit above 1024 (which should never
* happen!, but who knows what we get passed in from pam_limit when invoked as --user * happen!, but who knows what we get passed in from pam_limit when invoked as --user

View File

@ -6,6 +6,7 @@
#include <linux/veth.h> #include <linux/veth.h>
#include <net/if.h> #include <net/if.h>
#include <poll.h> #include <poll.h>
#include <sched.h>
#include <sys/eventfd.h> #include <sys/eventfd.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/stat.h> #include <sys/stat.h>

View File

@ -12,7 +12,9 @@ generated_sources += test_hashmap_ordered_c
path = run_command(sh, '-c', 'echo "$PATH"', check: true).stdout().strip() path = run_command(sh, '-c', 'echo "$PATH"', check: true).stdout().strip()
test_env = environment() test_env = environment()
test_env.set('SYSTEMD_LANGUAGE_FALLBACK_MAP', language_fallback_map) if conf.get('ENABLE_LOCALED') == 1
test_env.set('SYSTEMD_LANGUAGE_FALLBACK_MAP', language_fallback_map)
endif
test_env.set('PATH', meson.project_build_root() + ':' + path) test_env.set('PATH', meson.project_build_root() + ':' + path)
test_env.set('PROJECT_BUILD_ROOT', meson.project_build_root()) test_env.set('PROJECT_BUILD_ROOT', meson.project_build_root())
test_env.set('SYSTEMD_SLOW_TESTS', want_slow_tests ? '1' : '0') test_env.set('SYSTEMD_SLOW_TESTS', want_slow_tests ? '1' : '0')

View File

@ -228,7 +228,7 @@ TEST(rearrange_stdio) {
} }
TEST(read_nr_open) { TEST(read_nr_open) {
log_info("nr-open: %i", read_nr_open()); log_info("nr-open: %u", read_nr_open());
} }
static size_t validate_fds( static size_t validate_fds(

View File

@ -310,7 +310,7 @@ class UkifyConfig:
class Uname: class Uname:
# This class is here purely as a namespace for the functions # This class is here purely as a namespace for the functions
VERSION_PATTERN = r'(?P<version>[a-z0-9._-]+) \([^ )]+\) (?:#.*)' VERSION_PATTERN = r'(?P<version>[a-z0-9._+-]+) \([^ )]+\) (?:#.*)'
NOTES_PATTERN = r'^\s+Linux\s+0x[0-9a-f]+\s+OPEN\n\s+description data: (?P<version>[0-9a-f ]+)\s*$' NOTES_PATTERN = r'^\s+Linux\s+0x[0-9a-f]+\s+OPEN\n\s+description data: (?P<version>[0-9a-f ]+)\s*$'

View File

@ -7,7 +7,10 @@ udev_storage_test_template = {
} }
qemu = find_program('qemu-system-@0@'.format(host_machine.cpu_family()), 'qemu-kvm', dirs : ['/usr/libexec'], native : true, required : false) qemu = find_program('qemu-system-@0@'.format(host_machine.cpu_family()), 'qemu-kvm', dirs : ['/usr/libexec'], native : true, required : false)
if qemu.found() if qemu.found() and host_machine.cpu_family() == 'aarch64'
# qemu-system-aarch64 errors out if no machine is specified
devices = run_command(qemu, '-device', 'help', '-machine', 'virt', check : true).stdout().strip()
elif qemu.found()
devices = run_command(qemu, '-device', 'help', check : true).stdout().strip() devices = run_command(qemu, '-device', 'help', check : true).stdout().strip()
else else
devices = '' devices = ''