From: Yu Watanabe Date: Wed, 8 Oct 2025 21:10:25 +0000 (+0900) Subject: coredump: split out functions for sending coredump to coredump-send.[ch] X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=4bae593612bcb1dd6bc61cb7dbb4b04593daa42a;p=thirdparty%2Fsystemd.git coredump: split out functions for sending coredump to coredump-send.[ch] --- diff --git a/src/coredump/coredump-send.c b/src/coredump/coredump-send.c new file mode 100644 index 00000000000..da571c5dfa8 --- /dev/null +++ b/src/coredump/coredump-send.c @@ -0,0 +1,334 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include + +#include "sd-messages.h" + +#include "coredump-context.h" +#include "coredump-send.h" +#include "coredump-util.h" +#include "errno-util.h" +#include "fd-util.h" +#include "fs-util.h" +#include "iovec-util.h" +#include "iovec-wrapper.h" +#include "log.h" +#include "namespace-util.h" +#include "path-util.h" +#include "pidref.h" +#include "process-util.h" +#include "socket-util.h" + +int coredump_send(const struct iovec_wrapper *iovw, int input_fd, PidRef *pidref, int mount_tree_fd) { + _cleanup_close_ int fd = -EBADF; + int r; + + assert(iovw); + assert(input_fd >= 0); + + fd = socket(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC, 0); + if (fd < 0) + return log_error_errno(errno, "Failed to create coredump socket: %m"); + + r = connect_unix_path(fd, AT_FDCWD, "/run/systemd/coredump"); + if (r < 0) + return log_error_errno(r, "Failed to connect to coredump service: %m"); + + for (size_t i = 0; i < iovw->count; i++) { + struct msghdr mh = { + .msg_iov = iovw->iovec + i, + .msg_iovlen = 1, + }; + struct iovec copy[2]; + + for (;;) { + if (sendmsg(fd, &mh, MSG_NOSIGNAL) >= 0) + break; + + if (errno == EMSGSIZE && mh.msg_iov[0].iov_len > 0) { + /* This field didn't fit? That's a pity. Given that this is + * just metadata, let's truncate the field at half, and try + * again. We append three dots, in order to show that this is + * truncated. */ + + if (mh.msg_iov != copy) { + /* We don't want to modify the caller's iovec, hence + * let's create our own array, consisting of two new + * iovecs, where the first is a (truncated) copy of + * what we want to send, and the second one contains + * the trailing dots. */ + copy[0] = iovw->iovec[i]; + copy[1] = IOVEC_MAKE(((const char[]){'.', '.', '.'}), 3); + + mh.msg_iov = copy; + mh.msg_iovlen = 2; + } + + copy[0].iov_len /= 2; /* halve it, and try again */ + continue; + } + + return log_error_errno(errno, "Failed to send coredump datagram: %m"); + } + } + + /* First sentinel: the coredump fd */ + r = send_one_fd(fd, input_fd, 0); + if (r < 0) + return log_error_errno(r, "Failed to send coredump fd: %m"); + + /* The optional second sentinel: the pidfd */ + if (!pidref_is_set(pidref) || pidref->fd < 0) /* If we have no pidfd, stop now */ + return 0; + + r = send_one_fd(fd, pidref->fd, 0); + if (r < 0) + return log_error_errno(r, "Failed to send pidfd: %m"); + + /* The optional third sentinel: the mount tree fd */ + if (mount_tree_fd < 0) /* If we have no mount tree, stop now */ + return 0; + + r = send_one_fd(fd, mount_tree_fd, 0); + if (r < 0) + return log_error_errno(r, "Failed to send mount tree fd: %m"); + + return 0; +} + +static int can_forward_coredump(Context *context, const PidRef *pid) { + _cleanup_free_ char *cgroup = NULL, *path = NULL, *unit = NULL; + int r; + + assert(context); + assert(pidref_is_set(pid)); + assert(!pidref_is_remote(pid)); + + /* We need to avoid a situation where the attacker crashes a SUID process or a root daemon and + * quickly replaces it with a namespaced process and we forward the coredump to the attacker, into + * the namespace. With %F/pidfd we can reliably check the namespace of the original process, hence we + * can allow forwarding. */ + if (!context->got_pidfd && context->dumpable != SUID_DUMP_USER) + return false; + + r = cg_pidref_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &cgroup); + if (r < 0) + return r; + + r = path_extract_directory(cgroup, &path); + if (r < 0) + return r; + + r = cg_path_get_unit_path(path, &unit); + if (r == -ENOMEM) + return log_oom(); + if (r == -ENXIO) + /* No valid units in this path. */ + return false; + if (r < 0) + return r; + + /* We require that this process belongs to a delegated cgroup + * (i.e. Delegate=yes), with CoredumpReceive=yes also. */ + r = cg_is_delegated(unit); + if (r <= 0) + return r; + + return cg_has_coredump_receive(unit); +} + +static int send_ucred(int transport_fd, const struct ucred *ucred) { + CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct ucred))) control = {}; + struct msghdr mh = { + .msg_control = &control, + .msg_controllen = sizeof(control), + }; + struct cmsghdr *cmsg; + + assert(transport_fd >= 0); + assert(ucred); + + cmsg = CMSG_FIRSTHDR(&mh); + *cmsg = (struct cmsghdr) { + .cmsg_level = SOL_SOCKET, + .cmsg_type = SCM_CREDENTIALS, + .cmsg_len = CMSG_LEN(sizeof(struct ucred)), + }; + memcpy(CMSG_DATA(cmsg), ucred, sizeof(struct ucred)); + + return RET_NERRNO(sendmsg(transport_fd, &mh, MSG_NOSIGNAL)); +} + +static int receive_ucred(int transport_fd, struct ucred *ret_ucred) { + CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct ucred))) control = {}; + struct msghdr mh = { + .msg_control = &control, + .msg_controllen = sizeof(control), + }; + struct cmsghdr *cmsg = NULL; + struct ucred *ucred = NULL; + ssize_t n; + + assert(transport_fd >= 0); + assert(ret_ucred); + + n = recvmsg_safe(transport_fd, &mh, 0); + if (n < 0) + return n; + + CMSG_FOREACH(cmsg, &mh) + if (cmsg->cmsg_level == SOL_SOCKET && + cmsg->cmsg_type == SCM_CREDENTIALS && + cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) { + + assert(!ucred); + ucred = CMSG_TYPED_DATA(cmsg, struct ucred); + } + + if (!ucred) + return -EIO; + + *ret_ucred = *ucred; + return 0; +} + +int coredump_send_to_container(Context *context) { + _cleanup_close_ int pidnsfd = -EBADF, mntnsfd = -EBADF, netnsfd = -EBADF, usernsfd = -EBADF, rootfd = -EBADF; + _cleanup_close_pair_ int pair[2] = EBADF_PAIR; + pid_t child; + struct ucred ucred = { + .pid = context->pidref.pid, + .uid = context->uid, + .gid = context->gid, + }; + int r; + + assert(context); + + _cleanup_(pidref_done) PidRef leader_pid = PIDREF_NULL; + r = namespace_get_leader(&context->pidref, NAMESPACE_PID, &leader_pid); + if (r < 0) + return log_debug_errno(r, "Failed to get namespace leader: %m"); + + r = can_forward_coredump(context, &leader_pid); + if (r < 0) + return log_debug_errno(r, "Failed to check if coredump can be forwarded: %m"); + if (r == 0) + return log_debug_errno(SYNTHETIC_ERRNO(ENOENT), + "Coredump will not be forwarded because no target cgroup was found."); + + r = RET_NERRNO(socketpair(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, pair)); + if (r < 0) + return log_debug_errno(r, "Failed to create socket pair: %m"); + + r = setsockopt_int(pair[1], SOL_SOCKET, SO_PASSCRED, true); + if (r < 0) + return log_debug_errno(r, "Failed to set SO_PASSCRED: %m"); + + r = pidref_namespace_open(&leader_pid, &pidnsfd, &mntnsfd, &netnsfd, &usernsfd, &rootfd); + if (r < 0) + return log_debug_errno(r, "Failed to open namespaces of PID " PID_FMT ": %m", leader_pid.pid); + + r = namespace_fork("(sd-coredumpns)", "(sd-coredump)", NULL, 0, + FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM, + pidnsfd, mntnsfd, netnsfd, usernsfd, rootfd, &child); + if (r < 0) + return log_debug_errno(r, "Failed to fork into namespaces of PID " PID_FMT ": %m", leader_pid.pid); + if (r == 0) { + pair[0] = safe_close(pair[0]); + + r = access_nofollow("/run/systemd/coredump", W_OK); + if (r < 0) { + log_debug_errno(r, "Cannot find coredump socket, exiting: %m"); + _exit(EXIT_FAILURE); + } + + r = receive_ucred(pair[1], &ucred); + if (r < 0) { + log_debug_errno(r, "Failed to receive ucred and fd: %m"); + _exit(EXIT_FAILURE); + } + + _cleanup_(iovw_free_freep) struct iovec_wrapper *iovw = iovw_new(); + if (!iovw) { + log_oom(); + _exit(EXIT_FAILURE); + } + + (void) iovw_put_string_field(iovw, "MESSAGE_ID=", SD_MESSAGE_COREDUMP_STR); + (void) iovw_put_string_field(iovw, "PRIORITY=", STRINGIFY(LOG_CRIT)); + (void) iovw_put_string_field(iovw, "COREDUMP_FORWARDED=", "1"); + + for (int i = 0; i < _META_ARGV_MAX; i++) { + char buf[DECIMAL_STR_MAX(pid_t)]; + const char *t = context->meta[i]; + + /* Patch some of the fields with the translated ucred data */ + switch (i) { + + case META_ARGV_PID: + xsprintf(buf, PID_FMT, ucred.pid); + t = buf; + break; + + case META_ARGV_UID: + xsprintf(buf, UID_FMT, ucred.uid); + t = buf; + break; + + case META_ARGV_GID: + xsprintf(buf, GID_FMT, ucred.gid); + t = buf; + break; + + default: + ; + } + + r = iovw_put_string_field(iovw, meta_field_names[i], t); + if (r < 0) { + log_debug_errno(r, "Failed to construct iovec: %m"); + _exit(EXIT_FAILURE); + } + } + + _cleanup_(context_done) Context child_context = CONTEXT_NULL; + r = context_parse_iovw(&child_context, iovw); + if (r < 0) { + log_debug_errno(r, "Failed to save context: %m"); + _exit(EXIT_FAILURE); + } + + r = gather_pid_metadata_from_procfs(iovw, &child_context); + if (r < 0) { + log_debug_errno(r, "Failed to gather metadata from procfs: %m"); + _exit(EXIT_FAILURE); + } + + r = coredump_send(iovw, STDIN_FILENO, &context->pidref, /* mount_tree_fd= */ -EBADF); + if (r < 0) { + log_debug_errno(r, "Failed to send iovec to coredump socket: %m"); + _exit(EXIT_FAILURE); + } + + _exit(EXIT_SUCCESS); + } + + pair[1] = safe_close(pair[1]); + + /* We need to translate the PID, UID, and GID of the crashing process + * to the container's namespaces. Do this by sending an SCM_CREDENTIALS + * message on a socket pair, and read the result when we join the + * container. The kernel will perform the translation for us. */ + r = send_ucred(pair[0], &ucred); + if (r < 0) + return log_debug_errno(r, "Failed to send metadata to container: %m"); + + r = wait_for_terminate_and_check("(sd-coredumpns)", child, 0); + if (r < 0) + return log_debug_errno(r, "Failed to wait for child to terminate: %m"); + if (r != EXIT_SUCCESS) + return log_debug_errno(SYNTHETIC_ERRNO(EPROTO), "Failed to process coredump in container."); + + return 0; +} diff --git a/src/coredump/coredump-send.h b/src/coredump/coredump-send.h new file mode 100644 index 00000000000..97ddec26c83 --- /dev/null +++ b/src/coredump/coredump-send.h @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +#pragma once + +#include "coredump-forward.h" + +int coredump_send(const struct iovec_wrapper *iovw, int input_fd, PidRef *pidref, int mount_tree_fd); +int coredump_send_to_container(Context *context); diff --git a/src/coredump/coredump.c b/src/coredump/coredump.c index df85ef447bb..9d348ac7ef5 100644 --- a/src/coredump/coredump.c +++ b/src/coredump/coredump.c @@ -26,6 +26,7 @@ #include "coredump-config.h" #include "coredump-context.h" #include "coredump-receive.h" +#include "coredump-send.h" #include "coredump-submit.h" #include "coredump-util.h" #include "coredump-vacuum.h" @@ -61,321 +62,6 @@ #include "uid-classification.h" #include "user-util.h" -static int send_iovec(const struct iovec_wrapper *iovw, int input_fd, PidRef *pidref, int mount_tree_fd) { - _cleanup_close_ int fd = -EBADF; - int r; - - assert(iovw); - assert(input_fd >= 0); - - fd = socket(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC, 0); - if (fd < 0) - return log_error_errno(errno, "Failed to create coredump socket: %m"); - - r = connect_unix_path(fd, AT_FDCWD, "/run/systemd/coredump"); - if (r < 0) - return log_error_errno(r, "Failed to connect to coredump service: %m"); - - for (size_t i = 0; i < iovw->count; i++) { - struct msghdr mh = { - .msg_iov = iovw->iovec + i, - .msg_iovlen = 1, - }; - struct iovec copy[2]; - - for (;;) { - if (sendmsg(fd, &mh, MSG_NOSIGNAL) >= 0) - break; - - if (errno == EMSGSIZE && mh.msg_iov[0].iov_len > 0) { - /* This field didn't fit? That's a pity. Given that this is - * just metadata, let's truncate the field at half, and try - * again. We append three dots, in order to show that this is - * truncated. */ - - if (mh.msg_iov != copy) { - /* We don't want to modify the caller's iovec, hence - * let's create our own array, consisting of two new - * iovecs, where the first is a (truncated) copy of - * what we want to send, and the second one contains - * the trailing dots. */ - copy[0] = iovw->iovec[i]; - copy[1] = IOVEC_MAKE(((const char[]){'.', '.', '.'}), 3); - - mh.msg_iov = copy; - mh.msg_iovlen = 2; - } - - copy[0].iov_len /= 2; /* halve it, and try again */ - continue; - } - - return log_error_errno(errno, "Failed to send coredump datagram: %m"); - } - } - - /* First sentinel: the coredump fd */ - r = send_one_fd(fd, input_fd, 0); - if (r < 0) - return log_error_errno(r, "Failed to send coredump fd: %m"); - - /* The optional second sentinel: the pidfd */ - if (!pidref_is_set(pidref) || pidref->fd < 0) /* If we have no pidfd, stop now */ - return 0; - - r = send_one_fd(fd, pidref->fd, 0); - if (r < 0) - return log_error_errno(r, "Failed to send pidfd: %m"); - - /* The optional third sentinel: the mount tree fd */ - if (mount_tree_fd < 0) /* If we have no mount tree, stop now */ - return 0; - - r = send_one_fd(fd, mount_tree_fd, 0); - if (r < 0) - return log_error_errno(r, "Failed to send mount tree fd: %m"); - - return 0; -} - -static int send_ucred(int transport_fd, const struct ucred *ucred) { - CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct ucred))) control = {}; - struct msghdr mh = { - .msg_control = &control, - .msg_controllen = sizeof(control), - }; - struct cmsghdr *cmsg; - - assert(transport_fd >= 0); - assert(ucred); - - cmsg = CMSG_FIRSTHDR(&mh); - *cmsg = (struct cmsghdr) { - .cmsg_level = SOL_SOCKET, - .cmsg_type = SCM_CREDENTIALS, - .cmsg_len = CMSG_LEN(sizeof(struct ucred)), - }; - memcpy(CMSG_DATA(cmsg), ucred, sizeof(struct ucred)); - - return RET_NERRNO(sendmsg(transport_fd, &mh, MSG_NOSIGNAL)); -} - -static int receive_ucred(int transport_fd, struct ucred *ret_ucred) { - CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct ucred))) control = {}; - struct msghdr mh = { - .msg_control = &control, - .msg_controllen = sizeof(control), - }; - struct cmsghdr *cmsg = NULL; - struct ucred *ucred = NULL; - ssize_t n; - - assert(transport_fd >= 0); - assert(ret_ucred); - - n = recvmsg_safe(transport_fd, &mh, 0); - if (n < 0) - return n; - - CMSG_FOREACH(cmsg, &mh) - if (cmsg->cmsg_level == SOL_SOCKET && - cmsg->cmsg_type == SCM_CREDENTIALS && - cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) { - - assert(!ucred); - ucred = CMSG_TYPED_DATA(cmsg, struct ucred); - } - - if (!ucred) - return -EIO; - - *ret_ucred = *ucred; - - return 0; -} - -static int can_forward_coredump(Context *context, const PidRef *pid) { - _cleanup_free_ char *cgroup = NULL, *path = NULL, *unit = NULL; - int r; - - assert(context); - assert(pidref_is_set(pid)); - assert(!pidref_is_remote(pid)); - - /* We need to avoid a situation where the attacker crashes a SUID process or a root daemon and - * quickly replaces it with a namespaced process and we forward the coredump to the attacker, into - * the namespace. With %F/pidfd we can reliably check the namespace of the original process, hence we - * can allow forwarding. */ - if (!context->got_pidfd && context->dumpable != SUID_DUMP_USER) - return false; - - r = cg_pidref_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &cgroup); - if (r < 0) - return r; - - r = path_extract_directory(cgroup, &path); - if (r < 0) - return r; - - r = cg_path_get_unit_path(path, &unit); - if (r == -ENOMEM) - return log_oom(); - if (r == -ENXIO) - /* No valid units in this path. */ - return false; - if (r < 0) - return r; - - /* We require that this process belongs to a delegated cgroup - * (i.e. Delegate=yes), with CoredumpReceive=yes also. */ - r = cg_is_delegated(unit); - if (r <= 0) - return r; - - return cg_has_coredump_receive(unit); -} - -static int forward_coredump_to_container(Context *context) { - _cleanup_close_ int pidnsfd = -EBADF, mntnsfd = -EBADF, netnsfd = -EBADF, usernsfd = -EBADF, rootfd = -EBADF; - _cleanup_close_pair_ int pair[2] = EBADF_PAIR; - pid_t child; - struct ucred ucred = { - .pid = context->pidref.pid, - .uid = context->uid, - .gid = context->gid, - }; - int r; - - assert(context); - - _cleanup_(pidref_done) PidRef leader_pid = PIDREF_NULL; - r = namespace_get_leader(&context->pidref, NAMESPACE_PID, &leader_pid); - if (r < 0) - return log_debug_errno(r, "Failed to get namespace leader: %m"); - - r = can_forward_coredump(context, &leader_pid); - if (r < 0) - return log_debug_errno(r, "Failed to check if coredump can be forwarded: %m"); - if (r == 0) - return log_debug_errno(SYNTHETIC_ERRNO(ENOENT), - "Coredump will not be forwarded because no target cgroup was found."); - - r = RET_NERRNO(socketpair(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, pair)); - if (r < 0) - return log_debug_errno(r, "Failed to create socket pair: %m"); - - r = setsockopt_int(pair[1], SOL_SOCKET, SO_PASSCRED, true); - if (r < 0) - return log_debug_errno(r, "Failed to set SO_PASSCRED: %m"); - - r = pidref_namespace_open(&leader_pid, &pidnsfd, &mntnsfd, &netnsfd, &usernsfd, &rootfd); - if (r < 0) - return log_debug_errno(r, "Failed to open namespaces of PID " PID_FMT ": %m", leader_pid.pid); - - r = namespace_fork("(sd-coredumpns)", "(sd-coredump)", NULL, 0, - FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGTERM, - pidnsfd, mntnsfd, netnsfd, usernsfd, rootfd, &child); - if (r < 0) - return log_debug_errno(r, "Failed to fork into namespaces of PID " PID_FMT ": %m", leader_pid.pid); - if (r == 0) { - pair[0] = safe_close(pair[0]); - - r = access_nofollow("/run/systemd/coredump", W_OK); - if (r < 0) { - log_debug_errno(r, "Cannot find coredump socket, exiting: %m"); - _exit(EXIT_FAILURE); - } - - r = receive_ucred(pair[1], &ucred); - if (r < 0) { - log_debug_errno(r, "Failed to receive ucred and fd: %m"); - _exit(EXIT_FAILURE); - } - - _cleanup_(iovw_free_freep) struct iovec_wrapper *iovw = iovw_new(); - if (!iovw) { - log_oom(); - _exit(EXIT_FAILURE); - } - - (void) iovw_put_string_field(iovw, "MESSAGE_ID=", SD_MESSAGE_COREDUMP_STR); - (void) iovw_put_string_field(iovw, "PRIORITY=", STRINGIFY(LOG_CRIT)); - (void) iovw_put_string_field(iovw, "COREDUMP_FORWARDED=", "1"); - - for (int i = 0; i < _META_ARGV_MAX; i++) { - char buf[DECIMAL_STR_MAX(pid_t)]; - const char *t = context->meta[i]; - - /* Patch some of the fields with the translated ucred data */ - switch (i) { - - case META_ARGV_PID: - xsprintf(buf, PID_FMT, ucred.pid); - t = buf; - break; - - case META_ARGV_UID: - xsprintf(buf, UID_FMT, ucred.uid); - t = buf; - break; - - case META_ARGV_GID: - xsprintf(buf, GID_FMT, ucred.gid); - t = buf; - break; - - default: - ; - } - - r = iovw_put_string_field(iovw, meta_field_names[i], t); - if (r < 0) { - log_debug_errno(r, "Failed to construct iovec: %m"); - _exit(EXIT_FAILURE); - } - } - - _cleanup_(context_done) Context child_context = CONTEXT_NULL; - r = context_parse_iovw(&child_context, iovw); - if (r < 0) { - log_debug_errno(r, "Failed to save context: %m"); - _exit(EXIT_FAILURE); - } - - r = gather_pid_metadata_from_procfs(iovw, &child_context); - if (r < 0) { - log_debug_errno(r, "Failed to gather metadata from procfs: %m"); - _exit(EXIT_FAILURE); - } - - r = send_iovec(iovw, STDIN_FILENO, &context->pidref, /* mount_tree_fd= */ -EBADF); - if (r < 0) { - log_debug_errno(r, "Failed to send iovec to coredump socket: %m"); - _exit(EXIT_FAILURE); - } - - _exit(EXIT_SUCCESS); - } - - pair[1] = safe_close(pair[1]); - - /* We need to translate the PID, UID, and GID of the crashing process - * to the container's namespaces. Do this by sending an SCM_CREDENTIALS - * message on a socket pair, and read the result when we join the - * container. The kernel will perform the translation for us. */ - r = send_ucred(pair[0], &ucred); - if (r < 0) - return log_debug_errno(r, "Failed to send metadata to container: %m"); - - r = wait_for_terminate_and_check("(sd-coredumpns)", child, 0); - if (r < 0) - return log_debug_errno(r, "Failed to wait for child to terminate: %m"); - if (r != EXIT_SUCCESS) - return log_debug_errno(SYNTHETIC_ERRNO(EPROTO), "Failed to process coredump in container."); - - return 0; -} - static int process_kernel(int argc, char *argv[]) { _cleanup_(iovw_free_freep) struct iovec_wrapper *iovw = NULL; _cleanup_(context_done) Context context = CONTEXT_NULL; @@ -420,7 +106,7 @@ static int process_kernel(int argc, char *argv[]) { if (r == 0) { /* If this fails, fallback to the old behavior so that * there is still some record of the crash. */ - r = forward_coredump_to_container(&context); + r = coredump_send_to_container(&context); if (r >= 0) return 0; @@ -446,7 +132,7 @@ static int process_kernel(int argc, char *argv[]) { if (context.is_journald || context.is_pid1) return coredump_submit(&context, iovw, STDIN_FILENO); - return send_iovec(iovw, STDIN_FILENO, &context.pidref, context.mount_tree_fd); + return coredump_send(iovw, STDIN_FILENO, &context.pidref, context.mount_tree_fd); } static int run(int argc, char *argv[]) { diff --git a/src/coredump/meson.build b/src/coredump/meson.build index a14a4464de3..cd71119d1d3 100644 --- a/src/coredump/meson.build +++ b/src/coredump/meson.build @@ -10,6 +10,7 @@ systemd_coredump_sources = files( 'coredump-config.c', 'coredump-context.c', 'coredump-receive.c', + 'coredump-send.c', 'coredump-submit.c', ) systemd_coredump_extract_sources = files(