parent
ef58c3488a
commit
c9d170cd93
@ -1,2 +1,3 @@
|
||||
SOURCES/rhel-net-naming-sysattrs-v0.5.tar.gz
|
||||
SOURCES/systemd-252.tar.gz
|
||||
SOURCES/systemd-container-coredump.pp.bz2
|
||||
|
@ -1,2 +1,3 @@
|
||||
9ce6834429dbb9cb049de1bdf77bc8c84763709c SOURCES/rhel-net-naming-sysattrs-v0.5.tar.gz
|
||||
7c961dc6e8bb950825b85129f59dc80f4536cabb SOURCES/systemd-252.tar.gz
|
||||
36eac49c362dc6e142f23b570a9a6b75f7547250 SOURCES/systemd-container-coredump.pp.bz2
|
||||
|
@ -0,0 +1,36 @@
|
||||
From 8e8f4d63f77fb9436d1e4caa2a4670dc3cf74657 Mon Sep 17 00:00:00 2001
|
||||
From: Daan De Meyer <daan.j.demeyer@gmail.com>
|
||||
Date: Tue, 13 Dec 2022 10:50:01 +0000
|
||||
Subject: [PATCH] execute: Pass AT_FDCWD instead of -1
|
||||
|
||||
Let's enforce that callers pass AT_FDCWD as read_dfd to load_credential()
|
||||
to avoid an assert() in read_full_file_full() if read_dfd is -1.
|
||||
|
||||
(cherry picked from commit 661e4251a5b157d1aee1df98fbd2f0c95285ebba)
|
||||
|
||||
Resolves: RHEL-32259
|
||||
---
|
||||
src/core/execute.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/core/execute.c b/src/core/execute.c
|
||||
index ea36254241..13222ddea3 100644
|
||||
--- a/src/core/execute.c
|
||||
+++ b/src/core/execute.c
|
||||
@@ -2662,6 +2662,7 @@ static int load_credential(
|
||||
assert(id);
|
||||
assert(path);
|
||||
assert(unit);
|
||||
+ assert(read_dfd >= 0 || read_dfd == AT_FDCWD);
|
||||
assert(write_dfd >= 0);
|
||||
assert(left);
|
||||
|
||||
@@ -2888,7 +2889,7 @@ static int acquire_credentials(
|
||||
lc->path,
|
||||
lc->encrypted,
|
||||
unit,
|
||||
- -1,
|
||||
+ AT_FDCWD,
|
||||
dfd,
|
||||
uid,
|
||||
ownership_ok,
|
@ -0,0 +1,530 @@
|
||||
From 65989e9f8f66ef3d6a81d38b913616ce722bab2b Mon Sep 17 00:00:00 2001
|
||||
From: Michal Sekletar <msekleta@redhat.com>
|
||||
Date: Mon, 18 Mar 2024 13:01:40 +0100
|
||||
Subject: [PATCH] coredump: generate stacktraces also for processes running in
|
||||
containers w/o coredump forwarding
|
||||
|
||||
Note that entering container namespace has to be explicitly enabled by
|
||||
setting SYSTEMD_COREDUMP_ALLOW_NAMESPACE_CHANGE environment variable.
|
||||
|
||||
RHEL-only
|
||||
|
||||
Resolves: RHEL-34061
|
||||
---
|
||||
src/analyze/analyze-inspect-elf.c | 2 +-
|
||||
src/basic/socket-util.c | 52 +++++++++++
|
||||
src/basic/socket-util.h | 15 ++++
|
||||
src/coredump/coredump.c | 143 +++++++++++++++++++-----------
|
||||
src/shared/elf-util.c | 46 +++++++++-
|
||||
src/shared/elf-util.h | 4 +-
|
||||
6 files changed, 202 insertions(+), 60 deletions(-)
|
||||
|
||||
diff --git a/src/analyze/analyze-inspect-elf.c b/src/analyze/analyze-inspect-elf.c
|
||||
index 155c611c71..b8074100a5 100644
|
||||
--- a/src/analyze/analyze-inspect-elf.c
|
||||
+++ b/src/analyze/analyze-inspect-elf.c
|
||||
@@ -30,7 +30,7 @@ static int analyze_elf(char **filenames, JsonFormatFlags json_flags) {
|
||||
if (fd < 0)
|
||||
return log_error_errno(fd, "Could not open \"%s\": %m", abspath);
|
||||
|
||||
- r = parse_elf_object(fd, abspath, /* fork_disable_dump= */false, NULL, &package_metadata);
|
||||
+ r = parse_elf_object(fd, -EBADF, UID_NOBODY, GID_NOBODY, abspath, /* fork_disable_dump= */false, NULL, &package_metadata);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Parsing \"%s\" as ELF object failed: %m", abspath);
|
||||
|
||||
diff --git a/src/basic/socket-util.c b/src/basic/socket-util.c
|
||||
index f39be19a59..1d86ca3f55 100644
|
||||
--- a/src/basic/socket-util.c
|
||||
+++ b/src/basic/socket-util.c
|
||||
@@ -41,6 +41,11 @@
|
||||
# define IDN_FLAGS 0
|
||||
#endif
|
||||
|
||||
+/* From the kernel's include/net/scm.h */
|
||||
+#ifndef SCM_MAX_FD
|
||||
+# define SCM_MAX_FD 253
|
||||
+#endif
|
||||
+
|
||||
static const char* const socket_address_type_table[] = {
|
||||
[SOCK_STREAM] = "Stream",
|
||||
[SOCK_DGRAM] = "Datagram",
|
||||
@@ -951,6 +956,53 @@ int getpeergroups(int fd, gid_t **ret) {
|
||||
return (int) n;
|
||||
}
|
||||
|
||||
+ssize_t send_many_fds_iov_sa(
|
||||
+ int transport_fd,
|
||||
+ int *fds_array, size_t n_fds_array,
|
||||
+ const struct iovec *iov, size_t iovlen,
|
||||
+ const struct sockaddr *sa, socklen_t len,
|
||||
+ int flags) {
|
||||
+
|
||||
+ _cleanup_free_ struct cmsghdr *cmsg = NULL;
|
||||
+ struct msghdr mh = {
|
||||
+ .msg_name = (struct sockaddr*) sa,
|
||||
+ .msg_namelen = len,
|
||||
+ .msg_iov = (struct iovec *)iov,
|
||||
+ .msg_iovlen = iovlen,
|
||||
+ };
|
||||
+ ssize_t k;
|
||||
+
|
||||
+ assert(transport_fd >= 0);
|
||||
+ assert(fds_array || n_fds_array == 0);
|
||||
+
|
||||
+ /* The kernel will reject sending more than SCM_MAX_FD FDs at once */
|
||||
+ if (n_fds_array > SCM_MAX_FD)
|
||||
+ return -E2BIG;
|
||||
+
|
||||
+ /* We need either an FD array or data to send. If there's nothing, return an error. */
|
||||
+ if (n_fds_array == 0 && !iov)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (n_fds_array > 0) {
|
||||
+ mh.msg_controllen = CMSG_SPACE(sizeof(int) * n_fds_array);
|
||||
+ mh.msg_control = cmsg = malloc(mh.msg_controllen);
|
||||
+ if (!cmsg)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ *cmsg = (struct cmsghdr) {
|
||||
+ .cmsg_len = CMSG_LEN(sizeof(int) * n_fds_array),
|
||||
+ .cmsg_level = SOL_SOCKET,
|
||||
+ .cmsg_type = SCM_RIGHTS,
|
||||
+ };
|
||||
+ memcpy(CMSG_DATA(cmsg), fds_array, sizeof(int) * n_fds_array);
|
||||
+ }
|
||||
+ k = sendmsg(transport_fd, &mh, MSG_NOSIGNAL | flags);
|
||||
+ if (k < 0)
|
||||
+ return (ssize_t) -errno;
|
||||
+
|
||||
+ return k;
|
||||
+}
|
||||
+
|
||||
ssize_t send_one_fd_iov_sa(
|
||||
int transport_fd,
|
||||
int fd,
|
||||
diff --git a/src/basic/socket-util.h b/src/basic/socket-util.h
|
||||
index 2e36e1a56b..61bf8ff32b 100644
|
||||
--- a/src/basic/socket-util.h
|
||||
+++ b/src/basic/socket-util.h
|
||||
@@ -153,6 +153,13 @@ int getpeercred(int fd, struct ucred *ucred);
|
||||
int getpeersec(int fd, char **ret);
|
||||
int getpeergroups(int fd, gid_t **ret);
|
||||
|
||||
+ssize_t send_many_fds_iov_sa(
|
||||
+ int transport_fd,
|
||||
+ int *fds_array, size_t n_fds_array,
|
||||
+ const struct iovec *iov, size_t iovlen,
|
||||
+ const struct sockaddr *sa, socklen_t len,
|
||||
+ int flags);
|
||||
+
|
||||
ssize_t send_one_fd_iov_sa(
|
||||
int transport_fd,
|
||||
int fd,
|
||||
@@ -163,6 +170,14 @@ int send_one_fd_sa(int transport_fd,
|
||||
int fd,
|
||||
const struct sockaddr *sa, socklen_t len,
|
||||
int flags);
|
||||
+static inline int send_many_fds(
|
||||
+ int transport_fd,
|
||||
+ int *fds_array,
|
||||
+ size_t n_fds_array,
|
||||
+ int flags) {
|
||||
+
|
||||
+ return send_many_fds_iov_sa(transport_fd, fds_array, n_fds_array, NULL, 0, NULL, 0, flags);
|
||||
+}
|
||||
#define send_one_fd_iov(transport_fd, fd, iov, iovlen, flags) send_one_fd_iov_sa(transport_fd, fd, iov, iovlen, NULL, 0, flags)
|
||||
#define send_one_fd(transport_fd, fd, flags) send_one_fd_iov_sa(transport_fd, fd, NULL, 0, NULL, 0, flags)
|
||||
ssize_t receive_one_fd_iov(int transport_fd, struct iovec *iov, size_t iovlen, int flags, int *ret_fd);
|
||||
diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c
|
||||
index b9c5f3ad04..dca78fa72c 100644
|
||||
--- a/src/coredump/coredump.c
|
||||
+++ b/src/coredump/coredump.c
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "coredump-vacuum.h"
|
||||
#include "dirent-util.h"
|
||||
#include "elf-util.h"
|
||||
+#include "env-util.h"
|
||||
#include "escape.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
@@ -36,6 +37,7 @@
|
||||
#include "main-func.h"
|
||||
#include "memory-util.h"
|
||||
#include "mkdir-label.h"
|
||||
+#include "namespace-util.h"
|
||||
#include "parse-util.h"
|
||||
#include "process-util.h"
|
||||
#include "signal-util.h"
|
||||
@@ -130,6 +132,8 @@ typedef struct Context {
|
||||
const char *meta[_META_MAX];
|
||||
size_t meta_size[_META_MAX];
|
||||
pid_t pid;
|
||||
+ uid_t uid;
|
||||
+ gid_t gid;
|
||||
bool is_pid1;
|
||||
bool is_journald;
|
||||
} Context;
|
||||
@@ -866,36 +870,11 @@ static int get_process_container_parent_cmdline(pid_t pid, char** cmdline) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
-static int change_uid_gid(const Context *context) {
|
||||
- uid_t uid;
|
||||
- gid_t gid;
|
||||
- int r;
|
||||
-
|
||||
- r = parse_uid(context->meta[META_ARGV_UID], &uid);
|
||||
- if (r < 0)
|
||||
- return r;
|
||||
-
|
||||
- if (uid_is_system(uid)) {
|
||||
- const char *user = "systemd-coredump";
|
||||
-
|
||||
- r = get_user_creds(&user, &uid, &gid, NULL, NULL, 0);
|
||||
- if (r < 0) {
|
||||
- log_warning_errno(r, "Cannot resolve %s user. Proceeding to dump core as root: %m", user);
|
||||
- uid = gid = 0;
|
||||
- }
|
||||
- } else {
|
||||
- r = parse_gid(context->meta[META_ARGV_GID], &gid);
|
||||
- if (r < 0)
|
||||
- return r;
|
||||
- }
|
||||
-
|
||||
- return drop_privileges(uid, gid, 0);
|
||||
-}
|
||||
-
|
||||
static int submit_coredump(
|
||||
const Context *context,
|
||||
struct iovec_wrapper *iovw,
|
||||
- int input_fd) {
|
||||
+ int input_fd,
|
||||
+ int mntns_fd) {
|
||||
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *json_metadata = NULL;
|
||||
_cleanup_close_ int coredump_fd = -1, coredump_node_fd = -1;
|
||||
@@ -938,15 +917,6 @@ static int submit_coredump(
|
||||
/* Vacuum again, but exclude the coredump we just created */
|
||||
(void) coredump_vacuum(coredump_node_fd >= 0 ? coredump_node_fd : coredump_fd, arg_keep_free, arg_max_use);
|
||||
|
||||
- /* Now, let's drop privileges to become the user who owns the segfaulted process
|
||||
- * and allocate the coredump memory under the user's uid. This also ensures that
|
||||
- * the credentials journald will see are the ones of the coredumping user, thus
|
||||
- * making sure the user gets access to the core dump. Let's also get rid of all
|
||||
- * capabilities, if we run as root, we won't need them anymore. */
|
||||
- r = change_uid_gid(context);
|
||||
- if (r < 0)
|
||||
- return log_error_errno(r, "Failed to drop privileges: %m");
|
||||
-
|
||||
/* Try to get a stack trace if we can */
|
||||
if (coredump_size > arg_process_size_max)
|
||||
log_debug("Not generating stack trace: core size %"PRIu64" is greater "
|
||||
@@ -956,12 +926,23 @@ static int submit_coredump(
|
||||
bool skip = startswith(context->meta[META_COMM], "systemd-coredum"); /* COMM is 16 bytes usually */
|
||||
|
||||
(void) parse_elf_object(coredump_fd,
|
||||
+ mntns_fd,
|
||||
+ context->uid,
|
||||
+ context->gid,
|
||||
context->meta[META_EXE],
|
||||
/* fork_disable_dump= */ skip, /* avoid loops */
|
||||
&stacktrace,
|
||||
&json_metadata);
|
||||
}
|
||||
|
||||
+ /* Now, let's drop privileges to become the user who owns the segfaulted process. This also ensures
|
||||
+ * that the credentials journald will see are the ones of the coredumping user, thus making sure
|
||||
+ * the user gets access to the core dump. Let's also get rid of all capabilities, if we run as root,
|
||||
+ * we won't need them anymore. */
|
||||
+ r = drop_privileges(context->uid, context->gid, 0);
|
||||
+ if (r < 0)
|
||||
+ return log_error_errno(r, "Failed to drop privileges: %m");
|
||||
+
|
||||
log:
|
||||
core_message = strjoina("Process ", context->meta[META_ARGV_PID],
|
||||
" (", context->meta[META_COMM], ") of user ",
|
||||
@@ -1094,6 +1075,15 @@ static int save_context(Context *context, const struct iovec_wrapper *iovw) {
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse PID \"%s\": %m", context->meta[META_ARGV_PID]);
|
||||
|
||||
+ r = parse_uid(context->meta[META_ARGV_UID], &context->uid);
|
||||
+ if (r < 0)
|
||||
+ return log_error_errno(r, "Failed to parse UID \"%s\": %m", context->meta[META_ARGV_UID]);
|
||||
+
|
||||
+ r = parse_gid(context->meta[META_ARGV_GID], &context->gid);
|
||||
+ if (r < 0)
|
||||
+ return log_error_errno(r, "Failed to parse GID \"%s\": %m", context->meta[META_ARGV_GID]);
|
||||
+
|
||||
+
|
||||
unit = context->meta[META_UNIT];
|
||||
context->is_pid1 = streq(context->meta[META_ARGV_PID], "1") || streq_ptr(unit, SPECIAL_INIT_SCOPE);
|
||||
context->is_journald = streq_ptr(unit, SPECIAL_JOURNALD_SERVICE);
|
||||
@@ -1102,11 +1092,11 @@ static int save_context(Context *context, const struct iovec_wrapper *iovw) {
|
||||
}
|
||||
|
||||
static int process_socket(int fd) {
|
||||
- _cleanup_close_ int input_fd = -1;
|
||||
+ _cleanup_close_ int input_fd = -EBADF, mntns_fd = -EBADF;
|
||||
Context context = {};
|
||||
struct iovec_wrapper iovw = {};
|
||||
struct iovec iovec;
|
||||
- int r;
|
||||
+ int iterations = 0, r;
|
||||
|
||||
assert(fd >= 0);
|
||||
|
||||
@@ -1146,23 +1136,39 @@ static int process_socket(int fd) {
|
||||
goto finish;
|
||||
}
|
||||
|
||||
- /* The final zero-length datagram carries the file descriptor and tells us
|
||||
+ /* The final zero-length datagram carries the file descriptors and tells us
|
||||
* that we're done. */
|
||||
if (n == 0) {
|
||||
struct cmsghdr *found;
|
||||
|
||||
free(iovec.iov_base);
|
||||
|
||||
- found = cmsg_find(&mh, SOL_SOCKET, SCM_RIGHTS, CMSG_LEN(sizeof(int)));
|
||||
- if (!found) {
|
||||
- cmsg_close_all(&mh);
|
||||
- r = log_error_errno(SYNTHETIC_ERRNO(EBADMSG),
|
||||
- "Coredump file descriptor missing.");
|
||||
- goto finish;
|
||||
+ found = cmsg_find(&mh, SOL_SOCKET, SCM_RIGHTS, CMSG_LEN(sizeof(int) * 2));
|
||||
+ if (found) {
|
||||
+ int fds[2] = { -EBADF, -EBADF };
|
||||
+
|
||||
+ memcpy(fds, CMSG_DATA(found), sizeof(int) * 2);
|
||||
+
|
||||
+ assert(mntns_fd < 0);
|
||||
+
|
||||
+ /* Maybe we already got coredump FD in previous iteration? */
|
||||
+ safe_close(input_fd);
|
||||
+
|
||||
+ input_fd = fds[0];
|
||||
+ mntns_fd = fds[1];
|
||||
+
|
||||
+ /* We have all FDs we need let's take a shortcut here. */
|
||||
+ break;
|
||||
+ } else {
|
||||
+ found = cmsg_find(&mh, SOL_SOCKET, SCM_RIGHTS, CMSG_LEN(sizeof(int)));
|
||||
+ if (found)
|
||||
+ input_fd = *CMSG_DATA(found);
|
||||
}
|
||||
|
||||
- assert(input_fd < 0);
|
||||
- input_fd = *(int*) CMSG_DATA(found);
|
||||
+ /* This is the first message that carries file descriptors, maybe there will be one more that actually contains array of descriptors. */
|
||||
+ if (iterations++ == 0)
|
||||
+ continue;
|
||||
+
|
||||
break;
|
||||
} else
|
||||
cmsg_close_all(&mh);
|
||||
@@ -1177,7 +1183,11 @@ static int process_socket(int fd) {
|
||||
}
|
||||
|
||||
/* Make sure we got all data we really need */
|
||||
- assert(input_fd >= 0);
|
||||
+ if (input_fd < 0) {
|
||||
+ r = log_error_errno(SYNTHETIC_ERRNO(EBADMSG),
|
||||
+ "Coredump file descriptor missing.");
|
||||
+ goto finish;
|
||||
+ }
|
||||
|
||||
r = save_context(&context, &iovw);
|
||||
if (r < 0)
|
||||
@@ -1192,15 +1202,15 @@ static int process_socket(int fd) {
|
||||
goto finish;
|
||||
}
|
||||
|
||||
- r = submit_coredump(&context, &iovw, input_fd);
|
||||
+ r = submit_coredump(&context, &iovw, input_fd, mntns_fd);
|
||||
|
||||
finish:
|
||||
iovw_free_contents(&iovw, true);
|
||||
return r;
|
||||
}
|
||||
|
||||
-static int send_iovec(const struct iovec_wrapper *iovw, int input_fd) {
|
||||
- _cleanup_close_ int fd = -1;
|
||||
+static int send_iovec(const struct iovec_wrapper *iovw, int input_fd, int mntns_fd) {
|
||||
+ _cleanup_close_ int fd = -EBADF;
|
||||
int r;
|
||||
|
||||
assert(iovw);
|
||||
@@ -1256,6 +1266,12 @@ static int send_iovec(const struct iovec_wrapper *iovw, int input_fd) {
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to send coredump fd: %m");
|
||||
|
||||
+ if (mntns_fd >= 0) {
|
||||
+ r = send_many_fds(fd, (int[]) { input_fd, mntns_fd }, 2, 0);
|
||||
+ if (r < 0)
|
||||
+ return log_error_errno(r, "Failed to send coredump fds: %m");
|
||||
+ }
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1428,7 +1444,7 @@ static int gather_pid_metadata(struct iovec_wrapper *iovw, Context *context) {
|
||||
static int process_kernel(int argc, char* argv[]) {
|
||||
Context context = {};
|
||||
struct iovec_wrapper *iovw;
|
||||
- int r;
|
||||
+ int r, mntns_fd = -EBADF;
|
||||
|
||||
/* When we're invoked by the kernel, stdout/stderr are closed which is dangerous because the fds
|
||||
* could get reallocated. To avoid hard to debug issues, let's instead bind stdout/stderr to
|
||||
@@ -1462,6 +1478,25 @@ static int process_kernel(int argc, char* argv[]) {
|
||||
log_open();
|
||||
}
|
||||
|
||||
+ r = in_same_namespace(getpid_cached(), context.pid, NAMESPACE_PID);
|
||||
+ if (r < 0)
|
||||
+ log_debug_errno(r, "Failed to check pidns of crashing process, ignoring: %m");
|
||||
+
|
||||
+ if (r == 0 && getenv_bool("SYSTEMD_COREDUMP_ALLOW_NAMESPACE_CHANGE") > 0) {
|
||||
+ r = namespace_open(context.pid, NULL, &mntns_fd, NULL, NULL, NULL);
|
||||
+ if (r < 0)
|
||||
+ return log_error_errno(r, "Failed to open mntns of crashing process: %m");
|
||||
+ } else {
|
||||
+ /* Crashing process is not running in the container or changing namespace is disabled, but we
|
||||
+ still need to send mount namespace fd along side coredump fd so let's just open our own
|
||||
+ mount namespace. Entering it will be NOP but that is OK. */
|
||||
+ r = namespace_open(getpid_cached(), NULL, &mntns_fd, NULL, NULL, NULL);
|
||||
+ if (r < 0)
|
||||
+ return log_error_errno(r, "Failed to open our mntns: %m");
|
||||
+ }
|
||||
+
|
||||
+ assert(mntns_fd >= 0 && fd_is_ns(mntns_fd, CLONE_NEWNS) > 0);
|
||||
+
|
||||
/* If this is PID 1 disable coredump collection, we'll unlikely be able to process
|
||||
* it later on.
|
||||
*
|
||||
@@ -1474,9 +1509,9 @@ static int process_kernel(int argc, char* argv[]) {
|
||||
}
|
||||
|
||||
if (context.is_journald || context.is_pid1)
|
||||
- r = submit_coredump(&context, iovw, STDIN_FILENO);
|
||||
+ r = submit_coredump(&context, iovw, STDIN_FILENO, mntns_fd);
|
||||
else
|
||||
- r = send_iovec(iovw, STDIN_FILENO);
|
||||
+ r = send_iovec(iovw, STDIN_FILENO, mntns_fd);
|
||||
|
||||
finish:
|
||||
iovw = iovw_free_free(iovw);
|
||||
diff --git a/src/shared/elf-util.c b/src/shared/elf-util.c
|
||||
index bde5013b92..6a2969732d 100644
|
||||
--- a/src/shared/elf-util.c
|
||||
+++ b/src/shared/elf-util.c
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
+#include "capability-util.h"
|
||||
#include "dlfcn-util.h"
|
||||
#include "elf-util.h"
|
||||
#include "errno-util.h"
|
||||
@@ -21,9 +22,12 @@
|
||||
#include "hexdecoct.h"
|
||||
#include "io-util.h"
|
||||
#include "macro.h"
|
||||
+#include "namespace-util.h"
|
||||
#include "process-util.h"
|
||||
#include "rlimit-util.h"
|
||||
#include "string-util.h"
|
||||
+#include "uid-alloc-range.h"
|
||||
+#include "user-util.h"
|
||||
#include "util.h"
|
||||
|
||||
#define FRAMES_MAX 64
|
||||
@@ -752,11 +756,27 @@ static int parse_elf(int fd, const char *executable, char **ret, JsonVariant **r
|
||||
return 0;
|
||||
}
|
||||
|
||||
-int parse_elf_object(int fd, const char *executable, bool fork_disable_dump, char **ret, JsonVariant **ret_package_metadata) {
|
||||
+static int core_change_uid_gid(uid_t uid, gid_t gid) {
|
||||
+ uid_t u = uid;
|
||||
+ gid_t g = gid;
|
||||
+ int r;
|
||||
+
|
||||
+ if (uid_is_system(u)) {
|
||||
+ const char *user = "systemd-coredump";
|
||||
+
|
||||
+ r = get_user_creds(&user, &u, &g, NULL, NULL, 0);
|
||||
+ if (r < 0)
|
||||
+ log_warning_errno(r, "Cannot resolve %s user, ignoring: %m", user);
|
||||
+ }
|
||||
+
|
||||
+ return drop_privileges(u, g, 0);
|
||||
+}
|
||||
+
|
||||
+int parse_elf_object(int fd, int mntns_fd, uid_t uid, gid_t gid, const char *executable, bool fork_disable_dump, char **ret, JsonVariant **ret_package_metadata) {
|
||||
_cleanup_close_pair_ int error_pipe[2] = { -1, -1 }, return_pipe[2] = { -1, -1 }, json_pipe[2] = { -1, -1 };
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *package_metadata = NULL;
|
||||
_cleanup_free_ char *buf = NULL;
|
||||
- int r;
|
||||
+ int flags, r;
|
||||
|
||||
assert(fd >= 0);
|
||||
|
||||
@@ -784,6 +804,10 @@ int parse_elf_object(int fd, const char *executable, bool fork_disable_dump, cha
|
||||
return r;
|
||||
}
|
||||
|
||||
+ flags = FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE|FORK_NEW_USERNS|FORK_WAIT|FORK_REOPEN_LOG;
|
||||
+ if (mntns_fd >= 0)
|
||||
+ flags &= ~(FORK_CLOSE_ALL_FDS|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE|FORK_NEW_USERNS);
|
||||
+
|
||||
/* Parsing possibly malformed data is crash-happy, so fork. In case we crash,
|
||||
* the core file will not be lost, and the messages will still be attached to
|
||||
* the journal. Reading the elf object might be slow, but it still has an upper
|
||||
@@ -793,7 +817,7 @@ int parse_elf_object(int fd, const char *executable, bool fork_disable_dump, cha
|
||||
r = safe_fork_full("(sd-parse-elf)",
|
||||
(int[]){ fd, error_pipe[1], return_pipe[1], json_pipe[1] },
|
||||
4,
|
||||
- FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE|FORK_NEW_USERNS|FORK_WAIT|FORK_REOPEN_LOG,
|
||||
+ flags,
|
||||
NULL);
|
||||
if (r < 0) {
|
||||
if (r == -EPROTO) { /* We should have the errno from the child, but don't clobber original error */
|
||||
@@ -811,6 +835,22 @@ int parse_elf_object(int fd, const char *executable, bool fork_disable_dump, cha
|
||||
return r;
|
||||
}
|
||||
if (r == 0) {
|
||||
+ if (mntns_fd >= 0) {
|
||||
+ r = namespace_enter(/* pidns_fd = */ -EBADF,
|
||||
+ mntns_fd,
|
||||
+ /* netns_fd = */ -EBADF,
|
||||
+ /* userns_fd = */ -EBADF,
|
||||
+ /* root_fd = */ -EBADF);
|
||||
+ if (r < 0)
|
||||
+ log_notice_errno(r, "Failed to enter mount namespace of crashing process, ignoring: %m");
|
||||
+ }
|
||||
+
|
||||
+ if (uid != UID_NOBODY && gid != GID_NOBODY) {
|
||||
+ r = core_change_uid_gid(uid, gid);
|
||||
+ if (r < 0)
|
||||
+ log_notice_errno(r, "Failed to drop privileges, ignoring: %m");
|
||||
+ }
|
||||
+
|
||||
/* We want to avoid loops, given this can be called from systemd-coredump */
|
||||
if (fork_disable_dump) {
|
||||
r = RET_NERRNO(prctl(PR_SET_DUMPABLE, 0));
|
||||
diff --git a/src/shared/elf-util.h b/src/shared/elf-util.h
|
||||
index b28e64cea6..350464941f 100644
|
||||
--- a/src/shared/elf-util.h
|
||||
+++ b/src/shared/elf-util.h
|
||||
@@ -10,9 +10,9 @@ int dlopen_elf(void);
|
||||
/* Parse an ELF object in a forked process, so that errors while iterating over
|
||||
* untrusted and potentially malicious data do not propagate to the main caller's process.
|
||||
* If fork_disable_dump, the child process will not dump core if it crashes. */
|
||||
-int parse_elf_object(int fd, const char *executable, bool fork_disable_dump, char **ret, JsonVariant **ret_package_metadata);
|
||||
+int parse_elf_object(int fd, int mntns_fd, uid_t uid, gid_t gid, const char *executable, bool fork_disable_dump, char **ret, JsonVariant **ret_package_metadata);
|
||||
#else
|
||||
-static inline int parse_elf_object(int fd, const char *executable, bool fork_disable_dump, char **ret, JsonVariant **ret_package_metadata) {
|
||||
+static inline int parse_elf_object(int fd, int mntns_fd, uid_t uid, gid_t gid, const char *executable, bool fork_disable_dump, char **ret, JsonVariant **ret_package_metadata) {
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "elfutils disabled, parsing ELF objects not supported");
|
||||
}
|
||||
#endif
|
@ -0,0 +1,194 @@
|
||||
From ab1212eb3880ef8f9b59c2145efa1f289f02c8c4 Mon Sep 17 00:00:00 2001
|
||||
From: Frantisek Sumsal <frantisek@sumsal.cz>
|
||||
Date: Tue, 21 Mar 2023 23:19:41 +0100
|
||||
Subject: [PATCH] test: add a couple of tests for systemd-coredump
|
||||
|
||||
(cherry picked from commit aadbd81f7ffbc313d0541c15455211dddeedbfde)
|
||||
|
||||
Related: RHEL-34061
|
||||
---
|
||||
test/units/testsuite-74.coredump.sh | 175 ++++++++++++++++++++++++++++
|
||||
1 file changed, 175 insertions(+)
|
||||
create mode 100755 test/units/testsuite-74.coredump.sh
|
||||
|
||||
diff --git a/test/units/testsuite-74.coredump.sh b/test/units/testsuite-74.coredump.sh
|
||||
new file mode 100755
|
||||
index 0000000000..6a299ecbfb
|
||||
--- /dev/null
|
||||
+++ b/test/units/testsuite-74.coredump.sh
|
||||
@@ -0,0 +1,175 @@
|
||||
+#!/usr/bin/env bash
|
||||
+# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
+set -eux
|
||||
+set -o pipefail
|
||||
+
|
||||
+# Make sure the binary name fits into 15 characters
|
||||
+CORE_TEST_BIN="/tmp/test-dump"
|
||||
+CORE_TEST_UNPRIV_BIN="/tmp/test-usr-dump"
|
||||
+MAKE_DUMP_SCRIPT="/tmp/make-dump"
|
||||
+# Unset $PAGER so we don't have to use --no-pager everywhere
|
||||
+export PAGER=
|
||||
+
|
||||
+at_exit() {
|
||||
+ rm -fv -- "$CORE_TEST_BIN" "$CORE_TEST_UNPRIV_BIN" "$MAKE_DUMP_SCRIPT"
|
||||
+}
|
||||
+
|
||||
+trap at_exit EXIT
|
||||
+
|
||||
+if systemd-detect-virt -cq; then
|
||||
+ echo "Running in a container, skipping the systemd-coredump test..."
|
||||
+ exit 0
|
||||
+fi
|
||||
+
|
||||
+# Check that we're the ones to receive coredumps
|
||||
+sysctl kernel.core_pattern | grep systemd-coredump
|
||||
+
|
||||
+# Prepare "fake" binaries for coredumps, so we can properly exercise
|
||||
+# the matching stuff too
|
||||
+cp -vf /bin/sleep "${CORE_TEST_BIN:?}"
|
||||
+cp -vf /bin/sleep "${CORE_TEST_UNPRIV_BIN:?}"
|
||||
+# Simple script that spawns given "fake" binary and then kills it with
|
||||
+# given signal
|
||||
+cat >"${MAKE_DUMP_SCRIPT:?}" <<\EOF
|
||||
+#!/bin/bash -ex
|
||||
+
|
||||
+bin="${1:?}"
|
||||
+sig="${2:?}"
|
||||
+
|
||||
+ulimit -c unlimited
|
||||
+"$bin" infinity &
|
||||
+pid=$!
|
||||
+sleep 1
|
||||
+kill -s "$sig" "$pid"
|
||||
+# This should always fail
|
||||
+! wait "$pid"
|
||||
+EOF
|
||||
+chmod +x "$MAKE_DUMP_SCRIPT"
|
||||
+
|
||||
+# Privileged stuff
|
||||
+[[ "$(id -u)" -eq 0 ]]
|
||||
+# Trigger a couple of coredumps
|
||||
+"$MAKE_DUMP_SCRIPT" "$CORE_TEST_BIN" "SIGTRAP"
|
||||
+"$MAKE_DUMP_SCRIPT" "$CORE_TEST_BIN" "SIGABRT"
|
||||
+# In the tests we store the coredumps in journals, so let's generate a couple
|
||||
+# with Storage=external as well
|
||||
+mkdir -p /run/systemd/coredump.conf.d/
|
||||
+printf '[Coredump]\nStorage=external' >/run/systemd/coredump.conf.d/99-external.conf
|
||||
+"$MAKE_DUMP_SCRIPT" "$CORE_TEST_BIN" "SIGTRAP"
|
||||
+"$MAKE_DUMP_SCRIPT" "$CORE_TEST_BIN" "SIGABRT"
|
||||
+rm -fv /run/systemd/coredump.conf.d/99-external.conf
|
||||
+# Wait a bit for the coredumps to get processed
|
||||
+timeout 30 bash -c "while [[ $(coredumpctl list -q --no-legend $CORE_TEST_BIN | wc -l) -lt 4 ]]; do sleep 1; done"
|
||||
+
|
||||
+coredumpctl
|
||||
+SYSTEMD_LOG_LEVEL=debug coredumpctl
|
||||
+coredumpctl --help
|
||||
+coredumpctl --version
|
||||
+coredumpctl --no-pager --no-legend
|
||||
+coredumpctl --all
|
||||
+coredumpctl -1
|
||||
+coredumpctl -n 1
|
||||
+coredumpctl --reverse
|
||||
+coredumpctl -F COREDUMP_EXE
|
||||
+coredumpctl --json=short | jq
|
||||
+coredumpctl --json=pretty | jq
|
||||
+coredumpctl --json=off
|
||||
+coredumpctl --root=/
|
||||
+coredumpctl --directory=/var/log/journal
|
||||
+coredumpctl --file="/var/log/journal/$(</etc/machine-id)/system.journal"
|
||||
+coredumpctl --since=@0
|
||||
+coredumpctl --since=yesterday --until=tomorrow
|
||||
+# We should have a couple of externally stored coredumps
|
||||
+coredumpctl --field=COREDUMP_FILENAME | tee /tmp/coredumpctl.out
|
||||
+grep "/var/lib/systemd/coredump/core" /tmp/coredumpctl.out
|
||||
+rm -f /tmp/coredumpctl.out
|
||||
+
|
||||
+coredumpctl info
|
||||
+coredumpctl info "$CORE_TEST_BIN"
|
||||
+coredumpctl info /foo /bar/ /baz "$CORE_TEST_BIN"
|
||||
+coredumpctl info "${CORE_TEST_BIN##*/}"
|
||||
+coredumpctl info foo bar baz "${CORE_TEST_BIN##*/}"
|
||||
+coredumpctl info COREDUMP_EXE="$CORE_TEST_BIN"
|
||||
+coredumpctl info COREDUMP_EXE=aaaaa COREDUMP_EXE= COREDUMP_EXE="$CORE_TEST_BIN"
|
||||
+
|
||||
+coredumpctl debug --debugger=/bin/true "$CORE_TEST_BIN"
|
||||
+SYSTEMD_DEBUGGER=/bin/true coredumpctl debug "$CORE_TEST_BIN"
|
||||
+coredumpctl debug --debugger=/bin/true --debugger-arguments="-this --does --not 'do anything' -a -t --all" "${CORE_TEST_BIN##*/}"
|
||||
+
|
||||
+coredumpctl dump "$CORE_TEST_BIN" >/tmp/core.redirected
|
||||
+test -s /tmp/core.redirected
|
||||
+coredumpctl dump -o /tmp/core.output "${CORE_TEST_BIN##*/}"
|
||||
+test -s /tmp/core.output
|
||||
+rm -f /tmp/core.{output,redirected}
|
||||
+
|
||||
+# Unprivileged stuff
|
||||
+# Related issue: https://github.com/systemd/systemd/issues/26912
|
||||
+UNPRIV_CMD=(systemd-run --user --wait --pipe -M "testuser@.host" --)
|
||||
+# Trigger a couple of coredumps as an unprivileged user
|
||||
+"${UNPRIV_CMD[@]}" "$MAKE_DUMP_SCRIPT" "$CORE_TEST_UNPRIV_BIN" "SIGTRAP"
|
||||
+"${UNPRIV_CMD[@]}" "$MAKE_DUMP_SCRIPT" "$CORE_TEST_UNPRIV_BIN" "SIGABRT"
|
||||
+# In the tests we store the coredumps in journals, so let's generate a couple
|
||||
+# with Storage=external as well
|
||||
+mkdir -p /run/systemd/coredump.conf.d/
|
||||
+printf '[Coredump]\nStorage=external' >/run/systemd/coredump.conf.d/99-external.conf
|
||||
+"${UNPRIV_CMD[@]}" "$MAKE_DUMP_SCRIPT" "$CORE_TEST_UNPRIV_BIN" "SIGTRAP"
|
||||
+"${UNPRIV_CMD[@]}" "$MAKE_DUMP_SCRIPT" "$CORE_TEST_UNPRIV_BIN" "SIGABRT"
|
||||
+rm -fv /run/systemd/coredump.conf.d/99-external.conf
|
||||
+# Wait a bit for the coredumps to get processed
|
||||
+timeout 30 bash -c "while [[ $(coredumpctl list -q --no-legend $CORE_TEST_UNPRIV_BIN | wc -l) -lt 4 ]]; do sleep 1; done"
|
||||
+
|
||||
+# root should see coredumps from both binaries
|
||||
+coredumpctl info "$CORE_TEST_UNPRIV_BIN"
|
||||
+coredumpctl info "${CORE_TEST_UNPRIV_BIN##*/}"
|
||||
+# The test user should see only their own coredumps
|
||||
+"${UNPRIV_CMD[@]}" coredumpctl
|
||||
+"${UNPRIV_CMD[@]}" coredumpctl info "$CORE_TEST_UNPRIV_BIN"
|
||||
+"${UNPRIV_CMD[@]}" coredumpctl info "${CORE_TEST_UNPRIV_BIN##*/}"
|
||||
+(! "${UNPRIV_CMD[@]}" coredumpctl info --all "$CORE_TEST_BIN")
|
||||
+(! "${UNPRIV_CMD[@]}" coredumpctl info --all "${CORE_TEST_BIN##*/}")
|
||||
+# We should have a couple of externally stored coredumps
|
||||
+"${UNPRIV_CMD[@]}" coredumpctl --field=COREDUMP_FILENAME | tee /tmp/coredumpctl.out
|
||||
+grep "/var/lib/systemd/coredump/core" /tmp/coredumpctl.out
|
||||
+rm -f /tmp/coredumpctl.out
|
||||
+
|
||||
+"${UNPRIV_CMD[@]}" coredumpctl debug --debugger=/bin/true "$CORE_TEST_UNPRIV_BIN"
|
||||
+"${UNPRIV_CMD[@]}" coredumpctl debug --debugger=/bin/true --debugger-arguments="-this --does --not 'do anything' -a -t --all" "${CORE_TEST_UNPRIV_BIN##*/}"
|
||||
+
|
||||
+"${UNPRIV_CMD[@]}" coredumpctl dump "$CORE_TEST_UNPRIV_BIN" >/tmp/core.redirected
|
||||
+test -s /tmp/core.redirected
|
||||
+"${UNPRIV_CMD[@]}" coredumpctl dump -o /tmp/core.output "${CORE_TEST_UNPRIV_BIN##*/}"
|
||||
+test -s /tmp/core.output
|
||||
+rm -f /tmp/core.{output,redirected}
|
||||
+(! "${UNPRIV_CMD[@]}" coredumpctl dump "$CORE_TEST_BIN" >/dev/null)
|
||||
+
|
||||
+# --backtrace mode
|
||||
+# Pass one of the existing journal coredump records to systemd-coredump and
|
||||
+# use our PID as the source to make matching the coredump later easier
|
||||
+# systemd-coredump args: PID UID GID SIGNUM TIMESTAMP CORE_SOFT_RLIMIT HOSTNAME
|
||||
+journalctl -b -n 1 --output=export --output-fields=MESSAGE,COREDUMP COREDUMP_EXE="/usr/bin/test-dump" |
|
||||
+ /usr/lib/systemd/systemd-coredump --backtrace $$ 0 0 6 1679509994 12345 mymachine
|
||||
+# Wait a bit for the coredump to get processed
|
||||
+timeout 30 bash -c "while [[ $(coredumpctl list -q --no-legend $$ | wc -l) -eq 0 ]]; do sleep 1; done"
|
||||
+coredumpctl info "$$"
|
||||
+coredumpctl info COREDUMP_HOSTNAME="mymachine"
|
||||
+
|
||||
+
|
||||
+(! coredumpctl --hello-world)
|
||||
+(! coredumpctl -n 0)
|
||||
+(! coredumpctl -n -1)
|
||||
+(! coredumpctl --file=/dev/null)
|
||||
+(! coredumpctl --since=0)
|
||||
+(! coredumpctl --until='')
|
||||
+(! coredumpctl --since=today --until=yesterday)
|
||||
+(! coredumpctl --directory=/ --root=/)
|
||||
+(! coredumpctl --json=foo)
|
||||
+(! coredumpctl -F foo -F bar)
|
||||
+(! coredumpctl list 0)
|
||||
+(! coredumpctl list -- -1)
|
||||
+(! coredumpctl list '')
|
||||
+(! coredumpctl info /../.~=)
|
||||
+(! coredumpctl info '')
|
||||
+(! coredumpctl dump --output=/dev/full "$CORE_TEST_BIN")
|
||||
+(! coredumpctl dump --output=/dev/null --output=/dev/null "$CORE_TEST_BIN")
|
||||
+(! coredumpctl debug --debugger=/bin/false)
|
||||
+(! coredumpctl debug --debugger=/bin/true --debugger-arguments='"')
|
@ -0,0 +1,54 @@
|
||||
From 67b33be5be12ea7500d54a78961acbe76126e8ed Mon Sep 17 00:00:00 2001
|
||||
From: Frantisek Sumsal <frantisek@sumsal.cz>
|
||||
Date: Sat, 25 Mar 2023 12:02:15 +0100
|
||||
Subject: [PATCH] test: don't expand the subshell expression prematurely
|
||||
|
||||
We need to expand the subshell expression during the `bash -c`
|
||||
invocation, not before, to take the desired effect, as now it expands to:
|
||||
|
||||
timeout 30 bash -c 'while [[ 0 -eq 0 ]]; do sleep 1; done'
|
||||
|
||||
instead of the expected:
|
||||
|
||||
timeout 30 bash -c 'while [[ $(coredumpctl list -q --no-legend 770 | wc -l) -eq 0 ]]; do sleep 1; done'
|
||||
|
||||
Follow-up to aadbd81f7f.
|
||||
|
||||
(cherry picked from commit 0b189ac84c432a085a1f10139260cec6b5032523)
|
||||
|
||||
Related: RHEL-34061
|
||||
---
|
||||
test/units/testsuite-74.coredump.sh | 6 +++---
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/test/units/testsuite-74.coredump.sh b/test/units/testsuite-74.coredump.sh
|
||||
index 6a299ecbfb..3910abe0ec 100755
|
||||
--- a/test/units/testsuite-74.coredump.sh
|
||||
+++ b/test/units/testsuite-74.coredump.sh
|
||||
@@ -59,7 +59,7 @@ printf '[Coredump]\nStorage=external' >/run/systemd/coredump.conf.d/99-external.
|
||||
"$MAKE_DUMP_SCRIPT" "$CORE_TEST_BIN" "SIGABRT"
|
||||
rm -fv /run/systemd/coredump.conf.d/99-external.conf
|
||||
# Wait a bit for the coredumps to get processed
|
||||
-timeout 30 bash -c "while [[ $(coredumpctl list -q --no-legend $CORE_TEST_BIN | wc -l) -lt 4 ]]; do sleep 1; done"
|
||||
+timeout 30 bash -c "while [[ \$(coredumpctl list -q --no-legend $CORE_TEST_BIN | wc -l) -lt 4 ]]; do sleep 1; done"
|
||||
|
||||
coredumpctl
|
||||
SYSTEMD_LOG_LEVEL=debug coredumpctl
|
||||
@@ -116,7 +116,7 @@ printf '[Coredump]\nStorage=external' >/run/systemd/coredump.conf.d/99-external.
|
||||
"${UNPRIV_CMD[@]}" "$MAKE_DUMP_SCRIPT" "$CORE_TEST_UNPRIV_BIN" "SIGABRT"
|
||||
rm -fv /run/systemd/coredump.conf.d/99-external.conf
|
||||
# Wait a bit for the coredumps to get processed
|
||||
-timeout 30 bash -c "while [[ $(coredumpctl list -q --no-legend $CORE_TEST_UNPRIV_BIN | wc -l) -lt 4 ]]; do sleep 1; done"
|
||||
+timeout 30 bash -c "while [[ \$(coredumpctl list -q --no-legend $CORE_TEST_UNPRIV_BIN | wc -l) -lt 4 ]]; do sleep 1; done"
|
||||
|
||||
# root should see coredumps from both binaries
|
||||
coredumpctl info "$CORE_TEST_UNPRIV_BIN"
|
||||
@@ -149,7 +149,7 @@ rm -f /tmp/core.{output,redirected}
|
||||
journalctl -b -n 1 --output=export --output-fields=MESSAGE,COREDUMP COREDUMP_EXE="/usr/bin/test-dump" |
|
||||
/usr/lib/systemd/systemd-coredump --backtrace $$ 0 0 6 1679509994 12345 mymachine
|
||||
# Wait a bit for the coredump to get processed
|
||||
-timeout 30 bash -c "while [[ $(coredumpctl list -q --no-legend $$ | wc -l) -eq 0 ]]; do sleep 1; done"
|
||||
+timeout 30 bash -c "while [[ \$(coredumpctl list -q --no-legend $$ | wc -l) -eq 0 ]]; do sleep 1; done"
|
||||
coredumpctl info "$$"
|
||||
coredumpctl info COREDUMP_HOSTNAME="mymachine"
|
||||
|
@ -0,0 +1,63 @@
|
||||
From 8eab546a3468dcb1ed714ec02c927ea2f5141645 Mon Sep 17 00:00:00 2001
|
||||
From: Luca Boccassi <bluca@debian.org>
|
||||
Date: Wed, 26 Apr 2023 14:18:04 +0100
|
||||
Subject: [PATCH] coredump filter: fix stack overflow with =all
|
||||
|
||||
We translate 'all' to UNIT64_MAX, which has a lot more 'f's. Use the
|
||||
helper macro, since a decimal uint64_t will always be >> than a hex
|
||||
representation.
|
||||
|
||||
root@image:~# systemd-run -t --property CoredumpFilter=all ls /tmp
|
||||
Running as unit: run-u13.service
|
||||
Press ^] three times within 1s to disconnect TTY.
|
||||
*** stack smashing detected ***: terminated
|
||||
[137256.320511] systemd[1]: run-u13.service: Main process exited, code=dumped, status=6/ABRT
|
||||
[137256.320850] systemd[1]: run-u13.service: Failed with result 'core-dump'.
|
||||
|
||||
(cherry picked from commit 37232d55a7bcace37280e28b207c85f5ca9b3f6b)
|
||||
|
||||
Related: RHEL-34061
|
||||
---
|
||||
src/basic/macro.h | 4 ++++
|
||||
src/shared/coredump-util.c | 5 +++--
|
||||
2 files changed, 7 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/basic/macro.h b/src/basic/macro.h
|
||||
index 2d378454a2..6893a1ff32 100644
|
||||
--- a/src/basic/macro.h
|
||||
+++ b/src/basic/macro.h
|
||||
@@ -268,6 +268,10 @@ static inline int __coverity_check_and_return__(int condition) {
|
||||
|
||||
#define sizeof_field(struct_type, member) sizeof(((struct_type *) 0)->member)
|
||||
|
||||
+/* Maximum buffer size needed for formatting an unsigned integer type as hex, including space for '0x'
|
||||
+ * prefix and trailing NUL suffix. */
|
||||
+#define HEXADECIMAL_STR_MAX(type) (2 + sizeof(type) * 2 + 1)
|
||||
+
|
||||
/* Returns the number of chars needed to format variables of the specified type as a decimal string. Adds in
|
||||
* extra space for a negative '-' prefix for signed types. Includes space for the trailing NUL. */
|
||||
#define DECIMAL_STR_MAX(type) \
|
||||
diff --git a/src/shared/coredump-util.c b/src/shared/coredump-util.c
|
||||
index a0b648bf79..aaf3e16eff 100644
|
||||
--- a/src/shared/coredump-util.c
|
||||
+++ b/src/shared/coredump-util.c
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "coredump-util.h"
|
||||
#include "extract-word.h"
|
||||
#include "fileio.h"
|
||||
+#include "stdio-util.h"
|
||||
#include "string-table.h"
|
||||
|
||||
static const char *const coredump_filter_table[_COREDUMP_FILTER_MAX] = {
|
||||
@@ -65,9 +66,9 @@ int coredump_filter_mask_from_string(const char *s, uint64_t *ret) {
|
||||
}
|
||||
|
||||
int set_coredump_filter(uint64_t value) {
|
||||
- char t[STRLEN("0xFFFFFFFF")];
|
||||
+ char t[HEXADECIMAL_STR_MAX(uint64_t)];
|
||||
|
||||
- sprintf(t, "0x%"PRIx64, value);
|
||||
+ xsprintf(t, "0x%"PRIx64, value);
|
||||
|
||||
return write_string_file("/proc/self/coredump_filter", t,
|
||||
WRITE_STRING_FILE_VERIFY_ON_FAILURE|WRITE_STRING_FILE_DISABLE_BUFFER);
|
@ -0,0 +1,59 @@
|
||||
From 88d675ef77a4cdebbb7f1367679fc349de487f75 Mon Sep 17 00:00:00 2001
|
||||
From: Luca Boccassi <bluca@debian.org>
|
||||
Date: Wed, 26 Apr 2023 14:19:33 +0100
|
||||
Subject: [PATCH] coredump filter: add mask for 'all' using UINT32_MAX, not
|
||||
UINT64_MAX
|
||||
|
||||
The kernel returns ERANGE when UINT64_MAX is passed. Create a mask
|
||||
and use UINT32_max, which is accepted, so that future bits will also
|
||||
be set.
|
||||
|
||||
(cherry picked from commit 7f3bb8f20dcccaceea8b1ee05f0560b81162037b)
|
||||
|
||||
Related: RHEL-34061
|
||||
---
|
||||
src/shared/coredump-util.c | 2 +-
|
||||
src/shared/coredump-util.h | 3 +++
|
||||
src/test/test-coredump-util.c | 2 ++
|
||||
3 files changed, 6 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/shared/coredump-util.c b/src/shared/coredump-util.c
|
||||
index aaf3e16eff..7a44816834 100644
|
||||
--- a/src/shared/coredump-util.c
|
||||
+++ b/src/shared/coredump-util.c
|
||||
@@ -43,7 +43,7 @@ int coredump_filter_mask_from_string(const char *s, uint64_t *ret) {
|
||||
}
|
||||
|
||||
if (streq(n, "all")) {
|
||||
- m = UINT64_MAX;
|
||||
+ m = COREDUMP_FILTER_MASK_ALL;
|
||||
continue;
|
||||
}
|
||||
|
||||
diff --git a/src/shared/coredump-util.h b/src/shared/coredump-util.h
|
||||
index 09e7ed443f..f4d4098136 100644
|
||||
--- a/src/shared/coredump-util.h
|
||||
+++ b/src/shared/coredump-util.h
|
||||
@@ -22,6 +22,9 @@ typedef enum CoredumpFilter {
|
||||
1u << COREDUMP_FILTER_ELF_HEADERS | \
|
||||
1u << COREDUMP_FILTER_PRIVATE_HUGE)
|
||||
|
||||
+/* The kernel doesn't like UINT64_MAX and returns ERANGE, use UINT32_MAX to support future new flags */
|
||||
+#define COREDUMP_FILTER_MASK_ALL UINT32_MAX
|
||||
+
|
||||
const char* coredump_filter_to_string(CoredumpFilter i) _const_;
|
||||
CoredumpFilter coredump_filter_from_string(const char *s) _pure_;
|
||||
int coredump_filter_mask_from_string(const char *s, uint64_t *ret);
|
||||
diff --git a/src/test/test-coredump-util.c b/src/test/test-coredump-util.c
|
||||
index 40b68df9f4..87dc371a88 100644
|
||||
--- a/src/test/test-coredump-util.c
|
||||
+++ b/src/test/test-coredump-util.c
|
||||
@@ -23,6 +23,8 @@ TEST(coredump_filter_mask_from_string) {
|
||||
uint64_t f;
|
||||
assert_se(coredump_filter_mask_from_string("default", &f) == 0);
|
||||
assert_se(f == COREDUMP_FILTER_MASK_DEFAULT);
|
||||
+ assert_se(coredump_filter_mask_from_string("all", &f) == 0);
|
||||
+ assert_se(f == COREDUMP_FILTER_MASK_ALL);
|
||||
|
||||
assert_se(coredump_filter_mask_from_string(" default\tdefault\tdefault ", &f) == 0);
|
||||
assert_se(f == COREDUMP_FILTER_MASK_DEFAULT);
|
@ -0,0 +1,26 @@
|
||||
From 2d16eaf0c4151ecb308452375661960eab3ec3c8 Mon Sep 17 00:00:00 2001
|
||||
From: Luca Boccassi <bluca@debian.org>
|
||||
Date: Wed, 26 Apr 2023 14:32:04 +0100
|
||||
Subject: [PATCH] test: add coverage for CoredumpFilter=all
|
||||
|
||||
(cherry picked from commit cf636aa59eb8c848ed04d5b08aac0acf3f6683d9)
|
||||
|
||||
Related: RHEL-34061
|
||||
---
|
||||
test/units/testsuite-74.coredump.sh | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/test/units/testsuite-74.coredump.sh b/test/units/testsuite-74.coredump.sh
|
||||
index 3910abe0ec..0e5d050f45 100755
|
||||
--- a/test/units/testsuite-74.coredump.sh
|
||||
+++ b/test/units/testsuite-74.coredump.sh
|
||||
@@ -153,6 +153,9 @@ timeout 30 bash -c "while [[ \$(coredumpctl list -q --no-legend $$ | wc -l) -eq
|
||||
coredumpctl info "$$"
|
||||
coredumpctl info COREDUMP_HOSTNAME="mymachine"
|
||||
|
||||
+# This used to cause a stack overflow
|
||||
+systemd-run -t --property CoredumpFilter=all ls /tmp
|
||||
+systemd-run -t --property CoredumpFilter=default ls /tmp
|
||||
|
||||
(! coredumpctl --hello-world)
|
||||
(! coredumpctl -n 0)
|
@ -0,0 +1,52 @@
|
||||
From 9bac78b7b359e063bfb43a2fb358195c0a6608e8 Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
Date: Wed, 24 May 2023 10:31:41 +0900
|
||||
Subject: [PATCH] test: rotate journal before storing coredumps
|
||||
|
||||
Hopefully fixes the failure like
|
||||
https://jenkins-systemd.apps.ocp.cloud.ci.centos.org/job/upstream-vagrant-archlinux-sanitizers/2558/
|
||||
---
|
||||
[ 66.708894] testsuite-74.sh[728]: + coredumpctl --json=off
|
||||
[ 66.709344] testsuite-74.sh[826]: TIME PID UID GID SIG COREFILE EXE SIZE
|
||||
[ 66.709773] testsuite-74.sh[826]: Tue 2023-05-23 22:10:17 UTC 739 0 0 SIGTRAP journal /tmp/test-dump -
|
||||
[ 66.711134] testsuite-74.sh[826]: Tue 2023-05-23 22:10:18 UTC 747 0 0 SIGABRT journal /tmp/test-dump -
|
||||
[ 66.711789] testsuite-74.sh[826]: Tue 2023-05-23 22:10:19 UTC 763 0 0 SIGTRAP present /tmp/test-dump 53.5K
|
||||
[ 66.712460] testsuite-74.sh[826]: Tue 2023-05-23 22:10:20 UTC 776 0 0 SIGABRT present /tmp/test-dump 53.3K
|
||||
[ 66.713505] testsuite-74.sh[728]: + coredumpctl --root=/
|
||||
[ 66.714144] testsuite-74.sh[828]: TIME PID UID GID SIG COREFILE EXE SIZE
|
||||
[ 66.714535] testsuite-74.sh[828]: Tue 2023-05-23 22:10:17 UTC 739 0 0 SIGTRAP journal /tmp/test-dump -
|
||||
[ 66.715208] testsuite-74.sh[828]: Tue 2023-05-23 22:10:18 UTC 747 0 0 SIGABRT journal /tmp/test-dump -
|
||||
[ 66.715907] testsuite-74.sh[828]: Tue 2023-05-23 22:10:19 UTC 763 0 0 SIGTRAP present /tmp/test-dump 53.5K
|
||||
[ 66.716565] testsuite-74.sh[828]: Tue 2023-05-23 22:10:20 UTC 776 0 0 SIGABRT present /tmp/test-dump 53.3K
|
||||
[ 66.717494] testsuite-74.sh[728]: + coredumpctl --directory=/var/log/journal
|
||||
[ 66.718188] testsuite-74.sh[830]: TIME PID UID GID SIG COREFILE EXE SIZE
|
||||
[ 66.882072] testsuite-74.sh[830]: Tue 2023-05-23 22:10:17 UTC 739 0 0 SIGTRAP journal /tmp/test-dump -
|
||||
[ 66.882642] testsuite-74.sh[830]: Tue 2023-05-23 22:10:18 UTC 747 0 0 SIGABRT journal /tmp/test-dump -
|
||||
[ 66.883450] testsuite-74.sh[830]: Tue 2023-05-23 22:10:19 UTC 763 0 0 SIGTRAP present /tmp/test-dump 53.5K
|
||||
[ 66.883944] testsuite-74.sh[830]: Tue 2023-05-23 22:10:20 UTC 776 0 0 SIGABRT present /tmp/test-dump 53.3K
|
||||
[ 66.885448] testsuite-74.sh[728]: + coredumpctl --file=/var/log/journal/2e1ed84be19a4e22adfc99ad849be1f6/system.journal
|
||||
[ 66.885989] testsuite-74.sh[728]: + at_exit
|
||||
[ 66.894162] coredumpctl[833]: No coredumps found.
|
||||
---
|
||||
|
||||
(cherry picked from commit 5c4e96c28c4a2193ba0dd459ea3366614f9b262f)
|
||||
|
||||
Related: RHEL-34061
|
||||
---
|
||||
test/units/testsuite-74.coredump.sh | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/test/units/testsuite-74.coredump.sh b/test/units/testsuite-74.coredump.sh
|
||||
index 0e5d050f45..d5039b70f4 100755
|
||||
--- a/test/units/testsuite-74.coredump.sh
|
||||
+++ b/test/units/testsuite-74.coredump.sh
|
||||
@@ -21,6 +21,9 @@ if systemd-detect-virt -cq; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
+# To make all coredump entries stored in system.journal.
|
||||
+journalctl --rotate
|
||||
+
|
||||
# Check that we're the ones to receive coredumps
|
||||
sysctl kernel.core_pattern | grep systemd-coredump
|
||||
|
@ -0,0 +1,77 @@
|
||||
From 43c604a8ed7f436c9c123d4e53dc9b3d7192522d Mon Sep 17 00:00:00 2001
|
||||
From: Frantisek Sumsal <frantisek@sumsal.cz>
|
||||
Date: Fri, 2 Jun 2023 13:24:32 +0200
|
||||
Subject: [PATCH] test: sync with the fake binary before killing it
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
On faster machines we might be too fast and kill the fake binary during
|
||||
fork() which then makes kernel report a "wrong" binary in the coredump,
|
||||
e.g.:
|
||||
|
||||
[ 31.408078] testsuite-74.sh[548]: + /tmp/make-dump /tmp/test-dump SIGTRAP
|
||||
[ 31.409720] testsuite-74.sh[560]: + bin=/tmp/test-dump
|
||||
[ 31.409720] testsuite-74.sh[560]: + sig=SIGTRAP
|
||||
[ 31.409720] testsuite-74.sh[560]: + ulimit -c unlimited
|
||||
[ 31.409720] testsuite-74.sh[560]: + pid=561
|
||||
[ 31.409720] testsuite-74.sh[560]: + sleep 1
|
||||
[ 31.409720] testsuite-74.sh[560]: + kill -s SIGTRAP 561
|
||||
[ 31.409720] testsuite-74.sh[560]: + wait 561
|
||||
[ 31.491757] systemd[1]: Created slice system-systemd\x2dcoredump.slice.
|
||||
[ 31.524488] systemd[1]: Started systemd-coredump@0-563-0.service.
|
||||
[ 31.616372] systemd-coredump[564]: [🡕] Process 561 (make-dump) of user 0 dumped core.
|
||||
|
||||
Stack trace of thread 561:
|
||||
#0 0x00007ff86bb49af7 _Fork (libc.so.6 + 0xd4af7)
|
||||
#1 0x00007ff86bb4965f __libc_fork (libc.so.6 + 0xd465f)
|
||||
#2 0x000055e88011b0ad make_child (bash + 0x550ad)
|
||||
#3 0x000055e8800fd05f n/a (bash + 0x3705f)
|
||||
#4 0x000055e880100116 execute_command_internal (bash + 0x3a116)
|
||||
#5 0x000055e8801011f2 execute_command_internal (bash + 0x3b1f2)
|
||||
#6 0x000055e8801025b6 execute_command (bash + 0x3c5b6)
|
||||
#7 0x000055e8800f134b reader_loop (bash + 0x2b34b)
|
||||
#8 0x000055e8800e757d main (bash + 0x2157d)
|
||||
#9 0x00007ff86ba98850 n/a (libc.so.6 + 0x23850)
|
||||
#10 0x00007ff86ba9890a __libc_start_main (libc.so.6 + 0x2390a)
|
||||
#11 0x000055e8800e83b5 _start (bash + 0x223b5)
|
||||
ELF object binary architecture: AMD x86-64
|
||||
[ 31.666617] testsuite-74.sh[560]: /tmp/make-dump: line 12: 561 Trace/breakpoint trap (core dumped) "$bin" infinity
|
||||
...
|
||||
$ coredumpctl list --file system.journal
|
||||
TIME PID UID GID SIG COREFILE EXE SIZE
|
||||
Fri 2023-06-02 10:42:10 CEST 561 0 0 SIGTRAP journal /usr/bin/bash -
|
||||
Fri 2023-06-02 10:42:11 CEST 570 0 0 SIGABRT journal /tmp/test-dump -
|
||||
Fri 2023-06-02 10:42:12 CEST 582 0 0 SIGTRAP missing /tmp/test-dump -
|
||||
Fri 2023-06-02 10:42:13 CEST 593 0 0 SIGABRT missing /tmp/test-dump -
|
||||
|
||||
(cherry picked from commit 1326d2dd059132760b40acb7a715ecc9ff08bd35)
|
||||
|
||||
Related: RHEL-34061
|
||||
---
|
||||
test/units/testsuite-74.coredump.sh | 12 +++++++++++-
|
||||
1 file changed, 11 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/test/units/testsuite-74.coredump.sh b/test/units/testsuite-74.coredump.sh
|
||||
index d5039b70f4..d30fd73717 100755
|
||||
--- a/test/units/testsuite-74.coredump.sh
|
||||
+++ b/test/units/testsuite-74.coredump.sh
|
||||
@@ -42,7 +42,17 @@ sig="${2:?}"
|
||||
ulimit -c unlimited
|
||||
"$bin" infinity &
|
||||
pid=$!
|
||||
-sleep 1
|
||||
+# Sync with the "fake" binary, so we kill it once it's fully forked off,
|
||||
+# otherwise we might kill it during fork and kernel would then report
|
||||
+# "wrong" binary name (i.e. $MAKE_DUMP_SCRIPT instead of $CORE_TEST_BIN).
|
||||
+# In this case, wait until the "fake" binary (sleep in this case) enters
|
||||
+# the "interruptible sleep" state, at which point it should be ready
|
||||
+# to be sacrificed.
|
||||
+for _ in {0..9}; do
|
||||
+ read -ra self_stat <"/proc/$pid/stat"
|
||||
+ [[ "${self_stat[2]}" == S ]] && break
|
||||
+ sleep .5
|
||||
+done
|
||||
kill -s "$sig" "$pid"
|
||||
# This should always fail
|
||||
! wait "$pid"
|
@ -0,0 +1,112 @@
|
||||
From a8924006c47a680f038d9ff66fd3896ffbc37bc1 Mon Sep 17 00:00:00 2001
|
||||
From: Frantisek Sumsal <frantisek@sumsal.cz>
|
||||
Date: Thu, 25 Apr 2024 19:50:10 +0200
|
||||
Subject: [PATCH] test: check coredump handling in containers & namespaces
|
||||
|
||||
This is partially based on upstream's 097e28736a, which tests coredump
|
||||
forwarding (that we don't have in RHEL 9). It also provides basic
|
||||
coverage for RHEL-29430 (generating stack traces for processes in
|
||||
containers without coredump fowarding).
|
||||
|
||||
rhel-only
|
||||
Related: RHEL-34061
|
||||
---
|
||||
test/test-functions | 2 +-
|
||||
test/units/testsuite-74.coredump.sh | 64 ++++++++++++++++++++++++++++-
|
||||
2 files changed, 64 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/test/test-functions b/test/test-functions
|
||||
index 1608644cbb..947f8589c5 100644
|
||||
--- a/test/test-functions
|
||||
+++ b/test/test-functions
|
||||
@@ -2619,7 +2619,7 @@ inst_binary() {
|
||||
# ls, stat - pulls in nss_systemd with certain options (like ls -l) when
|
||||
# nsswitch.conf uses [SUCCESS=merge] (like on Arch Linux)
|
||||
# tar - called by machinectl in TEST-25
|
||||
- if get_bool "$IS_BUILT_WITH_ASAN" && [[ "$bin" =~ /(chown|getent|login|ls|stat|su|tar|useradd|userdel)$ ]]; then
|
||||
+ if get_bool "$IS_BUILT_WITH_ASAN" && [[ "$bin" =~ /(chown|getent|login|id|ls|stat|su|tar|useradd|userdel)$ ]]; then
|
||||
wrap_binary=1
|
||||
fi
|
||||
|
||||
diff --git a/test/units/testsuite-74.coredump.sh b/test/units/testsuite-74.coredump.sh
|
||||
index d30fd73717..1093cad8a9 100755
|
||||
--- a/test/units/testsuite-74.coredump.sh
|
||||
+++ b/test/units/testsuite-74.coredump.sh
|
||||
@@ -74,6 +74,68 @@ rm -fv /run/systemd/coredump.conf.d/99-external.conf
|
||||
# Wait a bit for the coredumps to get processed
|
||||
timeout 30 bash -c "while [[ \$(coredumpctl list -q --no-legend $CORE_TEST_BIN | wc -l) -lt 4 ]]; do sleep 1; done"
|
||||
|
||||
+# RHEL9: following part is taken out of 097e28736aed9280dfac0f8e8096deca71bac813 but slightly tweaked, since
|
||||
+# in RHEL9 we don't have the support for coredump forwarding
|
||||
+CONTAINER="testsuite-74-container"
|
||||
+TESTUSER_UID="$(id -u testuser)"
|
||||
+TESTUSER_GID="$(id -g testuser)"
|
||||
+
|
||||
+mkdir -p "/var/lib/machines/$CONTAINER"
|
||||
+mkdir -p "/run/systemd/system/systemd-nspawn@$CONTAINER.service.d"
|
||||
+# Bind-mounting /etc into the container kinda defeats the purpose of --volatile=,
|
||||
+# but we need the ASan-related overrides scattered across /etc
|
||||
+cat > "/run/systemd/system/systemd-nspawn@$CONTAINER.service.d/override.conf" << EOF
|
||||
+[Service]
|
||||
+ExecStart=
|
||||
+ExecStart=systemd-nspawn --quiet --link-journal=try-guest --keep-unit --machine=%i --boot \
|
||||
+ --volatile=yes --directory=/ --bind-ro=/etc --inaccessible=/etc/machine-id
|
||||
+EOF
|
||||
+systemctl daemon-reload
|
||||
+
|
||||
+machinectl start "$CONTAINER"
|
||||
+timeout 60 bash -xec "until systemd-run -M '$CONTAINER' -q --wait --pipe true; do sleep .5; done"
|
||||
+machinectl copy-to "$CONTAINER" "$MAKE_DUMP_SCRIPT"
|
||||
+
|
||||
+run_namespaced_coredump_tests() {
|
||||
+ local TS
|
||||
+
|
||||
+ # Make a couple of coredumps in a full-fleged container
|
||||
+ TS="$(date +"%s.%N")"
|
||||
+ [[ "$(coredumpctl list --since="@$TS" -q --no-legend /usr/bin/sleep | wc -l)" -eq 0 ]]
|
||||
+ [[ "$(coredumpctl list --since="@$TS" -q --no-legend /usr/bin/sleep _UID="$TESTUSER_UID" | wc -l)" -eq 0 ]]
|
||||
+ systemd-run -M "testuser@$CONTAINER" --user -q --wait --pipe "$MAKE_DUMP_SCRIPT" "/usr/bin/sleep" "SIGABRT"
|
||||
+ systemd-run -M "$CONTAINER" -q --wait --pipe "$MAKE_DUMP_SCRIPT" "/usr/bin/sleep" "SIGTRAP"
|
||||
+ # Wait a bit for the coredumps to get processed
|
||||
+ timeout 30 bash -c "while [[ \$(coredumpctl list --since=@$TS -q --no-legend /usr/bin/sleep | wc -l) -ne 2 ]]; do sleep 1; done"
|
||||
+ coredumpctl list
|
||||
+ [[ "$(coredumpctl list --since="@$TS" -q --no-legend /usr/bin/sleep _UID="$TESTUSER_UID" _GID="$TESTUSER_GID" | wc -l)" -eq 1 ]]
|
||||
+
|
||||
+ # Simplified version of the above - not a full container, just a mount & pid namespace
|
||||
+ TS="$(date +"%s.%N")"
|
||||
+ unshare --mount --pid --fork --mount-proc /bin/bash -xec "$MAKE_DUMP_SCRIPT /usr/bin/sleep SIGABRT"
|
||||
+ timeout 30 bash -c "while [[ \$(coredumpctl list --since=@$TS -q --no-legend /usr/bin/sleep | wc -l) -ne 1 ]]; do sleep 1; done"
|
||||
+ TS="$(date +"%s.%N")"
|
||||
+ unshare --setuid="$TESTUSER_UID" --setgid="$TESTUSER_GID" --mount --pid --fork --mount-proc /bin/bash -xec "$MAKE_DUMP_SCRIPT /usr/bin/sleep SIGABRT"
|
||||
+ timeout 30 bash -c "while [[ \$(coredumpctl list --since=@$TS -q --no-legend /usr/bin/sleep _UID=$TESTUSER_UID _GID=$TESTUSER_GID | wc -l) -ne 1 ]]; do sleep 1; done"
|
||||
+}
|
||||
+
|
||||
+# First, run the tests with default systemd-coredumpd settings
|
||||
+run_namespaced_coredump_tests
|
||||
+
|
||||
+# And now with SYSTEMD_COREDUMP_ALLOW_NAMESPACE_CHANGE=1 (RHEL-only)
|
||||
+cat >/tmp/coredump-handler.sh <<EOF
|
||||
+#!/bin/bash
|
||||
+export SYSTEMD_COREDUMP_ALLOW_NAMESPACE_CHANGE=1
|
||||
+exec /usr/lib/systemd/systemd-coredump "\$@"
|
||||
+EOF
|
||||
+chmod +x /tmp/coredump-handler.sh
|
||||
+sysctl -w kernel.core_pattern="|/tmp/coredump-handler.sh %P %u %g %s %t %c %h"
|
||||
+run_namespaced_coredump_tests
|
||||
+
|
||||
+# Restore the original coredump handler
|
||||
+sysctl -p /usr/lib/sysctl.d/50-coredump.conf
|
||||
+sysctl kernel.core_pattern
|
||||
+
|
||||
coredumpctl
|
||||
SYSTEMD_LOG_LEVEL=debug coredumpctl
|
||||
coredumpctl --help
|
||||
@@ -89,7 +151,7 @@ coredumpctl --json=pretty | jq
|
||||
coredumpctl --json=off
|
||||
coredumpctl --root=/
|
||||
coredumpctl --directory=/var/log/journal
|
||||
-coredumpctl --file="/var/log/journal/$(</etc/machine-id)/system.journal"
|
||||
+coredumpctl --file="/var/log/journal/$(</etc/machine-id)"/*.journal
|
||||
coredumpctl --since=@0
|
||||
coredumpctl --since=yesterday --until=tomorrow
|
||||
# We should have a couple of externally stored coredumps
|
@ -0,0 +1,42 @@
|
||||
From 93759e2eedd282e57455735326d99b0dd3356a8a Mon Sep 17 00:00:00 2001
|
||||
From: Frantisek Sumsal <frantisek@sumsal.cz>
|
||||
Date: Sat, 23 Dec 2023 12:20:03 +0100
|
||||
Subject: [PATCH] ukify: make the test happy with the latest OpenSSL
|
||||
|
||||
Which dropped some whitespaces in the output:
|
||||
|
||||
$ openssl version
|
||||
OpenSSL 3.2.0 23 Nov 2023 (Library: OpenSSL 3.2.0 23 Nov 2023)
|
||||
$ openssl x509 -in cert.pem -text -noout | grep Issuer
|
||||
Issuer: C=AU, ST=Some-State, O=Internet Widgits Pty Ltd
|
||||
|
||||
$ openssl version
|
||||
OpenSSL 3.0.9 30 May 2023 (Library: OpenSSL 3.0.9 30 May 2023)
|
||||
$ openssl x509 -in cert.pem -text -noout | grep Issuer
|
||||
Issuer: C = XX, L = Default City, O = Default Company Ltd
|
||||
|
||||
Making test-ukify unhappy:
|
||||
|
||||
> assert 'Issuer: CN = SecureBoot signing key on host' in out
|
||||
E AssertionError: assert 'Issuer: CN = SecureBoot signing key on host' in '<...snip...>Issuer: CN=SecureBoot signing key on host archlinux2\n...'
|
||||
|
||||
(cherry picked from commit 338ed5bea4fcd0b5b1cdcfb96a789edf6251bbdd)
|
||||
|
||||
Resolves: RHEL-34061
|
||||
---
|
||||
src/ukify/test/test_ukify.py | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/ukify/test/test_ukify.py b/src/ukify/test/test_ukify.py
|
||||
index 5a42a94799..31054eabea 100755
|
||||
--- a/src/ukify/test/test_ukify.py
|
||||
+++ b/src/ukify/test/test_ukify.py
|
||||
@@ -850,7 +850,7 @@ def test_key_cert_generation(tmpdir):
|
||||
'-noout',
|
||||
], text = True)
|
||||
assert 'Certificate' in out
|
||||
- assert 'Issuer: CN = SecureBoot signing key on host' in out
|
||||
+ assert re.search('Issuer: CN\s?=\s?SecureBoot signing key on host', out)
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(pytest.main(sys.argv))
|
@ -0,0 +1,44 @@
|
||||
From ba83f030dc2721a317f31f5b7a5884431349074f Mon Sep 17 00:00:00 2001
|
||||
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||
Date: Mon, 18 Mar 2024 17:04:22 +0100
|
||||
Subject: [PATCH] kernel-install: fix uki-copy deinstall
|
||||
|
||||
For "kernel-install remove ..." only the kernel version is passed, not
|
||||
the kernel image. So auto-detecting KERNEL_INSTALL_IMAGE_TYPE and
|
||||
setting KERNEL_INSTALL_LAYOUT does not work for uninstall.
|
||||
|
||||
The 90-uki-copy.install plugin must consider this and *not* exit early
|
||||
for the "remove" command, otherwise $BOOT_ROOT will be filled with stale
|
||||
kernel images.
|
||||
|
||||
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
||||
|
||||
(cherry picked from commit 3037616d8ed68f3263746e3c6399d4a05242068b)
|
||||
|
||||
Resolves: RHEL-35994
|
||||
---
|
||||
src/kernel-install/90-uki-copy.install | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/kernel-install/90-uki-copy.install b/src/kernel-install/90-uki-copy.install
|
||||
index c66c09719c..d443c4b401 100755
|
||||
--- a/src/kernel-install/90-uki-copy.install
|
||||
+++ b/src/kernel-install/90-uki-copy.install
|
||||
@@ -26,8 +26,6 @@ KERNEL_VERSION="${2:?}"
|
||||
ENTRY_DIR_ABS="$3"
|
||||
KERNEL_IMAGE="$4"
|
||||
|
||||
-[ "$KERNEL_INSTALL_LAYOUT" = "uki" ] || exit 0
|
||||
-
|
||||
ENTRY_TOKEN="$KERNEL_INSTALL_ENTRY_TOKEN"
|
||||
BOOT_ROOT="$KERNEL_INSTALL_BOOT_ROOT"
|
||||
|
||||
@@ -48,6 +46,8 @@ case "$COMMAND" in
|
||||
;;
|
||||
esac
|
||||
|
||||
+[ "$KERNEL_INSTALL_LAYOUT" = "uki" ] || exit 0
|
||||
+
|
||||
if ! [ -d "$UKI_DIR" ]; then
|
||||
[ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && echo "creating $UKI_DIR"
|
||||
mkdir -p "$UKI_DIR"
|
@ -0,0 +1,75 @@
|
||||
From 540f1d6b38dc6f2f72785ba7b44ad3cc65243982 Mon Sep 17 00:00:00 2001
|
||||
From: Luca Boccassi <bluca@debian.org>
|
||||
Date: Wed, 15 Feb 2023 00:44:01 +0000
|
||||
Subject: [PATCH] cryptsetup: do not assert when unsealing token without salt
|
||||
|
||||
Salt was added in v253. We are not checking whether it was actually found
|
||||
(non-zero size), so when an old tpm+pin enrollment is opened things go boom.
|
||||
For good measure, check both the buffer and the size in both places.
|
||||
|
||||
Assertion 'saltlen > 0' failed at src/shared/tpm2-util.c:2490, function tpm2_util_pbkdf2_hmac_sha256(). Aborting.
|
||||
|
||||
(cherry picked from commit 504d0acf61c8472bc93c2a927e858074873b2eaf)
|
||||
|
||||
Resolves: RHEL-40119
|
||||
---
|
||||
src/cryptsetup/cryptsetup-tokens/luks2-tpm2.c | 3 ++-
|
||||
src/cryptsetup/cryptsetup-tpm2.c | 4 +++-
|
||||
src/shared/tpm2-util.c | 1 +
|
||||
3 files changed, 6 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/cryptsetup/cryptsetup-tokens/luks2-tpm2.c b/src/cryptsetup/cryptsetup-tokens/luks2-tpm2.c
|
||||
index 630a2d8d3e..e353e947aa 100644
|
||||
--- a/src/cryptsetup/cryptsetup-tokens/luks2-tpm2.c
|
||||
+++ b/src/cryptsetup/cryptsetup-tokens/luks2-tpm2.c
|
||||
@@ -40,6 +40,7 @@ int acquire_luks2_key(
|
||||
_cleanup_(erase_and_freep) char *b64_salted_pin = NULL;
|
||||
int r;
|
||||
|
||||
+ assert(salt || salt_size == 0);
|
||||
assert(ret_decrypted_key);
|
||||
assert(ret_decrypted_key_size);
|
||||
|
||||
@@ -60,7 +61,7 @@ int acquire_luks2_key(
|
||||
if ((flags & TPM2_FLAGS_USE_PIN) && salt && !pin)
|
||||
return -ENOANO;
|
||||
|
||||
- if (pin) {
|
||||
+ if (pin && salt_size > 0) {
|
||||
uint8_t salted_pin[SHA256_DIGEST_SIZE] = {};
|
||||
CLEANUP_ERASE(salted_pin);
|
||||
r = tpm2_util_pbkdf2_hmac_sha256(pin, strlen(pin), salt, salt_size, salted_pin);
|
||||
diff --git a/src/cryptsetup/cryptsetup-tpm2.c b/src/cryptsetup/cryptsetup-tpm2.c
|
||||
index c049b8a313..036f3d3a00 100644
|
||||
--- a/src/cryptsetup/cryptsetup-tpm2.c
|
||||
+++ b/src/cryptsetup/cryptsetup-tpm2.c
|
||||
@@ -88,6 +88,8 @@ int acquire_tpm2_key(
|
||||
const void *blob;
|
||||
int r;
|
||||
|
||||
+ assert(salt || salt_size == 0);
|
||||
+
|
||||
if (!device) {
|
||||
r = tpm2_find_device_auto(&auto_device);
|
||||
if (r == -ENODEV)
|
||||
@@ -165,7 +167,7 @@ int acquire_tpm2_key(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
- if (salt) {
|
||||
+ if (salt_size > 0) {
|
||||
uint8_t salted_pin[SHA256_DIGEST_SIZE] = {};
|
||||
CLEANUP_ERASE(salted_pin);
|
||||
|
||||
diff --git a/src/shared/tpm2-util.c b/src/shared/tpm2-util.c
|
||||
index 4e382f691e..1d2d4ddda4 100644
|
||||
--- a/src/shared/tpm2-util.c
|
||||
+++ b/src/shared/tpm2-util.c
|
||||
@@ -6041,6 +6041,7 @@ int tpm2_util_pbkdf2_hmac_sha256(const void *pass,
|
||||
*/
|
||||
static const uint8_t block_cnt[] = { 0, 0, 0, 1 };
|
||||
|
||||
+ assert (salt);
|
||||
assert (saltlen > 0);
|
||||
assert (saltlen <= (SIZE_MAX - sizeof(block_cnt)));
|
||||
assert (passlen > 0);
|
@ -0,0 +1,29 @@
|
||||
From d22cd36758db25eb9144fbe47f741cd1547b7d0e Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
Date: Fri, 17 Feb 2023 08:24:54 +0900
|
||||
Subject: [PATCH] cryptsetup: check the existence of salt by salt_size > 0
|
||||
|
||||
Follow-up for 504d0acf61c8472bc93c2a927e858074873b2eaf.
|
||||
|
||||
The function may be called with non-NULL salt and salt_size == 0.
|
||||
|
||||
(cherry picked from commit 8c2264abb9c16bc2933f95be299f15ee66c21181)
|
||||
|
||||
Related: RHEL-40119
|
||||
---
|
||||
src/cryptsetup/cryptsetup-tokens/luks2-tpm2.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/cryptsetup/cryptsetup-tokens/luks2-tpm2.c b/src/cryptsetup/cryptsetup-tokens/luks2-tpm2.c
|
||||
index e353e947aa..5230a84025 100644
|
||||
--- a/src/cryptsetup/cryptsetup-tokens/luks2-tpm2.c
|
||||
+++ b/src/cryptsetup/cryptsetup-tokens/luks2-tpm2.c
|
||||
@@ -58,7 +58,7 @@ int acquire_luks2_key(
|
||||
return -ENOANO;
|
||||
|
||||
/* If we're using a PIN, and the luks header has a salt, it better have a pin too */
|
||||
- if ((flags & TPM2_FLAGS_USE_PIN) && salt && !pin)
|
||||
+ if ((flags & TPM2_FLAGS_USE_PIN) && salt_size > 0 && !pin)
|
||||
return -ENOANO;
|
||||
|
||||
if (pin && salt_size > 0) {
|
@ -0,0 +1,38 @@
|
||||
From ebb3f05ef5d2bf3543e61047a658103baa293ca0 Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
Date: Fri, 2 Dec 2022 14:30:22 +0900
|
||||
Subject: [PATCH] bootspec: fix null-dereference-read
|
||||
|
||||
Fixes [oss-fuzz#53578](https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=53578).
|
||||
Fixes #25450.
|
||||
|
||||
(cherry picked from commit 46dc071985ff487f5ccf20808531168a6add73d3)
|
||||
|
||||
Related: RHEL-40119
|
||||
---
|
||||
src/shared/bootspec.c | 2 ++
|
||||
...lusterfuzz-testcase-minimized-fuzz-bootspec-5731869371269120 | 1 +
|
||||
2 files changed, 3 insertions(+)
|
||||
create mode 100644 test/fuzz/fuzz-bootspec/clusterfuzz-testcase-minimized-fuzz-bootspec-5731869371269120
|
||||
|
||||
diff --git a/src/shared/bootspec.c b/src/shared/bootspec.c
|
||||
index 61e20c40a8..7fe8845429 100644
|
||||
--- a/src/shared/bootspec.c
|
||||
+++ b/src/shared/bootspec.c
|
||||
@@ -996,6 +996,8 @@ static int boot_config_find(const BootConfig *config, const char *id) {
|
||||
if (id[0] == '@') {
|
||||
if (!strcaseeq(id, "@saved"))
|
||||
return -1;
|
||||
+ if (!config->entry_selected)
|
||||
+ return -1;
|
||||
id = config->entry_selected;
|
||||
}
|
||||
|
||||
diff --git a/test/fuzz/fuzz-bootspec/clusterfuzz-testcase-minimized-fuzz-bootspec-5731869371269120 b/test/fuzz/fuzz-bootspec/clusterfuzz-testcase-minimized-fuzz-bootspec-5731869371269120
|
||||
new file mode 100644
|
||||
index 0000000000..8804abd094
|
||||
--- /dev/null
|
||||
+++ b/test/fuzz/fuzz-bootspec/clusterfuzz-testcase-minimized-fuzz-bootspec-5731869371269120
|
||||
@@ -0,0 +1 @@
|
||||
+{"config":"default @saved","loader":[""]}
|
||||
\ No newline at end of file
|
Loading…
Reference in new issue