systemd-252-3

Resolves: #2138081,#2141979,#2151993,#2155517,#2160477
This commit is contained in:
Jan Macku 2023-01-16 09:56:47 +01:00
parent 79350f79d8
commit eceb26ad96
24 changed files with 2035 additions and 1 deletions

View File

@ -0,0 +1,29 @@
From 94bab389194116ab10a68bca3d72c5b06f332645 Mon Sep 17 00:00:00 2001
From: David Tardon <dtardon@redhat.com>
Date: Mon, 12 Dec 2022 16:21:30 +0100
Subject: [PATCH] swap: tell swapon to reinitialize swap if needed
If the page size of a swap space doesn't match the page size of the
currently running kernel, swapon will fail. Let's instruct it to
reinitialize the swap space instead.
(cherry picked from commit cc137d53e36da5e57b060be5e621864f572b2cac)
Resolves: #2151993
---
src/core/swap.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/core/swap.c b/src/core/swap.c
index 2196793ad1..5c83c4780f 100644
--- a/src/core/swap.c
+++ b/src/core/swap.c
@@ -827,7 +827,7 @@ static void swap_enter_activating(Swap *s) {
}
}
- r = exec_command_set(s->control_command, "/sbin/swapon", NULL);
+ r = exec_command_set(s->control_command, "/sbin/swapon", "--fixpgsz", NULL);
if (r < 0)
goto fail;

View File

@ -0,0 +1,101 @@
From e611a79647dd2ec68b8d5553d8aa566e79cd9f6e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Tue, 29 Nov 2022 09:00:16 +0100
Subject: [PATCH] coredump: adjust whitespace
(cherry picked from commit 510a146634f3e095b34e2a26023b1b1f99dcb8c0)
Related: #2155517
---
src/coredump/coredump.c | 56 ++++++++++++++++++++---------------------
1 file changed, 28 insertions(+), 28 deletions(-)
diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c
index 98e7492811..7a181bdeeb 100644
--- a/src/coredump/coredump.c
+++ b/src/coredump/coredump.c
@@ -110,16 +110,16 @@ enum {
};
static const char * const meta_field_names[_META_MAX] = {
- [META_ARGV_PID] = "COREDUMP_PID=",
- [META_ARGV_UID] = "COREDUMP_UID=",
- [META_ARGV_GID] = "COREDUMP_GID=",
- [META_ARGV_SIGNAL] = "COREDUMP_SIGNAL=",
- [META_ARGV_TIMESTAMP] = "COREDUMP_TIMESTAMP=",
- [META_ARGV_RLIMIT] = "COREDUMP_RLIMIT=",
- [META_ARGV_HOSTNAME] = "COREDUMP_HOSTNAME=",
- [META_COMM] = "COREDUMP_COMM=",
- [META_EXE] = "COREDUMP_EXE=",
- [META_UNIT] = "COREDUMP_UNIT=",
+ [META_ARGV_PID] = "COREDUMP_PID=",
+ [META_ARGV_UID] = "COREDUMP_UID=",
+ [META_ARGV_GID] = "COREDUMP_GID=",
+ [META_ARGV_SIGNAL] = "COREDUMP_SIGNAL=",
+ [META_ARGV_TIMESTAMP] = "COREDUMP_TIMESTAMP=",
+ [META_ARGV_RLIMIT] = "COREDUMP_RLIMIT=",
+ [META_ARGV_HOSTNAME] = "COREDUMP_HOSTNAME=",
+ [META_COMM] = "COREDUMP_COMM=",
+ [META_EXE] = "COREDUMP_EXE=",
+ [META_UNIT] = "COREDUMP_UNIT=",
};
typedef struct Context {
@@ -138,9 +138,9 @@ typedef enum CoredumpStorage {
} CoredumpStorage;
static const char* const coredump_storage_table[_COREDUMP_STORAGE_MAX] = {
- [COREDUMP_STORAGE_NONE] = "none",
+ [COREDUMP_STORAGE_NONE] = "none",
[COREDUMP_STORAGE_EXTERNAL] = "external",
- [COREDUMP_STORAGE_JOURNAL] = "journal",
+ [COREDUMP_STORAGE_JOURNAL] = "journal",
};
DEFINE_PRIVATE_STRING_TABLE_LOOKUP(coredump_storage, CoredumpStorage);
@@ -156,13 +156,13 @@ static uint64_t arg_max_use = UINT64_MAX;
static int parse_config(void) {
static const ConfigTableItem items[] = {
- { "Coredump", "Storage", config_parse_coredump_storage, 0, &arg_storage },
- { "Coredump", "Compress", config_parse_bool, 0, &arg_compress },
- { "Coredump", "ProcessSizeMax", config_parse_iec_uint64, 0, &arg_process_size_max },
- { "Coredump", "ExternalSizeMax", config_parse_iec_uint64_infinity, 0, &arg_external_size_max },
- { "Coredump", "JournalSizeMax", config_parse_iec_size, 0, &arg_journal_size_max },
- { "Coredump", "KeepFree", config_parse_iec_uint64, 0, &arg_keep_free },
- { "Coredump", "MaxUse", config_parse_iec_uint64, 0, &arg_max_use },
+ { "Coredump", "Storage", config_parse_coredump_storage, 0, &arg_storage },
+ { "Coredump", "Compress", config_parse_bool, 0, &arg_compress },
+ { "Coredump", "ProcessSizeMax", config_parse_iec_uint64, 0, &arg_process_size_max },
+ { "Coredump", "ExternalSizeMax", config_parse_iec_uint64_infinity, 0, &arg_external_size_max },
+ { "Coredump", "JournalSizeMax", config_parse_iec_size, 0, &arg_journal_size_max },
+ { "Coredump", "KeepFree", config_parse_iec_uint64, 0, &arg_keep_free },
+ { "Coredump", "MaxUse", config_parse_iec_uint64, 0, &arg_max_use },
{}
};
@@ -208,15 +208,15 @@ static int fix_acl(int fd, uid_t uid) {
static int fix_xattr(int fd, const Context *context) {
static const char * const xattrs[_META_MAX] = {
- [META_ARGV_PID] = "user.coredump.pid",
- [META_ARGV_UID] = "user.coredump.uid",
- [META_ARGV_GID] = "user.coredump.gid",
- [META_ARGV_SIGNAL] = "user.coredump.signal",
- [META_ARGV_TIMESTAMP] = "user.coredump.timestamp",
- [META_ARGV_RLIMIT] = "user.coredump.rlimit",
- [META_ARGV_HOSTNAME] = "user.coredump.hostname",
- [META_COMM] = "user.coredump.comm",
- [META_EXE] = "user.coredump.exe",
+ [META_ARGV_PID] = "user.coredump.pid",
+ [META_ARGV_UID] = "user.coredump.uid",
+ [META_ARGV_GID] = "user.coredump.gid",
+ [META_ARGV_SIGNAL] = "user.coredump.signal",
+ [META_ARGV_TIMESTAMP] = "user.coredump.timestamp",
+ [META_ARGV_RLIMIT] = "user.coredump.rlimit",
+ [META_ARGV_HOSTNAME] = "user.coredump.hostname",
+ [META_COMM] = "user.coredump.comm",
+ [META_EXE] = "user.coredump.exe",
};
int r = 0;

View File

@ -0,0 +1,383 @@
From e86a03c4f201745a683cfe1549a202d5ae636b07 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Mon, 28 Nov 2022 12:12:55 +0100
Subject: [PATCH] coredump: do not allow user to access coredumps with changed
uid/gid/capabilities
When the user starts a program which elevates its permissions via setuid,
setgid, or capabilities set on the file, it may access additional information
which would then be visible in the coredump. We shouldn't make the the coredump
visible to the user in such cases.
Reported-by: Matthias Gerstner <mgerstner@suse.de>
This reads the /proc/<pid>/auxv file and attaches it to the process metadata as
PROC_AUXV. Before the coredump is submitted, it is parsed and if either
at_secure was set (which the kernel will do for processes that are setuid,
setgid, or setcap), or if the effective uid/gid don't match uid/gid, the file
is not made accessible to the user. If we can't access this data, we assume the
file should not be made accessible either. In principle we could also access
the auxv data from a note in the core file, but that is much more complex and
it seems better to use the stand-alone file that is provided by the kernel.
Attaching auxv is both convient for this patch (because this way it's passed
between the stages along with other fields), but I think it makes sense to save
it in general.
We use the information early in the core file to figure out if the program was
32-bit or 64-bit and its endianness. This way we don't need heuristics to guess
whether the format of the auxv structure. This test might reject some cases on
fringe architecutes. But the impact would be limited: we just won't grant the
user permissions to view the coredump file. If people report that we're missing
some cases, we can always enhance this to support more architectures.
I tested auxv parsing on amd64, 32-bit program on amd64, arm64, arm32, and
ppc64el, but not the whole coredump handling.
(cherry picked from commit 3e4d0f6cf99f8677edd6a237382a65bfe758de03)
Resolves: #2155517
---
src/basic/io-util.h | 9 ++
src/coredump/coredump.c | 196 +++++++++++++++++++++++++++++++++++++---
2 files changed, 192 insertions(+), 13 deletions(-)
diff --git a/src/basic/io-util.h b/src/basic/io-util.h
index 39728e06bc..3afb134266 100644
--- a/src/basic/io-util.h
+++ b/src/basic/io-util.h
@@ -91,7 +91,16 @@ struct iovec_wrapper *iovw_new(void);
struct iovec_wrapper *iovw_free(struct iovec_wrapper *iovw);
struct iovec_wrapper *iovw_free_free(struct iovec_wrapper *iovw);
void iovw_free_contents(struct iovec_wrapper *iovw, bool free_vectors);
+
int iovw_put(struct iovec_wrapper *iovw, void *data, size_t len);
+static inline int iovw_consume(struct iovec_wrapper *iovw, void *data, size_t len) {
+ /* Move data into iovw or free on error */
+ int r = iovw_put(iovw, data, len);
+ if (r < 0)
+ free(data);
+ return r;
+}
+
int iovw_put_string_field(struct iovec_wrapper *iovw, const char *field, const char *value);
int iovw_put_string_field_free(struct iovec_wrapper *iovw, const char *field, char *value);
void iovw_rebase(struct iovec_wrapper *iovw, char *old, char *new);
diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c
index 7a181bdeeb..ea3d8c415a 100644
--- a/src/coredump/coredump.c
+++ b/src/coredump/coredump.c
@@ -4,6 +4,7 @@
#include <stdio.h>
#include <sys/prctl.h>
#include <sys/statvfs.h>
+#include <sys/auxv.h>
#include <sys/xattr.h>
#include <unistd.h>
@@ -106,6 +107,7 @@ enum {
META_EXE = _META_MANDATORY_MAX,
META_UNIT,
+ META_PROC_AUXV,
_META_MAX
};
@@ -120,10 +122,12 @@ static const char * const meta_field_names[_META_MAX] = {
[META_COMM] = "COREDUMP_COMM=",
[META_EXE] = "COREDUMP_EXE=",
[META_UNIT] = "COREDUMP_UNIT=",
+ [META_PROC_AUXV] = "COREDUMP_PROC_AUXV=",
};
typedef struct Context {
const char *meta[_META_MAX];
+ size_t meta_size[_META_MAX];
pid_t pid;
bool is_pid1;
bool is_journald;
@@ -185,13 +189,16 @@ static uint64_t storage_size_max(void) {
return 0;
}
-static int fix_acl(int fd, uid_t uid) {
+static int fix_acl(int fd, uid_t uid, bool allow_user) {
+ assert(fd >= 0);
+ assert(uid_is_valid(uid));
#if HAVE_ACL
int r;
- assert(fd >= 0);
- assert(uid_is_valid(uid));
+ /* We don't allow users to read coredumps if the uid or capabilities were changed. */
+ if (!allow_user)
+ return 0;
if (uid_is_system(uid) || uid_is_dynamic(uid) || uid == UID_NOBODY)
return 0;
@@ -251,7 +258,8 @@ static int fix_permissions(
const char *filename,
const char *target,
const Context *context,
- uid_t uid) {
+ uid_t uid,
+ bool allow_user) {
int r;
@@ -261,7 +269,7 @@ static int fix_permissions(
/* Ignore errors on these */
(void) fchmod(fd, 0640);
- (void) fix_acl(fd, uid);
+ (void) fix_acl(fd, uid, allow_user);
(void) fix_xattr(fd, context);
r = fsync_full(fd);
@@ -331,6 +339,153 @@ static int make_filename(const Context *context, char **ret) {
return 0;
}
+static int parse_auxv64(
+ const uint64_t *auxv,
+ size_t size_bytes,
+ int *at_secure,
+ uid_t *uid,
+ uid_t *euid,
+ gid_t *gid,
+ gid_t *egid) {
+
+ assert(auxv || size_bytes == 0);
+
+ if (size_bytes % (2 * sizeof(uint64_t)) != 0)
+ return log_warning_errno(SYNTHETIC_ERRNO(EIO), "Incomplete auxv structure (%zu bytes).", size_bytes);
+
+ size_t words = size_bytes / sizeof(uint64_t);
+
+ /* Note that we set output variables even on error. */
+
+ for (size_t i = 0; i + 1 < words; i += 2)
+ switch (auxv[i]) {
+ case AT_SECURE:
+ *at_secure = auxv[i + 1] != 0;
+ break;
+ case AT_UID:
+ *uid = auxv[i + 1];
+ break;
+ case AT_EUID:
+ *euid = auxv[i + 1];
+ break;
+ case AT_GID:
+ *gid = auxv[i + 1];
+ break;
+ case AT_EGID:
+ *egid = auxv[i + 1];
+ break;
+ case AT_NULL:
+ if (auxv[i + 1] != 0)
+ goto error;
+ return 0;
+ }
+ error:
+ return log_warning_errno(SYNTHETIC_ERRNO(ENODATA),
+ "AT_NULL terminator not found, cannot parse auxv structure.");
+}
+
+static int parse_auxv32(
+ const uint32_t *auxv,
+ size_t size_bytes,
+ int *at_secure,
+ uid_t *uid,
+ uid_t *euid,
+ gid_t *gid,
+ gid_t *egid) {
+
+ assert(auxv || size_bytes == 0);
+
+ size_t words = size_bytes / sizeof(uint32_t);
+
+ if (size_bytes % (2 * sizeof(uint32_t)) != 0)
+ return log_warning_errno(SYNTHETIC_ERRNO(EIO), "Incomplete auxv structure (%zu bytes).", size_bytes);
+
+ /* Note that we set output variables even on error. */
+
+ for (size_t i = 0; i + 1 < words; i += 2)
+ switch (auxv[i]) {
+ case AT_SECURE:
+ *at_secure = auxv[i + 1] != 0;
+ break;
+ case AT_UID:
+ *uid = auxv[i + 1];
+ break;
+ case AT_EUID:
+ *euid = auxv[i + 1];
+ break;
+ case AT_GID:
+ *gid = auxv[i + 1];
+ break;
+ case AT_EGID:
+ *egid = auxv[i + 1];
+ break;
+ case AT_NULL:
+ if (auxv[i + 1] != 0)
+ goto error;
+ return 0;
+ }
+ error:
+ return log_warning_errno(SYNTHETIC_ERRNO(ENODATA),
+ "AT_NULL terminator not found, cannot parse auxv structure.");
+}
+
+static int grant_user_access(int core_fd, const Context *context) {
+ int at_secure = -1;
+ uid_t uid = UID_INVALID, euid = UID_INVALID;
+ uid_t gid = GID_INVALID, egid = GID_INVALID;
+ int r;
+
+ assert(core_fd >= 0);
+ assert(context);
+
+ if (!context->meta[META_PROC_AUXV])
+ return log_warning_errno(SYNTHETIC_ERRNO(ENODATA), "No auxv data, not adjusting permissions.");
+
+ uint8_t elf[EI_NIDENT];
+ errno = 0;
+ if (pread(core_fd, &elf, sizeof(elf), 0) != sizeof(elf))
+ return log_warning_errno(errno_or_else(EIO),
+ "Failed to pread from coredump fd: %s", STRERROR_OR_EOF(errno));
+
+ if (elf[EI_MAG0] != ELFMAG0 ||
+ elf[EI_MAG1] != ELFMAG1 ||
+ elf[EI_MAG2] != ELFMAG2 ||
+ elf[EI_MAG3] != ELFMAG3 ||
+ elf[EI_VERSION] != EV_CURRENT)
+ return log_info_errno(SYNTHETIC_ERRNO(EUCLEAN),
+ "Core file does not have ELF header, not adjusting permissions.");
+ if (!IN_SET(elf[EI_CLASS], ELFCLASS32, ELFCLASS64) ||
+ !IN_SET(elf[EI_DATA], ELFDATA2LSB, ELFDATA2MSB))
+ return log_info_errno(SYNTHETIC_ERRNO(EUCLEAN),
+ "Core file has strange ELF class, not adjusting permissions.");
+
+ if ((elf[EI_DATA] == ELFDATA2LSB) != (__BYTE_ORDER == __LITTLE_ENDIAN))
+ return log_info_errno(SYNTHETIC_ERRNO(EUCLEAN),
+ "Core file has non-native endianness, not adjusting permissions.");
+
+ if (elf[EI_CLASS] == ELFCLASS64)
+ r = parse_auxv64((const uint64_t*) context->meta[META_PROC_AUXV],
+ context->meta_size[META_PROC_AUXV],
+ &at_secure, &uid, &euid, &gid, &egid);
+ else
+ r = parse_auxv32((const uint32_t*) context->meta[META_PROC_AUXV],
+ context->meta_size[META_PROC_AUXV],
+ &at_secure, &uid, &euid, &gid, &egid);
+ if (r < 0)
+ return r;
+
+ /* We allow access if we got all the data and at_secure is not set and
+ * the uid/gid matches euid/egid. */
+ bool ret =
+ at_secure == 0 &&
+ uid != UID_INVALID && euid != UID_INVALID && uid == euid &&
+ gid != GID_INVALID && egid != GID_INVALID && gid == egid;
+ log_debug("Will %s access (uid="UID_FMT " euid="UID_FMT " gid="GID_FMT " egid="GID_FMT " at_secure=%s)",
+ ret ? "permit" : "restrict",
+ uid, euid, gid, egid, yes_no(at_secure));
+ return ret;
+}
+
static int save_external_coredump(
const Context *context,
int input_fd,
@@ -453,6 +608,8 @@ static int save_external_coredump(
context->meta[META_ARGV_PID], context->meta[META_COMM]);
truncated = r == 1;
+ bool allow_user = grant_user_access(fd, context) > 0;
+
#if HAVE_COMPRESSION
if (arg_compress) {
_cleanup_(unlink_and_freep) char *tmp_compressed = NULL;
@@ -490,7 +647,7 @@ static int save_external_coredump(
uncompressed_size += partial_uncompressed_size;
}
- r = fix_permissions(fd_compressed, tmp_compressed, fn_compressed, context, uid);
+ r = fix_permissions(fd_compressed, tmp_compressed, fn_compressed, context, uid, allow_user);
if (r < 0)
return r;
@@ -517,7 +674,7 @@ static int save_external_coredump(
"SIZE_LIMIT=%"PRIu64, max_size,
"MESSAGE_ID=" SD_MESSAGE_TRUNCATED_CORE_STR);
- r = fix_permissions(fd, tmp, fn, context, uid);
+ r = fix_permissions(fd, tmp, fn, context, uid, allow_user);
if (r < 0)
return log_error_errno(r, "Failed to fix permissions and finalize coredump %s into %s: %m", coredump_tmpfile_name(tmp), fn);
@@ -765,7 +922,7 @@ static int change_uid_gid(const Context *context) {
}
static int submit_coredump(
- Context *context,
+ const Context *context,
struct iovec_wrapper *iovw,
int input_fd) {
@@ -944,16 +1101,15 @@ static int save_context(Context *context, const struct iovec_wrapper *iovw) {
struct iovec *iovec = iovw->iovec + n;
for (size_t i = 0; i < ELEMENTSOF(meta_field_names); i++) {
- char *p;
-
/* Note that these strings are NUL terminated, because we made sure that a
* trailing NUL byte is in the buffer, though not included in the iov_len
* count (see process_socket() and gather_pid_metadata_*()) */
assert(((char*) iovec->iov_base)[iovec->iov_len] == 0);
- p = startswith(iovec->iov_base, meta_field_names[i]);
+ const char *p = startswith(iovec->iov_base, meta_field_names[i]);
if (p) {
context->meta[i] = p;
+ context->meta_size[i] = iovec->iov_len - strlen(meta_field_names[i]);
break;
}
}
@@ -1190,6 +1346,7 @@ static int gather_pid_metadata(struct iovec_wrapper *iovw, Context *context) {
uid_t owner_uid;
pid_t pid;
char *t;
+ size_t size;
const char *p;
int r;
@@ -1254,13 +1411,26 @@ static int gather_pid_metadata(struct iovec_wrapper *iovw, Context *context) {
(void) iovw_put_string_field_free(iovw, "COREDUMP_PROC_LIMITS=", t);
p = procfs_file_alloca(pid, "cgroup");
- if (read_full_virtual_file(p, &t, NULL) >=0)
+ if (read_full_virtual_file(p, &t, NULL) >= 0)
(void) iovw_put_string_field_free(iovw, "COREDUMP_PROC_CGROUP=", t);
p = procfs_file_alloca(pid, "mountinfo");
- if (read_full_virtual_file(p, &t, NULL) >=0)
+ if (read_full_virtual_file(p, &t, NULL) >= 0)
(void) iovw_put_string_field_free(iovw, "COREDUMP_PROC_MOUNTINFO=", t);
+ /* We attach /proc/auxv here. ELF coredumps also contain a note for this (NT_AUXV), see elf(5). */
+ p = procfs_file_alloca(pid, "auxv");
+ if (read_full_virtual_file(p, &t, &size) >= 0) {
+ char *buf = malloc(strlen("COREDUMP_PROC_AUXV=") + size + 1);
+ if (buf) {
+ /* Add a dummy terminator to make save_context() happy. */
+ *((uint8_t*) mempcpy(stpcpy(buf, "COREDUMP_PROC_AUXV="), t, size)) = '\0';
+ (void) iovw_consume(iovw, buf, size + strlen("COREDUMP_PROC_AUXV="));
+ }
+
+ free(t);
+ }
+
if (get_process_cwd(pid, &t) >= 0)
(void) iovw_put_string_field_free(iovw, "COREDUMP_CWD=", t);

View File

@ -0,0 +1,43 @@
From eb9135c9499f6be627323929df48bc9efc93926a Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <fsumsal@redhat.com>
Date: Thu, 8 Dec 2022 10:56:42 +0100
Subject: [PATCH] Revert "basic: add fallback in chase_symlinks_and_opendir()
for cases when /proc is not mounted"
This reverts commit 47c0c5108b39d01283ba040c41d556b160d45a55.
Related: #2138081
---
src/basic/chase-symlinks.c | 14 +++-----------
1 file changed, 3 insertions(+), 11 deletions(-)
diff --git a/src/basic/chase-symlinks.c b/src/basic/chase-symlinks.c
index c09aab389e..afab54f067 100644
--- a/src/basic/chase-symlinks.c
+++ b/src/basic/chase-symlinks.c
@@ -466,22 +466,14 @@ int chase_symlinks_and_opendir(
return 0;
}
- r = chase_symlinks(path, root, chase_flags, &p, &path_fd);
+ r = chase_symlinks(path, root, chase_flags, ret_path ? &p : NULL, &path_fd);
if (r < 0)
return r;
assert(path_fd >= 0);
d = opendir(FORMAT_PROC_FD_PATH(path_fd));
- if (!d) {
- /* Hmm, we have the fd already but we got ENOENT, most likely /proc is not mounted.
- * Let's try opendir() again on the full path. */
- if (errno == ENOENT) {
- d = opendir(p);
- if (!d)
- return -errno;
- } else
- return -errno;
- }
+ if (!d)
+ return -errno;
if (ret_path)
*ret_path = TAKE_PTR(p);

View File

@ -0,0 +1,72 @@
From 008cc31066925ca8ef69ad6a03d20bb4ed299a41 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Fri, 2 Dec 2022 23:50:48 +0100
Subject: [PATCH] glyph-util: add warning sign special glyph
(cherry picked from commit 03c16b9784151275e71db3f9a25dc42206f1b5d3)
Related: #2138081
---
src/basic/glyph-util.c | 4 +++-
src/basic/glyph-util.h | 1 +
src/test/test-locale-util.c | 3 ++-
3 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/src/basic/glyph-util.c b/src/basic/glyph-util.c
index 67f2270daf..de1224f04f 100644
--- a/src/basic/glyph-util.c
+++ b/src/basic/glyph-util.c
@@ -71,6 +71,7 @@ const char *special_glyph(SpecialGlyph code) {
[SPECIAL_GLYPH_RECYCLING] = "~",
[SPECIAL_GLYPH_DOWNLOAD] = "\\",
[SPECIAL_GLYPH_SPARKLES] = "*",
+ [SPECIAL_GLYPH_WARNING_SIGN] = "!",
},
/* UTF-8 */
@@ -124,10 +125,11 @@ const char *special_glyph(SpecialGlyph code) {
/* This emoji is a single character cell glyph in Unicode, and two in ASCII */
[SPECIAL_GLYPH_TOUCH] = u8"👆", /* actually called: BACKHAND INDEX POINTING UP */
- /* These three emojis are single character cell glyphs in Unicode and also in ASCII. */
+ /* These four emojis are single character cell glyphs in Unicode and also in ASCII. */
[SPECIAL_GLYPH_RECYCLING] = u8"♻️", /* actually called: UNIVERSAL RECYCLNG SYMBOL */
[SPECIAL_GLYPH_DOWNLOAD] = u8"⤵️", /* actually called: RIGHT ARROW CURVING DOWN */
[SPECIAL_GLYPH_SPARKLES] = u8"✨",
+ [SPECIAL_GLYPH_WARNING_SIGN] = u8"⚠️",
},
};
diff --git a/src/basic/glyph-util.h b/src/basic/glyph-util.h
index 621d7a85b7..b64639622e 100644
--- a/src/basic/glyph-util.h
+++ b/src/basic/glyph-util.h
@@ -44,6 +44,7 @@ typedef enum SpecialGlyph {
SPECIAL_GLYPH_RECYCLING,
SPECIAL_GLYPH_DOWNLOAD,
SPECIAL_GLYPH_SPARKLES,
+ SPECIAL_GLYPH_WARNING_SIGN,
_SPECIAL_GLYPH_MAX,
_SPECIAL_GLYPH_INVALID = -EINVAL,
} SpecialGlyph;
diff --git a/src/test/test-locale-util.c b/src/test/test-locale-util.c
index 9f50c6227f..f38100401c 100644
--- a/src/test/test-locale-util.c
+++ b/src/test/test-locale-util.c
@@ -83,7 +83,7 @@ TEST(keymaps) {
#define dump_glyph(x) log_info(STRINGIFY(x) ": %s", special_glyph(x))
TEST(dump_special_glyphs) {
- assert_cc(SPECIAL_GLYPH_SPARKLES + 1 == _SPECIAL_GLYPH_MAX);
+ assert_cc(SPECIAL_GLYPH_WARNING_SIGN + 1 == _SPECIAL_GLYPH_MAX);
log_info("is_locale_utf8: %s", yes_no(is_locale_utf8()));
@@ -120,6 +120,7 @@ TEST(dump_special_glyphs) {
dump_glyph(SPECIAL_GLYPH_RECYCLING);
dump_glyph(SPECIAL_GLYPH_DOWNLOAD);
dump_glyph(SPECIAL_GLYPH_SPARKLES);
+ dump_glyph(SPECIAL_GLYPH_WARNING_SIGN);
}
DEFINE_TEST_MAIN(LOG_INFO);

View File

@ -0,0 +1,27 @@
From 2bd9f97275480842c99117123daab69cbb8f45f4 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Fri, 2 Dec 2022 23:50:57 +0100
Subject: [PATCH] chase-symlink: when converting directory O_PATH fd to real
fd, don't bother with /proc/
Replaces: #25581
(cherry picked from commit 2075b6dd394e09a0f203b9cc7e3253908397f933)
Related: #2138081
---
src/basic/chase-symlinks.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/basic/chase-symlinks.c b/src/basic/chase-symlinks.c
index afab54f067..ac55311f4d 100644
--- a/src/basic/chase-symlinks.c
+++ b/src/basic/chase-symlinks.c
@@ -471,7 +471,7 @@ int chase_symlinks_and_opendir(
return r;
assert(path_fd >= 0);
- d = opendir(FORMAT_PROC_FD_PATH(path_fd));
+ d = xopendirat(path_fd, ".", O_NOFOLLOW);
if (!d)
return -errno;

View File

@ -0,0 +1,39 @@
From d98adab06485b0da23294f8a5db4f94b40988e2a Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Fri, 2 Dec 2022 23:52:12 +0100
Subject: [PATCH] systemctl: print a clear warning if people invoke systemctl
without /proc/
(cherry picked from commit 0f958c8d4fc13ed1c1af928b2a7d91d31c7576eb)
Related: #2138081
---
src/systemctl/systemctl.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 5858c3f6d3..91954d91e6 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -20,6 +20,7 @@
#include "rlimit-util.h"
#include "sigbus.h"
#include "signal-util.h"
+#include "stat-util.h"
#include "string-table.h"
#include "systemctl-add-dependency.h"
#include "systemctl-cancel-job.h"
@@ -1146,6 +1147,13 @@ static int run(int argc, char *argv[]) {
if (r <= 0)
goto finish;
+ if (proc_mounted() == 0)
+ log_warning("%s%s/proc/ is not mounted. This is not a supported mode of operation. Please fix\n"
+ "your invocation environment to mount /proc/ and /sys/ properly. Proceeding anyway.\n"
+ "Your mileage may vary.",
+ emoji_enabled() ? special_glyph(SPECIAL_GLYPH_WARNING_SIGN) : "",
+ emoji_enabled() ? " " : "");
+
if (arg_action != ACTION_SYSTEMCTL && running_in_chroot() > 0) {
if (!arg_quiet)
log_info("Running in chroot, ignoring request.");

View File

@ -0,0 +1,48 @@
From 3be1c0fa543f024319a03e89decedc6106cb4e02 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Mon, 5 Dec 2022 13:52:28 +0100
Subject: [PATCH] TEST-65: check cat-config operation in chroot
This verifies the fix in 2075b6dd394e09a0f203b9cc7e3253908397f933.
(cherry picked from commit a7eed3eca3d7bc022d870258deb2f738b9527c6d)
Related: #2138081
---
test/test-functions | 1 +
test/units/testsuite-65.sh | 10 ++++++++++
2 files changed, 11 insertions(+)
diff --git a/test/test-functions b/test/test-functions
index 194cd682bb..94e11a686a 100644
--- a/test/test-functions
+++ b/test/test-functions
@@ -158,6 +158,7 @@ BASICTOOLS=(
cat
chmod
chown
+ chroot
cmp
cryptsetup
cut
diff --git a/test/units/testsuite-65.sh b/test/units/testsuite-65.sh
index 1f34308b44..ebe1f57b52 100755
--- a/test/units/testsuite-65.sh
+++ b/test/units/testsuite-65.sh
@@ -139,6 +139,16 @@ systemd-analyze cat-config systemd/system.conf systemd/journald.conf >/dev/null
systemd-analyze cat-config systemd/system.conf foo/bar systemd/journald.conf >/dev/null
systemd-analyze cat-config foo/bar
+if [[ ! -v ASAN_OPTIONS ]]; then
+ # check that systemd-analyze cat-config paths work in a chroot
+ mkdir -p /tmp/root
+ mount --bind / /tmp/root
+ systemd-analyze cat-config systemd/system-preset >/tmp/out1
+ chroot /tmp/root systemd-analyze cat-config systemd/system-preset >/tmp/out2
+ diff /tmp/out{1,2}
+fi
+
+# verify
mkdir -p /tmp/img/usr/lib/systemd/system/
mkdir -p /tmp/img/opt/

View File

@ -0,0 +1,64 @@
From fa44b8d1e6b0d5e0ef4dfcb01e26e7907068bfa3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Wed, 7 Dec 2022 09:52:35 +0100
Subject: [PATCH] TEST-65: use [[ -v ]] more
It's a bashism, but we use other bash features anyway, and it's cleaner
and much less verbose.
(cherry picked from commit 1f9caf28cafbec89b93b8e6b641d387ac5acdd24)
Related: #2138081
---
test/units/testsuite-64.sh | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/test/units/testsuite-64.sh b/test/units/testsuite-64.sh
index 7673036335..fd1ad7c041 100755
--- a/test/units/testsuite-64.sh
+++ b/test/units/testsuite-64.sh
@@ -192,7 +192,7 @@ testcase_nvme_subsystem() {
testcase_virtio_scsi_identically_named_partitions() {
local num
- if [[ -n "${ASAN_OPTIONS:-}" ]] || [[ "$(systemd-detect-virt -v)" == "qemu" ]]; then
+ if [[ -v ASAN_OPTIONS || "$(systemd-detect-virt -v)" == "qemu" ]]; then
num=$((4 * 4))
else
num=$((16 * 8))
@@ -305,7 +305,7 @@ testcase_simultaneous_events() {
local -a devices symlinks
local -A running
- if [[ -n "${ASAN_OPTIONS:-}" ]] || [[ "$(systemd-detect-virt -v)" == "qemu" ]]; then
+ if [[ -v ASAN_OPTIONS || "$(systemd-detect-virt -v)" == "qemu" ]]; then
num_part=2
iterations=10
timeout=240
@@ -400,7 +400,7 @@ testcase_lvm_basic() {
/dev/disk/by-id/ata-foobar_deadbeeflvm{0..3}
)
- if [[ -n "${ASAN_OPTIONS:-}" ]] || [[ "$(systemd-detect-virt -v)" == "qemu" ]]; then
+ if [[ -v ASAN_OPTIONS || "$(systemd-detect-virt -v)" == "qemu" ]]; then
timeout=180
else
timeout=30
@@ -453,7 +453,7 @@ testcase_lvm_basic() {
helper_check_device_units
# Same as above, but now with more "stress"
- if [[ -n "${ASAN_OPTIONS:-}" ]] || [[ "$(systemd-detect-virt -v)" == "qemu" ]]; then
+ if [[ -v ASAN_OPTIONS || "$(systemd-detect-virt -v)" == "qemu" ]]; then
iterations=10
else
iterations=50
@@ -478,7 +478,7 @@ testcase_lvm_basic() {
helper_check_device_units
# Create & remove LVs in a loop, i.e. with more "stress"
- if [[ -n "${ASAN_OPTIONS:-}" ]]; then
+ if [[ -v ASAN_OPTIONS ]]; then
iterations=8
partitions=16
elif [[ "$(systemd-detect-virt -v)" == "qemu" ]]; then

View File

@ -0,0 +1,227 @@
From 201c651eaaf886064987272cc88b03995fd2715d Mon Sep 17 00:00:00 2001
From: Mike Yuan <me@yhndnzj.com>
Date: Fri, 18 Nov 2022 15:43:34 +0800
Subject: [PATCH] systemctl: warn if trying to disable a unit with no install
info
Trying to disable a unit with no install info is mostly useless, so
adding a warning like we do for enable (with the new dbus method
'DisableUnitFilesWithFlagsAndInstallInfo()'). Note that it would
still find and remove symlinks to the unit in /etc, regardless of
whether it has install info or not, just like before. And if there are
actually files to remove, we suppress the warning.
Fixes #17689
(cherry picked from commit bf1bea43f15b04152a3948702ba1695a0835c2bf)
Related: #2141979
---
man/org.freedesktop.systemd1.xml | 13 ++++++++++++-
src/core/dbus-manager.c | 21 ++++++++++++++++-----
src/shared/install.c | 21 +++++++++++++++++----
src/systemctl/systemctl-enable.c | 15 ++++++++++-----
4 files changed, 55 insertions(+), 15 deletions(-)
diff --git a/man/org.freedesktop.systemd1.xml b/man/org.freedesktop.systemd1.xml
index 5e08b35234..c2f70870c7 100644
--- a/man/org.freedesktop.systemd1.xml
+++ b/man/org.freedesktop.systemd1.xml
@@ -209,6 +209,10 @@ node /org/freedesktop/systemd1 {
DisableUnitFilesWithFlags(in as files,
in t flags,
out a(sss) changes);
+ DisableUnitFilesWithFlagsAndInstallInfo(in as files,
+ in t flags,
+ out b carries_install_info,
+ out a(sss) changes);
ReenableUnitFiles(in as files,
in b runtime,
in b force,
@@ -916,6 +920,8 @@ node /org/freedesktop/systemd1 {
<variablelist class="dbus-method" generated="True" extra-ref="DisableUnitFilesWithFlags()"/>
+ <variablelist class="dbus-method" generated="True" extra-ref="DisableUnitFilesWithFlagsAndInstallInfo()"/>
+
<variablelist class="dbus-method" generated="True" extra-ref="ReenableUnitFiles()"/>
<variablelist class="dbus-method" generated="True" extra-ref="LinkUnitFiles()"/>
@@ -1417,7 +1423,7 @@ node /org/freedesktop/systemd1 {
enabled for runtime only (true, <filename>/run/</filename>), or persistently (false,
<filename>/etc/</filename>). The second one controls whether symlinks pointing to other units shall be
replaced if necessary. This method returns one boolean and an array of the changes made. The boolean
- signals whether the unit files contained any enablement information (i.e. an [Install]) section. The
+ signals whether the unit files contained any enablement information (i.e. an [Install] section). The
changes array consists of structures with three strings: the type of the change (one of
<literal>symlink</literal> or <literal>unlink</literal>), the file name of the symlink and the
destination of the symlink. Note that most of the following calls return a changes list in the same
@@ -1440,6 +1446,11 @@ node /org/freedesktop/systemd1 {
replaced if necessary. <varname>SD_SYSTEMD_UNIT_PORTABLE</varname> will add or remove the symlinks in
<filename>/etc/systemd/system.attached</filename> and <filename>/run/systemd/system.attached</filename>.</para>
+ <para><function>DisableUnitFilesWithFlagsAndInstallInfo()</function> is similar to
+ <function>DisableUnitFilesWithFlags()</function> and takes the same arguments, but returns
+ a boolean to indicate whether the unit files contain any enablement information, like
+ <function>EnableUnitFiles()</function>. The changes made are still returned in an array.</para>
+
<para>Similarly, <function>ReenableUnitFiles()</function> applies the changes to one or more units that
would result from disabling and enabling the unit quickly one after the other in an atomic
fashion. This is useful to apply updated [Install] information contained in unit files.</para>
diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
index 88f098ec86..2db12721a1 100644
--- a/src/core/dbus-manager.c
+++ b/src/core/dbus-manager.c
@@ -2425,6 +2425,7 @@ static int method_disable_unit_files_generic(
sd_bus_message *message,
Manager *m,
int (*call)(LookupScope scope, UnitFileFlags flags, const char *root_dir, char *files[], InstallChange **changes, size_t *n_changes),
+ bool carries_install_info,
sd_bus_error *error) {
_cleanup_strv_free_ char **l = NULL;
@@ -2440,7 +2441,8 @@ static int method_disable_unit_files_generic(
if (r < 0)
return r;
- if (sd_bus_message_is_method_call(message, NULL, "DisableUnitFilesWithFlags")) {
+ if (sd_bus_message_is_method_call(message, NULL, "DisableUnitFilesWithFlags") ||
+ sd_bus_message_is_method_call(message, NULL, "DisableUnitFilesWithFlagsAndInstallInfo")) {
uint64_t raw_flags;
r = sd_bus_message_read(message, "t", &raw_flags);
@@ -2469,19 +2471,23 @@ static int method_disable_unit_files_generic(
if (r < 0)
return install_error(error, r, changes, n_changes);
- return reply_install_changes_and_free(m, message, -1, changes, n_changes, error);
+ return reply_install_changes_and_free(m, message, carries_install_info ? r : -1, changes, n_changes, error);
}
static int method_disable_unit_files_with_flags(sd_bus_message *message, void *userdata, sd_bus_error *error) {
- return method_disable_unit_files_generic(message, userdata, unit_file_disable, error);
+ return method_disable_unit_files_generic(message, userdata, unit_file_disable, /* carries_install_info = */ false, error);
+}
+
+static int method_disable_unit_files_with_flags_and_install_info(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ return method_disable_unit_files_generic(message, userdata, unit_file_disable, /* carries_install_info = */ true, error);
}
static int method_disable_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
- return method_disable_unit_files_generic(message, userdata, unit_file_disable, error);
+ return method_disable_unit_files_generic(message, userdata, unit_file_disable, /* carries_install_info = */ false, error);
}
static int method_unmask_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
- return method_disable_unit_files_generic(message, userdata, unit_file_unmask, error);
+ return method_disable_unit_files_generic(message, userdata, unit_file_unmask, /* carries_install_info = */ false, error);
}
static int method_revert_unit_files(sd_bus_message *message, void *userdata, sd_bus_error *error) {
@@ -3194,6 +3200,11 @@ const sd_bus_vtable bus_manager_vtable[] = {
SD_BUS_RESULT("a(sss)", changes),
method_disable_unit_files_with_flags,
SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("DisableUnitFilesWithFlagsAndInstallInfo",
+ SD_BUS_ARGS("as", files, "t", flags),
+ SD_BUS_RESULT("b", carries_install_info, "a(sss)", changes),
+ method_disable_unit_files_with_flags_and_install_info,
+ SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD_WITH_ARGS("ReenableUnitFiles",
SD_BUS_ARGS("as", files, "b", runtime, "b", force),
SD_BUS_RESULT("b", carries_install_info, "a(sss)", changes),
diff --git a/src/shared/install.c b/src/shared/install.c
index 834a1c59e3..4b610b20a5 100644
--- a/src/shared/install.c
+++ b/src/shared/install.c
@@ -2790,25 +2790,38 @@ static int do_unit_file_disable(
_cleanup_(install_context_done) InstallContext ctx = { .scope = scope };
_cleanup_set_free_free_ Set *remove_symlinks_to = NULL;
+ InstallInfo *info;
+ bool has_install_info = false;
int r;
STRV_FOREACH(name, names) {
if (!unit_name_is_valid(*name, UNIT_NAME_ANY))
return install_changes_add(changes, n_changes, -EUCLEAN, *name, NULL);
- r = install_info_add(&ctx, *name, NULL, lp->root_dir, /* auxiliary= */ false, NULL);
+ r = install_info_add(&ctx, *name, NULL, lp->root_dir, /* auxiliary= */ false, &info);
+ if (r >= 0)
+ r = install_info_traverse(&ctx, lp, info, SEARCH_LOAD|SEARCH_FOLLOW_CONFIG_SYMLINKS, NULL);
+
if (r < 0)
- return r;
+ return install_changes_add(changes, n_changes, r, *name, NULL);
+
+ /* If we enable multiple units, some with install info and others without,
+ * the "empty [Install] section" warning is not shown. Let's make the behavior
+ * of disable align with that. */
+ has_install_info = has_install_info || install_info_has_rules(info) || install_info_has_also(info);
}
r = install_context_mark_for_removal(&ctx, lp, &remove_symlinks_to, config_path, changes, n_changes);
+ if (r >= 0)
+ r = remove_marked_symlinks(remove_symlinks_to, config_path, lp, flags & UNIT_FILE_DRY_RUN, changes, n_changes);
+
if (r < 0)
return r;
- return remove_marked_symlinks(remove_symlinks_to, config_path, lp, flags & UNIT_FILE_DRY_RUN, changes, n_changes);
+ /* The warning is shown only if it's a no-op */
+ return install_changes_have_modification(*changes, *n_changes) || has_install_info;
}
-
int unit_file_disable(
LookupScope scope,
UnitFileFlags flags,
diff --git a/src/systemctl/systemctl-enable.c b/src/systemctl/systemctl-enable.c
index 5be4c0c725..aea66872de 100644
--- a/src/systemctl/systemctl-enable.c
+++ b/src/systemctl/systemctl-enable.c
@@ -109,9 +109,10 @@ int verb_enable(int argc, char *argv[], void *userdata) {
if (streq(verb, "enable")) {
r = unit_file_enable(arg_scope, flags, arg_root, names, &changes, &n_changes);
carries_install_info = r;
- } else if (streq(verb, "disable"))
+ } else if (streq(verb, "disable")) {
r = unit_file_disable(arg_scope, flags, arg_root, names, &changes, &n_changes);
- else if (streq(verb, "reenable")) {
+ carries_install_info = r;
+ } else if (streq(verb, "reenable")) {
r = unit_file_reenable(arg_scope, flags, arg_root, names, &changes, &n_changes);
carries_install_info = r;
} else if (streq(verb, "link"))
@@ -165,7 +166,8 @@ int verb_enable(int argc, char *argv[], void *userdata) {
method = "EnableUnitFiles";
expect_carries_install_info = true;
} else if (streq(verb, "disable")) {
- method = "DisableUnitFiles";
+ method = "DisableUnitFilesWithFlagsAndInstallInfo";
+ expect_carries_install_info = true;
send_force = false;
} else if (streq(verb, "reenable")) {
method = "ReenableUnitFiles";
@@ -208,7 +210,10 @@ int verb_enable(int argc, char *argv[], void *userdata) {
}
if (send_runtime) {
- r = sd_bus_message_append(m, "b", arg_runtime);
+ if (streq(method, "DisableUnitFilesWithFlagsAndInstallInfo"))
+ r = sd_bus_message_append(m, "t", arg_runtime ? UNIT_FILE_RUNTIME : 0);
+ else
+ r = sd_bus_message_append(m, "b", arg_runtime);
if (r < 0)
return bus_log_create_error(r);
}
@@ -245,7 +250,7 @@ int verb_enable(int argc, char *argv[], void *userdata) {
if (carries_install_info == 0 && !ignore_carries_install_info)
log_notice("The unit files have no installation config (WantedBy=, RequiredBy=, Also=,\n"
"Alias= settings in the [Install] section, and DefaultInstance= for template\n"
- "units). This means they are not meant to be enabled using systemctl.\n"
+ "units). This means they are not meant to be enabled or disabled using systemctl.\n"
" \n" /* trick: the space is needed so that the line does not get stripped from output */
"Possible reasons for having this kind of units are:\n"
"%1$s A unit may be statically enabled by being symlinked from another unit's\n"

View File

@ -0,0 +1,136 @@
From 79c16ad7a09623b987a50a0d04a61fed41e45a77 Mon Sep 17 00:00:00 2001
From: Mike Yuan <me@yhndnzj.com>
Date: Sun, 27 Nov 2022 21:18:44 +0800
Subject: [PATCH] systemctl: allow suppress the warning of no install info
using --no-warn
In cases like packaging scripts, it might be desired to use
enable/disable on units without install info. So, adding an
option '--no-warn' to suppress the warning.
(cherry picked from commit 108d35ac7d435b4f1378a9c0fa50858263475e09)
Related: #2141979
---
man/systemctl.xml | 18 ++++++++++++++++--
src/systemctl/systemctl-enable.c | 2 +-
src/systemctl/systemctl.c | 9 +++++++++
src/systemctl/systemctl.h | 1 +
4 files changed, 27 insertions(+), 3 deletions(-)
diff --git a/man/systemctl.xml b/man/systemctl.xml
index f743c182fe..d909dc4db4 100644
--- a/man/systemctl.xml
+++ b/man/systemctl.xml
@@ -771,6 +771,9 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
account.
</para>
+ <para>When using this operation on units without install information, a warning about it is shown.
+ <option>--no-warn</option> can be used to suppress the warning.</para>
+
<para>Enabling units should not be confused with starting (activating) units, as done by the
<command>start</command> command. Enabling and starting units is orthogonal: units may be enabled without
being started and started without being enabled. Enabling simply hooks the unit into various suggested
@@ -814,8 +817,8 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
executed. This output may be suppressed by passing <option>--quiet</option>.
</para>
- <para>This command honors <option>--system</option>, <option>--user</option>, <option>--runtime</option>
- and <option>--global</option> in a similar way as <command>enable</command>.</para>
+ <para>This command honors <option>--system</option>, <option>--user</option>, <option>--runtime</option>,
+ <option>--global</option> and <option>--no-warn</option> in a similar way as <command>enable</command>.</para>
</listitem>
</varlistentry>
@@ -1997,6 +2000,17 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><option>--no-warn</option></term>
+
+ <listitem>
+ <para>Don't generate the warning shown by default when using
+ <command>enable</command> or <command>disable</command> on units
+ without install information (i.e. don't have or have an empty
+ [Install] section).</para>
+ </listitem>
+ </varlistentry>
+
<varlistentry>
<term><option>--no-block</option></term>
diff --git a/src/systemctl/systemctl-enable.c b/src/systemctl/systemctl-enable.c
index aea66872de..86d9f602fa 100644
--- a/src/systemctl/systemctl-enable.c
+++ b/src/systemctl/systemctl-enable.c
@@ -67,7 +67,7 @@ int verb_enable(int argc, char *argv[], void *userdata) {
InstallChange *changes = NULL;
size_t n_changes = 0;
int carries_install_info = -1;
- bool ignore_carries_install_info = arg_quiet;
+ bool ignore_carries_install_info = arg_quiet || arg_no_warn;
int r;
if (!argv[1])
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 91954d91e6..57e9966d3c 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -83,6 +83,7 @@ bool arg_show_types = false;
int arg_check_inhibitors = -1;
bool arg_dry_run = false;
bool arg_quiet = false;
+bool arg_no_warn = false;
bool arg_full = false;
bool arg_recursive = false;
bool arg_with_dependencies = false;
@@ -276,6 +277,8 @@ static int systemctl_help(void) {
" kexec, suspend, hibernate, suspend-then-hibernate,\n"
" hybrid-sleep, default, rescue, emergency, and exit.\n"
" -q --quiet Suppress output\n"
+ " --no-warn Don't generate warning when trying to enable/disable\n"
+ " units without install information\n"
" --wait For (re)start, wait until service stopped again\n"
" For is-system-running, wait until startup is completed\n"
" --no-block Do not wait until operation finished\n"
@@ -432,6 +435,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
ARG_READ_ONLY,
ARG_MKDIR,
ARG_MARKED,
+ ARG_NO_WARN,
};
static const struct option options[] = {
@@ -464,6 +468,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
{ "no-wall", no_argument, NULL, ARG_NO_WALL },
{ "dry-run", no_argument, NULL, ARG_DRY_RUN },
{ "quiet", no_argument, NULL, 'q' },
+ { "no-warn", no_argument, NULL, ARG_NO_WARN },
{ "root", required_argument, NULL, ARG_ROOT },
{ "image", required_argument, NULL, ARG_IMAGE },
{ "force", no_argument, NULL, 'f' },
@@ -925,6 +930,10 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
arg_marked = true;
break;
+ case ARG_NO_WARN:
+ arg_no_warn = true;
+ break;
+
case '.':
/* Output an error mimicking getopt, and print a hint afterwards */
log_error("%s: invalid option -- '.'", program_invocation_name);
diff --git a/src/systemctl/systemctl.h b/src/systemctl/systemctl.h
index 2454c4c714..1a7a6e28d3 100644
--- a/src/systemctl/systemctl.h
+++ b/src/systemctl/systemctl.h
@@ -65,6 +65,7 @@ extern bool arg_show_types;
extern int arg_check_inhibitors;
extern bool arg_dry_run;
extern bool arg_quiet;
+extern bool arg_no_warn;
extern bool arg_full;
extern bool arg_recursive;
extern bool arg_with_dependencies;

View File

@ -0,0 +1,44 @@
From 4161593c24ea24f03bc89d74147e7209dc02ba80 Mon Sep 17 00:00:00 2001
From: Mike Yuan <me@yhndnzj.com>
Date: Sat, 3 Dec 2022 20:27:47 +0800
Subject: [PATCH] rpm/systemd-update-helper: use --no-warn when disabling units
Suppress the "empty [Install] section" warning (see #25437).
(cherry picked from commit 0acb1459a15f5b4d3a9bd2e7bf52661ca7bdebf0)
Related: #2141979
---
src/rpm/systemd-update-helper.in | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/rpm/systemd-update-helper.in b/src/rpm/systemd-update-helper.in
index ab8cdc0ff9..b35d952fab 100755
--- a/src/rpm/systemd-update-helper.in
+++ b/src/rpm/systemd-update-helper.in
@@ -19,21 +19,21 @@ case "$command" in
remove-system-units)
if [ -d /run/systemd/system ]; then
- systemctl --no-reload disable --now "$@"
+ systemctl --no-reload disable --now --no-warn "$@"
else
- systemctl --no-reload disable "$@"
+ systemctl --no-reload disable --no-warn "$@"
fi
;;
remove-user-units)
- systemctl --global disable "$@"
+ systemctl --global disable --no-warn "$@"
[ -d /run/systemd/system ] || exit 0
users=$(systemctl list-units 'user@*' --legend=no | sed -n -r 's/.*user@([0-9]+).service.*/\1/p')
for user in $users; do
SYSTEMD_BUS_TIMEOUT={{UPDATE_HELPER_USER_TIMEOUT}} \
- systemctl --user -M "$user@" disable --now "$@" &
+ systemctl --user -M "$user@" disable --now --no-warn "$@" &
done
wait
;;

View File

@ -0,0 +1,80 @@
From 02fbe7d4c9bd34134c12978726b036ec1ceea839 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Wed, 7 Dec 2022 13:59:01 +0900
Subject: [PATCH] systemctl: suppress warning about missing /proc/ when
--no-warn
Follow-up for 0f958c8d4fc13ed1c1af928b2a7d91d31c7576eb.
systemctl is called many times by dnf or so, and missing /proc/ is not
a user's fault, but package manager's issue.
With this commit, we can suppress the warning by updating rpm macros if
necessary.
(cherry picked from commit 91dfb74ef5e38625dada2c2a6ae30152e64c3f5b)
Related: #2141979
---
man/systemctl.xml | 16 ++++++++++++----
src/systemctl/systemctl.c | 14 +++++++-------
2 files changed, 19 insertions(+), 11 deletions(-)
diff --git a/man/systemctl.xml b/man/systemctl.xml
index d909dc4db4..b73d4ac048 100644
--- a/man/systemctl.xml
+++ b/man/systemctl.xml
@@ -2004,10 +2004,18 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
<term><option>--no-warn</option></term>
<listitem>
- <para>Don't generate the warning shown by default when using
- <command>enable</command> or <command>disable</command> on units
- without install information (i.e. don't have or have an empty
- [Install] section).</para>
+ <para>Don't generate the warnings shown by default in the following cases:
+ <itemizedlist>
+ <listitem>
+ <para>when <command>systemctl</command> is invoked without procfs mounted on
+ <filename>/proc/</filename>,</para>
+ </listitem>
+ <listitem>
+ <para>when using <command>enable</command> or <command>disable</command> on units without
+ install information (i.e. don't have or have an empty [Install] section).</para>
+ </listitem>
+ </itemizedlist>
+ </para>
</listitem>
</varlistentry>
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 57e9966d3c..3f2b0029ca 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -277,8 +277,7 @@ static int systemctl_help(void) {
" kexec, suspend, hibernate, suspend-then-hibernate,\n"
" hybrid-sleep, default, rescue, emergency, and exit.\n"
" -q --quiet Suppress output\n"
- " --no-warn Don't generate warning when trying to enable/disable\n"
- " units without install information\n"
+ " --no-warn Suppress several warnings shown by default\n"
" --wait For (re)start, wait until service stopped again\n"
" For is-system-running, wait until startup is completed\n"
" --no-block Do not wait until operation finished\n"
@@ -1157,11 +1156,12 @@ static int run(int argc, char *argv[]) {
goto finish;
if (proc_mounted() == 0)
- log_warning("%s%s/proc/ is not mounted. This is not a supported mode of operation. Please fix\n"
- "your invocation environment to mount /proc/ and /sys/ properly. Proceeding anyway.\n"
- "Your mileage may vary.",
- emoji_enabled() ? special_glyph(SPECIAL_GLYPH_WARNING_SIGN) : "",
- emoji_enabled() ? " " : "");
+ log_full(arg_no_warn ? LOG_DEBUG : LOG_WARNING,
+ "%s%s/proc/ is not mounted. This is not a supported mode of operation. Please fix\n"
+ "your invocation environment to mount /proc/ and /sys/ properly. Proceeding anyway.\n"
+ "Your mileage may vary.",
+ emoji_enabled() ? special_glyph(SPECIAL_GLYPH_WARNING_SIGN) : "",
+ emoji_enabled() ? " " : "");
if (arg_action != ACTION_SYSTEMCTL && running_in_chroot() > 0) {
if (!arg_quiet)

View File

@ -0,0 +1,38 @@
From 282bb5b70e6ff146ba81fea82d85d1e3f0cebc77 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Tue, 13 Dec 2022 09:05:11 +0900
Subject: [PATCH] shell-completion: systemctl: add --no-warn
(cherry picked from commit 93b0ec8bc533e8e8245560152c57e9c5dfb906bf)
Related: #2141979
---
shell-completion/bash/systemctl.in | 2 +-
shell-completion/zsh/_systemctl.in | 1 +
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/shell-completion/bash/systemctl.in b/shell-completion/bash/systemctl.in
index f935960c77..3c64467e2f 100644
--- a/shell-completion/bash/systemctl.in
+++ b/shell-completion/bash/systemctl.in
@@ -128,7 +128,7 @@ _systemctl () {
[STANDALONE]='--all -a --reverse --after --before --defaults --force -f --full -l --global
--help -h --no-ask-password --no-block --legend=no --no-pager --no-reload --no-wall --now
--quiet -q --system --user --version --runtime --recursive -r --firmware-setup
- --show-types --plain --failed --value --fail --dry-run --wait'
+ --show-types --plain --failed --value --fail --dry-run --wait --no-warn'
[ARG]='--host -H --kill-whom --property -p --signal -s --type -t --state --job-mode --root
--preset-mode -n --lines -o --output -M --machine --message --timestamp --check-inhibitors'
)
diff --git a/shell-completion/zsh/_systemctl.in b/shell-completion/zsh/_systemctl.in
index d471743030..2811582236 100644
--- a/shell-completion/zsh/_systemctl.in
+++ b/shell-completion/zsh/_systemctl.in
@@ -480,6 +480,7 @@ _arguments -s \
'--show-types[When showing sockets, show socket type]' \
'--check-inhibitors[Specify if inhibitors should be checked]:mode:_systemctl_check_inhibitors' \
{-q,--quiet}'[Suppress output]' \
+ '--no-warn[Suppress several warnings shown by default]' \
'--no-block[Do not wait until operation finished]' \
'--legend=no[Do not print a legend, i.e. the column headers and the footer with hints]' \
'--no-pager[Do not pipe output into a pager]' \

View File

@ -0,0 +1,24 @@
From bc9f6f765f772e8535325c224d2023165bc53e5c Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Tue, 15 Nov 2022 12:54:11 +0900
Subject: [PATCH] core/unit: drop doubled empty line
(cherry picked from commit ca1999a24c88b2460240aaff8095c2db7491f77c)
Related: #2160477
---
src/core/unit.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/core/unit.c b/src/core/unit.c
index 4bb7e2d498..4cde5c4b4e 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -720,7 +720,6 @@ Unit* unit_free(Unit *u) {
if (u->on_console)
manager_unref_console(u->manager);
-
fdset_free(u->initial_socket_bind_link_fds);
#if BPF_FRAMEWORK
bpf_link_free(u->ipv4_socket_bind_link);

View File

@ -0,0 +1,66 @@
From 82e78c509c9eab33c1dbf2bc445f91b67b2f118f Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Wed, 16 Nov 2022 03:08:22 +0900
Subject: [PATCH] core/unit: drop dependency to the unit being merged
Fixes a bug in 15ed3c3a188cf7fa5a60ae508fc7a3ed048d2220.
Fixes #24990. Also, hopefully fixes #24577.
(cherry picked from commit c8b3b524134539846917269ddd644ee93a35623f)
Related: #2160477
---
src/core/unit.c | 21 +++++++++++++--------
1 file changed, 13 insertions(+), 8 deletions(-)
diff --git a/src/core/unit.c b/src/core/unit.c
index 4cde5c4b4e..ae9f688ad2 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -1043,10 +1043,10 @@ static int unit_add_dependency_hashmap(
return unit_per_dependency_type_hashmap_update(per_type, other, origin_mask, destination_mask);
}
-static void unit_merge_dependencies(
- Unit *u,
- Unit *other) {
-
+static void unit_merge_dependencies(Unit *u, Unit *other) {
+ Hashmap *deps;
+ void *dt; /* Actually of type UnitDependency, except that we don't bother casting it here,
+ * since the hashmaps all want it as void pointer. */
int r;
assert(u);
@@ -1055,12 +1055,19 @@ static void unit_merge_dependencies(
if (u == other)
return;
+ /* First, remove dependency to other. */
+ HASHMAP_FOREACH_KEY(deps, dt, u->dependencies) {
+ if (hashmap_remove(deps, other))
+ unit_maybe_warn_about_dependency(u, other->id, UNIT_DEPENDENCY_FROM_PTR(dt));
+
+ if (hashmap_isempty(deps))
+ hashmap_free(hashmap_remove(u->dependencies, dt));
+ }
+
for (;;) {
_cleanup_(hashmap_freep) Hashmap *other_deps = NULL;
UnitDependencyInfo di_back;
Unit *back;
- void *dt; /* Actually of type UnitDependency, except that we don't bother casting it here,
- * since the hashmaps all want it as void pointer. */
/* Let's focus on one dependency type at a time, that 'other' has defined. */
other_deps = hashmap_steal_first_key_and_value(other->dependencies, &dt);
@@ -1102,8 +1109,6 @@ static void unit_merge_dependencies(
* them per type wholesale. */
r = hashmap_put(u->dependencies, dt, other_deps);
if (r == -EEXIST) {
- Hashmap *deps;
-
/* The target unit already has dependencies of this type, let's then merge this individually. */
assert_se(deps = hashmap_get(u->dependencies, dt));

View File

@ -0,0 +1,32 @@
From 1d12983063afc64709894d80b7adcf6609aa9a43 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Tue, 15 Nov 2022 23:08:35 +0900
Subject: [PATCH] core/unit: fix logic of dropping self-referencing
dependencies
Fixes a bug in 15ed3c3a188cf7fa5a60ae508fc7a3ed048d2220.
(cherry picked from commit 53e0e6ef0eea396bb432cbfc1f2f6ea1272ff1f1)
Related: #2160477
---
src/core/unit.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/core/unit.c b/src/core/unit.c
index ae9f688ad2..dbbf818622 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -1130,10 +1130,11 @@ static void unit_merge_dependencies(Unit *u, Unit *other) {
}
} else {
assert_se(r >= 0);
- TAKE_PTR(other_deps);
if (hashmap_remove(other_deps, u))
unit_maybe_warn_about_dependency(u, other->id, UNIT_DEPENDENCY_FROM_PTR(dt));
+
+ TAKE_PTR(other_deps);
}
}

View File

@ -0,0 +1,96 @@
From 471e4ee0b4fa9c7e9a5ea875fbf22de77fdd25d0 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Thu, 17 Nov 2022 12:46:45 +0900
Subject: [PATCH] core/unit: merge two loops into one
No functional change, just refactoring.
(cherry picked from commit 4b7918a65cc2571a2b3fc166229e1b8db463e217)
Related: #2160477
---
src/core/unit.c | 47 +++++++++++++++--------------------------------
1 file changed, 15 insertions(+), 32 deletions(-)
diff --git a/src/core/unit.c b/src/core/unit.c
index dbbf818622..6b49edc2de 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -1047,7 +1047,6 @@ static void unit_merge_dependencies(Unit *u, Unit *other) {
Hashmap *deps;
void *dt; /* Actually of type UnitDependency, except that we don't bother casting it here,
* since the hashmaps all want it as void pointer. */
- int r;
assert(u);
assert(other);
@@ -1074,6 +1073,8 @@ static void unit_merge_dependencies(Unit *u, Unit *other) {
if (!other_deps)
break; /* done! */
+ deps = hashmap_get(u->dependencies, dt);
+
/* Now iterate through all dependencies of this dependency type, of 'other'. We refer to the
* referenced units as 'back'. */
HASHMAP_FOREACH_KEY(di_back.data, back, other_deps) {
@@ -1084,6 +1085,7 @@ static void unit_merge_dependencies(Unit *u, Unit *other) {
/* This is a dependency pointing back to the unit we want to merge with?
* Suppress it (but warn) */
unit_maybe_warn_about_dependency(u, other->id, UNIT_DEPENDENCY_FROM_PTR(dt));
+ hashmap_remove(other_deps, back);
continue;
}
@@ -1102,40 +1104,21 @@ static void unit_merge_dependencies(Unit *u, Unit *other) {
di_move.origin_mask,
di_move.destination_mask) >= 0);
}
- }
- /* Now all references towards 'other' of the current type 'dt' are corrected to point to
- * 'u'. Lets's now move the deps of type 'dt' from 'other' to 'u'. First, let's try to move
- * them per type wholesale. */
- r = hashmap_put(u->dependencies, dt, other_deps);
- if (r == -EEXIST) {
/* The target unit already has dependencies of this type, let's then merge this individually. */
-
- assert_se(deps = hashmap_get(u->dependencies, dt));
-
- for (;;) {
- UnitDependencyInfo di_move;
-
- /* Get first dep */
- di_move.data = hashmap_steal_first_key_and_value(other_deps, (void**) &back);
- if (!di_move.data)
- break; /* done */
- if (back == u) {
- /* Would point back to us, ignore */
- unit_maybe_warn_about_dependency(u, other->id, UNIT_DEPENDENCY_FROM_PTR(dt));
- continue;
- }
-
- assert_se(unit_per_dependency_type_hashmap_update(deps, back, di_move.origin_mask, di_move.destination_mask) >= 0);
- }
- } else {
- assert_se(r >= 0);
-
- if (hashmap_remove(other_deps, u))
- unit_maybe_warn_about_dependency(u, other->id, UNIT_DEPENDENCY_FROM_PTR(dt));
-
- TAKE_PTR(other_deps);
+ if (deps)
+ assert_se(unit_per_dependency_type_hashmap_update(
+ deps,
+ back,
+ di_back.origin_mask,
+ di_back.destination_mask) >= 0);
}
+
+ /* Now all references towards 'other' of the current type 'dt' are corrected to point to 'u'.
+ * Lets's now move the deps of type 'dt' from 'other' to 'u'. If the unit does not have
+ * dependencies of this type, let's move them per type wholesale. */
+ if (!deps)
+ assert_se(hashmap_put(u->dependencies, dt, TAKE_PTR(other_deps)) >= 0);
}
other->dependencies = hashmap_free(other->dependencies);

View File

@ -0,0 +1,148 @@
From 55e11475d421f90cc5c7290c6b5d394f952ba577 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Tue, 15 Nov 2022 21:52:10 +0900
Subject: [PATCH] test: add test case for sysv-generator and invalid dependency
(cherry picked from commit 5f882cc3ab32636d9242effb2cefad20d92d2ec2)
Related: #2160477
---
test/units/testsuite-26.sh | 116 ++++++++++++++++++++++++++++++++++++-
1 file changed, 114 insertions(+), 2 deletions(-)
diff --git a/test/units/testsuite-26.sh b/test/units/testsuite-26.sh
index 7c7a12b1ae..a8e7a5abaa 100755
--- a/test/units/testsuite-26.sh
+++ b/test/units/testsuite-26.sh
@@ -3,10 +3,18 @@
set -eux
set -o pipefail
+# shellcheck source=test/units/assert.sh
+. "$(dirname "$0")"/assert.sh
+
+: >/failed
+
at_exit() {
if [[ -v UNIT_NAME && -e "/usr/lib/systemd/system/$UNIT_NAME" ]]; then
rm -fv "/usr/lib/systemd/system/$UNIT_NAME"
fi
+
+ rm -f /etc/init.d/issue-24990
+ return 0
}
trap at_exit EXIT
@@ -284,6 +292,110 @@ systemctl unset-environment IMPORT_THIS IMPORT_THIS_TOO
(! systemctl show-environment | grep "^IMPORT_THIS=")
(! systemctl show-environment | grep "^IMPORT_THIS_TOO=")
-echo OK >/testok
+# test for sysv-generator (issue #24990)
+if [[ -x /usr/lib/systemd/system-generators/systemd-sysv-generator ]]; then
+
+ # invalid dependency
+ cat >/etc/init.d/issue-24990 <<\EOF
+#!/bin/bash
+
+### BEGIN INIT INFO
+# Provides:test1 test2
+# Required-Start:test1 $remote_fs $network
+# Required-Stop:test1 $remote_fs $network
+# Description:Test
+# Short-Description: Test
+### END INIT INFO
+
+case "$1" in
+ start)
+ echo "Starting issue-24990.service"
+ sleep 1000 &
+ ;;
+ stop)
+ echo "Stopping issue-24990.service"
+ sleep 10 &
+ ;;
+ *)
+ echo "Usage: service test {start|stop|restart|status}"
+ ;;
+esac
+EOF
+
+ chmod +x /etc/init.d/issue-24990
+ systemctl daemon-reload
+ [[ -L /run/systemd/generator.late/test1.service ]]
+ [[ -L /run/systemd/generator.late/test2.service ]]
+ assert_eq "$(readlink -f /run/systemd/generator.late/test1.service)" "/run/systemd/generator.late/issue-24990.service"
+ assert_eq "$(readlink -f /run/systemd/generator.late/test2.service)" "/run/systemd/generator.late/issue-24990.service"
+ output=$(systemctl cat issue-24990)
+ assert_in "SourcePath=/etc/init.d/issue-24990" "$output"
+ assert_in "Description=LSB: Test" "$output"
+ assert_in "After=test1.service" "$output"
+ assert_in "After=remote-fs.target" "$output"
+ assert_in "After=network-online.target" "$output"
+ assert_in "Wants=network-online.target" "$output"
+ assert_in "ExecStart=/etc/init.d/issue-24990 start" "$output"
+ assert_in "ExecStop=/etc/init.d/issue-24990 stop" "$output"
+ systemctl status issue-24990 || :
+ systemctl show issue-24990
+ assert_not_in "issue-24990.service" "$(systemctl show --property=After --value)"
+ assert_not_in "issue-24990.service" "$(systemctl show --property=Before --value)"
+
+ if ! systemctl is-active network-online.target; then
+ systemctl start network-online.target
+ fi
+
+ systemctl restart issue-24990
+ systemctl stop issue-24990
+
+ # valid dependency
+ cat >/etc/init.d/issue-24990 <<\EOF
+#!/bin/bash
+
+### BEGIN INIT INFO
+# Provides:test1 test2
+# Required-Start:$remote_fs
+# Required-Stop:$remote_fs
+# Description:Test
+# Short-Description: Test
+### END INIT INFO
+
+case "$1" in
+ start)
+ echo "Starting issue-24990.service"
+ sleep 1000 &
+ ;;
+ stop)
+ echo "Stopping issue-24990.service"
+ sleep 10 &
+ ;;
+ *)
+ echo "Usage: service test {start|stop|restart|status}"
+ ;;
+esac
+EOF
+
+ chmod +x /etc/init.d/issue-24990
+ systemctl daemon-reload
+ [[ -L /run/systemd/generator.late/test1.service ]]
+ [[ -L /run/systemd/generator.late/test2.service ]]
+ assert_eq "$(readlink -f /run/systemd/generator.late/test1.service)" "/run/systemd/generator.late/issue-24990.service"
+ assert_eq "$(readlink -f /run/systemd/generator.late/test2.service)" "/run/systemd/generator.late/issue-24990.service"
+ output=$(systemctl cat issue-24990)
+ assert_in "SourcePath=/etc/init.d/issue-24990" "$output"
+ assert_in "Description=LSB: Test" "$output"
+ assert_in "After=remote-fs.target" "$output"
+ assert_in "ExecStart=/etc/init.d/issue-24990 start" "$output"
+ assert_in "ExecStop=/etc/init.d/issue-24990 stop" "$output"
+ systemctl status issue-24990 || :
+ systemctl show issue-24990
+ assert_not_in "issue-24990.service" "$(systemctl show --property=After --value)"
+ assert_not_in "issue-24990.service" "$(systemctl show --property=Before --value)"
+
+ systemctl restart issue-24990
+ systemctl stop issue-24990
+fi
-exit 0
+touch /testok
+rm /failed

View File

@ -0,0 +1,45 @@
From 48455fa876129bf33df06d2e758fb0fbda510d5b Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Wed, 16 Nov 2022 03:18:30 +0900
Subject: [PATCH] core/unit: merge unit names after merging deps
Before:
systemd[1]: issue-24990.service: Dependency Before=n/a dropped, merged into issue-24990.service
After:
systemd[1]: issue-24990.service: Dependency Before=test1.service dropped, merged into issue-24990.service
(cherry picked from commit 1d0c81a05b1605a5fc3db44d5a157a1d6876eda9)
Related: #2160477
---
src/core/unit.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/src/core/unit.c b/src/core/unit.c
index 6b49edc2de..d1929bbf69 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -1164,11 +1164,6 @@ int unit_merge(Unit *u, Unit *other) {
if (r < 0)
return r;
- /* Merge names */
- r = unit_merge_names(u, other);
- if (r < 0)
- return r;
-
/* Redirect all references */
while (other->refs_by_target)
unit_ref_set(other->refs_by_target, other->refs_by_target->source, u);
@@ -1176,6 +1171,11 @@ int unit_merge(Unit *u, Unit *other) {
/* Merge dependencies */
unit_merge_dependencies(u, other);
+ /* Merge names. It is better to do that after merging deps, otherwise the log message contains n/a. */
+ r = unit_merge_names(u, other);
+ if (r < 0)
+ return r;
+
other->load_state = UNIT_MERGED;
other->merged_into = u;

View File

@ -0,0 +1,113 @@
From 883e46f2e4255b92a338c9d4004a8b4740cdbcaf Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Tue, 15 Nov 2022 22:59:01 +0900
Subject: [PATCH] core/unit: fix log message
As you can see in the below, the dropped dependency Before=issue-24990.service
is not logged, but the dependency Before=test1.service which is not owned by
the units generated by the TEST-26 is logged.
Before:
systemd[1]: issue-24990.service: Dependency After=test1.service dropped, merged into issue-24990.service
systemd[1]: issue-24990.service: Dependency Before=test1.service dropped, merged into issue-24990.service
After:
systemd[1]: issue-24990.service: Dependency After=test1.service is dropped, as test1.service is merged into issue-24990.service.
systemd[1]: issue-24990.service: Dependency Before=issue-24990.service in test1.service is dropped, as test1.service is merged into issue-24990.service.
(cherry picked from commit ed9911630e4bca844381d7caeb850dad9a9fa122)
Related: #2160477
---
src/core/unit.c | 49 ++++++++++++++++++++++---------------------------
1 file changed, 22 insertions(+), 27 deletions(-)
diff --git a/src/core/unit.c b/src/core/unit.c
index d1929bbf69..c319e99d71 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -936,29 +936,17 @@ static int unit_reserve_dependencies(Unit *u, Unit *other) {
return 0;
}
-static void unit_maybe_warn_about_dependency(
- Unit *u,
- const char *other_id,
- UnitDependency dependency) {
-
- assert(u);
-
+static bool unit_should_warn_about_dependency(UnitDependency dependency) {
/* Only warn about some unit types */
- if (!IN_SET(dependency,
- UNIT_CONFLICTS,
- UNIT_CONFLICTED_BY,
- UNIT_BEFORE,
- UNIT_AFTER,
- UNIT_ON_SUCCESS,
- UNIT_ON_FAILURE,
- UNIT_TRIGGERS,
- UNIT_TRIGGERED_BY))
- return;
-
- if (streq_ptr(u->id, other_id))
- log_unit_warning(u, "Dependency %s=%s dropped", unit_dependency_to_string(dependency), u->id);
- else
- log_unit_warning(u, "Dependency %s=%s dropped, merged into %s", unit_dependency_to_string(dependency), strna(other_id), u->id);
+ return IN_SET(dependency,
+ UNIT_CONFLICTS,
+ UNIT_CONFLICTED_BY,
+ UNIT_BEFORE,
+ UNIT_AFTER,
+ UNIT_ON_SUCCESS,
+ UNIT_ON_FAILURE,
+ UNIT_TRIGGERS,
+ UNIT_TRIGGERED_BY);
}
static int unit_per_dependency_type_hashmap_update(
@@ -1056,8 +1044,10 @@ static void unit_merge_dependencies(Unit *u, Unit *other) {
/* First, remove dependency to other. */
HASHMAP_FOREACH_KEY(deps, dt, u->dependencies) {
- if (hashmap_remove(deps, other))
- unit_maybe_warn_about_dependency(u, other->id, UNIT_DEPENDENCY_FROM_PTR(dt));
+ if (hashmap_remove(deps, other) && unit_should_warn_about_dependency(UNIT_DEPENDENCY_FROM_PTR(dt)))
+ log_unit_warning(u, "Dependency %s=%s is dropped, as %s is merged into %s.",
+ unit_dependency_to_string(UNIT_DEPENDENCY_FROM_PTR(dt)),
+ other->id, other->id, u->id);
if (hashmap_isempty(deps))
hashmap_free(hashmap_remove(u->dependencies, dt));
@@ -1084,7 +1074,11 @@ static void unit_merge_dependencies(Unit *u, Unit *other) {
if (back == u) {
/* This is a dependency pointing back to the unit we want to merge with?
* Suppress it (but warn) */
- unit_maybe_warn_about_dependency(u, other->id, UNIT_DEPENDENCY_FROM_PTR(dt));
+ if (unit_should_warn_about_dependency(UNIT_DEPENDENCY_FROM_PTR(dt)))
+ log_unit_warning(u, "Dependency %s=%s in %s is dropped, as %s is merged into %s.",
+ unit_dependency_to_string(UNIT_DEPENDENCY_FROM_PTR(dt)),
+ u->id, other->id, other->id, u->id);
+
hashmap_remove(other_deps, back);
continue;
}
@@ -3049,7 +3043,6 @@ int unit_add_dependency(
[UNIT_IN_SLICE] = UNIT_SLICE_OF,
[UNIT_SLICE_OF] = UNIT_IN_SLICE,
};
- Unit *original_u = u, *original_other = other;
UnitDependencyAtom a;
int r;
@@ -3068,7 +3061,9 @@ int unit_add_dependency(
/* We won't allow dependencies on ourselves. We will not consider them an error however. */
if (u == other) {
- unit_maybe_warn_about_dependency(original_u, original_other->id, d);
+ if (unit_should_warn_about_dependency(d))
+ log_unit_warning(u, "Dependency %s=%s is dropped.",
+ unit_dependency_to_string(d), u->id);
return 0;
}

View File

@ -0,0 +1,34 @@
From 0bdf4aaa0d8cdc6b2721d09fe630bf6185903a0d Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Thu, 12 Jan 2023 19:19:28 +0100
Subject: [PATCH] test: explicitly create the /etc/init.d directory
On RHEL/CentOS/Fedora this directory is provided by the chkconfig or
initscripts package, which might not be installed:
testsuite-26.sh[1225]: + [[ -x /usr/lib/systemd/system-generators/systemd-sysv-generator ]]
testsuite-26.sh[1225]: + cat
testsuite-26.sh[2330]: /usr/lib/systemd/tests/testdata/units/testsuite-26.sh: line 299: /etc/init.d/issue-24990: No such file or directory
Follow-up to 5f882cc3ab32636d9242effb2cefad20d92d2ec2.
(cherry picked from commit 7fcf0fab078ed92a4f6c3c3658c0a9dfd67c9601)
Related: #2160477
---
test/units/testsuite-26.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/test/units/testsuite-26.sh b/test/units/testsuite-26.sh
index a8e7a5abaa..37ae6069bc 100755
--- a/test/units/testsuite-26.sh
+++ b/test/units/testsuite-26.sh
@@ -294,7 +294,7 @@ systemctl unset-environment IMPORT_THIS IMPORT_THIS_TOO
# test for sysv-generator (issue #24990)
if [[ -x /usr/lib/systemd/system-generators/systemd-sysv-generator ]]; then
-
+ mkdir -p /etc/init.d
# invalid dependency
cat >/etc/init.d/issue-24990 <<\EOF
#!/bin/bash

View File

@ -0,0 +1,97 @@
From 956944405391b5bbb8a4fee9ad93e14bf908f0a9 Mon Sep 17 00:00:00 2001
From: Frantisek Sumsal <frantisek@sumsal.cz>
Date: Fri, 13 Jan 2023 20:10:42 +0100
Subject: [PATCH] test: support a non-default SysV directory
Since the directory is configurable via -Dsysvinit-path= during build,
it makes the test fail on Fedora/RHEL/CentOS, where it's set to
/etc/rc.d/init.d, instead of the default /etc/init.d. Since we can't get
the value at runtime (in a reasonable manner), let's just support the
two most common paths for now.
Follow up to 7fcf0fab078ed92a4f6c3c3658c0a9dfd67c9601.
(cherry picked from commit fc2a0bc05e0429e468c7eaad52998292105fe7fb)
Related: #2160477
---
test/units/testsuite-26.sh | 25 ++++++++++++++-----------
1 file changed, 14 insertions(+), 11 deletions(-)
diff --git a/test/units/testsuite-26.sh b/test/units/testsuite-26.sh
index 37ae6069bc..916a6704d7 100755
--- a/test/units/testsuite-26.sh
+++ b/test/units/testsuite-26.sh
@@ -294,9 +294,12 @@ systemctl unset-environment IMPORT_THIS IMPORT_THIS_TOO
# test for sysv-generator (issue #24990)
if [[ -x /usr/lib/systemd/system-generators/systemd-sysv-generator ]]; then
- mkdir -p /etc/init.d
+ # This is configurable via -Dsysvinit-path=, but we can't get the value
+ # at runtime, so let's just support the two most common paths for now.
+ [[ -d /etc/rc.d/init.d ]] && SYSVINIT_PATH="/etc/rc.d/init.d" || SYSVINIT_PATH="/etc/init.d"
+
# invalid dependency
- cat >/etc/init.d/issue-24990 <<\EOF
+ cat >"${SYSVINIT_PATH:?}/issue-24990" <<\EOF
#!/bin/bash
### BEGIN INIT INFO
@@ -322,21 +325,21 @@ case "$1" in
esac
EOF
- chmod +x /etc/init.d/issue-24990
+ chmod +x "$SYSVINIT_PATH/issue-24990"
systemctl daemon-reload
[[ -L /run/systemd/generator.late/test1.service ]]
[[ -L /run/systemd/generator.late/test2.service ]]
assert_eq "$(readlink -f /run/systemd/generator.late/test1.service)" "/run/systemd/generator.late/issue-24990.service"
assert_eq "$(readlink -f /run/systemd/generator.late/test2.service)" "/run/systemd/generator.late/issue-24990.service"
output=$(systemctl cat issue-24990)
- assert_in "SourcePath=/etc/init.d/issue-24990" "$output"
+ assert_in "SourcePath=$SYSVINIT_PATH/issue-24990" "$output"
assert_in "Description=LSB: Test" "$output"
assert_in "After=test1.service" "$output"
assert_in "After=remote-fs.target" "$output"
assert_in "After=network-online.target" "$output"
assert_in "Wants=network-online.target" "$output"
- assert_in "ExecStart=/etc/init.d/issue-24990 start" "$output"
- assert_in "ExecStop=/etc/init.d/issue-24990 stop" "$output"
+ assert_in "ExecStart=$SYSVINIT_PATH/issue-24990 start" "$output"
+ assert_in "ExecStop=$SYSVINIT_PATH/issue-24990 stop" "$output"
systemctl status issue-24990 || :
systemctl show issue-24990
assert_not_in "issue-24990.service" "$(systemctl show --property=After --value)"
@@ -350,7 +353,7 @@ EOF
systemctl stop issue-24990
# valid dependency
- cat >/etc/init.d/issue-24990 <<\EOF
+ cat >"$SYSVINIT_PATH/issue-24990" <<\EOF
#!/bin/bash
### BEGIN INIT INFO
@@ -376,18 +379,18 @@ case "$1" in
esac
EOF
- chmod +x /etc/init.d/issue-24990
+ chmod +x "$SYSVINIT_PATH/issue-24990"
systemctl daemon-reload
[[ -L /run/systemd/generator.late/test1.service ]]
[[ -L /run/systemd/generator.late/test2.service ]]
assert_eq "$(readlink -f /run/systemd/generator.late/test1.service)" "/run/systemd/generator.late/issue-24990.service"
assert_eq "$(readlink -f /run/systemd/generator.late/test2.service)" "/run/systemd/generator.late/issue-24990.service"
output=$(systemctl cat issue-24990)
- assert_in "SourcePath=/etc/init.d/issue-24990" "$output"
+ assert_in "SourcePath=$SYSVINIT_PATH/issue-24990" "$output"
assert_in "Description=LSB: Test" "$output"
assert_in "After=remote-fs.target" "$output"
- assert_in "ExecStart=/etc/init.d/issue-24990 start" "$output"
- assert_in "ExecStop=/etc/init.d/issue-24990 stop" "$output"
+ assert_in "ExecStart=$SYSVINIT_PATH/issue-24990 start" "$output"
+ assert_in "ExecStop=$SYSVINIT_PATH/issue-24990 stop" "$output"
systemctl status issue-24990 || :
systemctl show issue-24990
assert_not_in "issue-24990.service" "$(systemctl show --property=After --value)"

View File

@ -21,7 +21,7 @@
Name: systemd
Url: https://www.freedesktop.org/wiki/Software/systemd
Version: 252
Release: 2%{?dist}
Release: 3%{?dist}
# For a breakdown of the licensing, see README
License: LGPLv2+ and MIT and GPLv2+
Summary: System and Service Manager
@ -234,6 +234,29 @@ Patch0153: 0153-dissect-rework-DISSECT_IMAGE_ADD_PARTITION_DEVICES-D.patch
Patch0154: 0154-ci-Mergify-v252-configuration-update.patch
Patch0155: 0155-ci-Run-GitHub-workflows-on-rhel-branches.patch
Patch0156: 0156-ci-Drop-scorecards-workflow-not-relevant.patch
Patch0157: 0157-swap-tell-swapon-to-reinitialize-swap-if-needed.patch
Patch0158: 0158-coredump-adjust-whitespace.patch
Patch0159: 0159-coredump-do-not-allow-user-to-access-coredumps-with-.patch
Patch0160: 0160-Revert-basic-add-fallback-in-chase_symlinks_and_open.patch
Patch0161: 0161-glyph-util-add-warning-sign-special-glyph.patch
Patch0162: 0162-chase-symlink-when-converting-directory-O_PATH-fd-to.patch
Patch0163: 0163-systemctl-print-a-clear-warning-if-people-invoke-sys.patch
Patch0164: 0164-TEST-65-check-cat-config-operation-in-chroot.patch
Patch0165: 0165-TEST-65-use-v-more.patch
Patch0166: 0166-systemctl-warn-if-trying-to-disable-a-unit-with-no-i.patch
Patch0167: 0167-systemctl-allow-suppress-the-warning-of-no-install-i.patch
Patch0168: 0168-rpm-systemd-update-helper-use-no-warn-when-disabling.patch
Patch0169: 0169-systemctl-suppress-warning-about-missing-proc-when-n.patch
Patch0170: 0170-shell-completion-systemctl-add-no-warn.patch
Patch0171: 0171-core-unit-drop-doubled-empty-line.patch
Patch0172: 0172-core-unit-drop-dependency-to-the-unit-being-merged.patch
Patch0173: 0173-core-unit-fix-logic-of-dropping-self-referencing-dep.patch
Patch0174: 0174-core-unit-merge-two-loops-into-one.patch
Patch0175: 0175-test-add-test-case-for-sysv-generator-and-invalid-de.patch
Patch0176: 0176-core-unit-merge-unit-names-after-merging-deps.patch
Patch0177: 0177-core-unit-fix-log-message.patch
Patch0178: 0178-test-explicitly-create-the-etc-init.d-directory.patch
Patch0179: 0179-test-support-a-non-default-SysV-directory.patch
# Downstream-only patches (90009999)
@ -1025,6 +1048,31 @@ getent passwd systemd-oom &>/dev/null || useradd -r -l -g systemd-oom -d / -s /s
%files standalone-sysusers -f .file-list-standalone-sysusers
%changelog
* Mon Jan 16 2023 systemd maintenance team <systemd-maint@redhat.com> - 252-3
- swap: tell swapon to reinitialize swap if needed (#2151993)
- coredump: adjust whitespace (#2155517)
- coredump: do not allow user to access coredumps with changed uid/gid/capabilities (#2155517)
- Revert "basic: add fallback in chase_symlinks_and_opendir() for cases when /proc is not mounted" (#2138081)
- glyph-util: add warning sign special glyph (#2138081)
- chase-symlink: when converting directory O_PATH fd to real fd, don't bother with /proc/ (#2138081)
- systemctl: print a clear warning if people invoke systemctl without /proc/ (#2138081)
- TEST-65: check cat-config operation in chroot (#2138081)
- TEST-65: use [[ -v ]] more (#2138081)
- systemctl: warn if trying to disable a unit with no install info (#2141979)
- systemctl: allow suppress the warning of no install info using --no-warn (#2141979)
- rpm/systemd-update-helper: use --no-warn when disabling units (#2141979)
- systemctl: suppress warning about missing /proc/ when --no-warn (#2141979)
- shell-completion: systemctl: add --no-warn (#2141979)
- core/unit: drop doubled empty line (#2160477)
- core/unit: drop dependency to the unit being merged (#2160477)
- core/unit: fix logic of dropping self-referencing dependencies (#2160477)
- core/unit: merge two loops into one (#2160477)
- test: add test case for sysv-generator and invalid dependency (#2160477)
- core/unit: merge unit names after merging deps (#2160477)
- core/unit: fix log message (#2160477)
- test: explicitly create the /etc/init.d directory (#2160477)
- test: support a non-default SysV directory (#2160477)
* Fri Dec 09 2022 systemd maintenance team <systemd-maint@redhat.com> - 252-2
- test: check if we can use SHA1 MD for signing before using it (#2141979)
- boot: cleanups for efivar_get() and friends (#2141979)