diff -rup systemd-228/src/basic/io-util.c systemd-228-new/src/basic/io-util.c --- systemd-228/src/basic/io-util.c 2015-11-17 23:59:06.000000000 -0800 +++ systemd-228-new/src/basic/io-util.c 2019-01-16 11:15:29.889275944 -0800 @@ -23,6 +23,7 @@ #include #include "io-util.h" +#include "string-util.h" int flush_fd(int fd) { struct pollfd pollfd = { @@ -259,3 +260,20 @@ ssize_t sparse_write(int fd, const void return q - (const uint8_t*) p; } + +char* set_iovec_string_field(struct iovec *iovec, unsigned int *n_iovec, const char *field, const char *value) { + char *x; + + x = strappend(field, value); + if (x) + iovec[(*n_iovec)++] = IOVEC_MAKE_STRING(x); + return x; +} + +char* set_iovec_field_free(struct iovec *iovec, unsigned int *n_iovec, const char *field, char *value) { + char *x; + + x = set_iovec_string_field(iovec, n_iovec, field, value); + free(value); + return x; +} diff -rup systemd-228/src/basic/io-util.h systemd-228-new/src/basic/io-util.h --- systemd-228/src/basic/io-util.h 2015-11-17 23:59:06.000000000 -0800 +++ systemd-228-new/src/basic/io-util.h 2019-01-16 11:15:29.889275944 -0800 @@ -47,6 +47,14 @@ ssize_t sparse_write(int fd, const void _i->iov_len = strlen(_s); \ } while(false) +#define IOVEC_INIT(base, len) { .iov_base = (base), .iov_len = (len) } +#define IOVEC_MAKE(base, len) (struct iovec) IOVEC_INIT(base, len) +#define IOVEC_INIT_STRING(string) IOVEC_INIT((char*) string, strlen(string)) +#define IOVEC_MAKE_STRING(string) (struct iovec) IOVEC_INIT_STRING(string) + +char* set_iovec_string_field(struct iovec *iovec, unsigned int *n_iovec, const char *field, const char *value); +char* set_iovec_field_free(struct iovec *iovec, unsigned int *n_iovec, const char *field, char *value); + static inline size_t IOVEC_TOTAL_SIZE(const struct iovec *i, unsigned n) { unsigned j; size_t r = 0; diff -rup systemd-228/src/journal/coredump.c systemd-228-new/src/journal/coredump.c --- systemd-228/src/journal/coredump.c 2015-11-17 23:59:06.000000000 -0800 +++ systemd-228-new/src/journal/coredump.c 2019-01-16 11:21:27.779910457 -0800 @@ -537,28 +537,16 @@ static int compose_open_fds(pid_t pid, c } int main(int argc, char* argv[]) { - - /* The small core field we allocate on the stack, to keep things simple */ - char - *core_pid = NULL, *core_uid = NULL, *core_gid = NULL, *core_signal = NULL, - *core_session = NULL, *core_exe = NULL, *core_comm = NULL, *core_cmdline = NULL, - *core_cgroup = NULL, *core_cwd = NULL, *core_root = NULL, *core_unit = NULL, - *core_slice = NULL; - - /* The larger ones we allocate on the heap */ - _cleanup_free_ char - *core_timestamp = NULL, *core_message = NULL, *coredump_data = NULL, *core_owner_uid = NULL, - *core_open_fds = NULL, *core_proc_status = NULL, *core_proc_maps = NULL, *core_proc_limits = NULL, - *core_proc_cgroup = NULL, *core_environ = NULL; - - _cleanup_free_ char *exe = NULL, *comm = NULL, *filename = NULL; + _cleanup_free_ char *core_timestamp = NULL, *core_owner_uid = NULL, *coredump_data = NULL; + _cleanup_free_ char *exe = NULL, *comm = NULL, *filename = NULL, *core_message = NULL; const char *info[_INFO_LEN]; _cleanup_close_ int coredump_fd = -1; struct iovec iovec[26]; uint64_t coredump_size; - int r, j = 0; + int r; + unsigned n_iovec = 0; uid_t uid, owner_uid; gid_t gid; pid_t pid; @@ -645,151 +633,101 @@ int main(int argc, char* argv[]) { goto finish; } - core_unit = strjoina("COREDUMP_UNIT=", t); - free(t); + if (!set_iovec_field_free(iovec, &n_iovec, "COREDUMP_UNIT=", t)) + return log_oom(); } else if (cg_pid_get_user_unit(pid, &t) >= 0) { - core_unit = strjoina("COREDUMP_USER_UNIT=", t); - free(t); + if (!set_iovec_field_free(iovec, &n_iovec, "COREDUMP_USER_UNIT=", t)) + return log_oom(); } - if (core_unit) - IOVEC_SET_STRING(iovec[j++], core_unit); - /* OK, now we know it's not the journal, hence we can make use * of it now. */ log_set_target(LOG_TARGET_JOURNAL_OR_KMSG); log_open(); - core_pid = strjoina("COREDUMP_PID=", info[INFO_PID]); - IOVEC_SET_STRING(iovec[j++], core_pid); - - core_uid = strjoina("COREDUMP_UID=", info[INFO_UID]); - IOVEC_SET_STRING(iovec[j++], core_uid); - - core_gid = strjoina("COREDUMP_GID=", info[INFO_GID]); - IOVEC_SET_STRING(iovec[j++], core_gid); - - core_signal = strjoina("COREDUMP_SIGNAL=", info[INFO_SIGNAL]); - IOVEC_SET_STRING(iovec[j++], core_signal); + if (!set_iovec_string_field(iovec, &n_iovec, "COREDUMP_PID=", info[INFO_PID])) + return log_oom(); + if (!set_iovec_string_field(iovec, &n_iovec, "COREDUMP_UID=", info[INFO_UID])) + return log_oom(); + if (!set_iovec_string_field(iovec, &n_iovec, "COREDUMP_GID=", info[INFO_GID])) + return log_oom(); + if (!set_iovec_string_field(iovec, &n_iovec, "COREDUMP_SIGNAL=", info[INFO_SIGNAL])) + return log_oom(); if (sd_pid_get_session(pid, &t) >= 0) { - core_session = strjoina("COREDUMP_SESSION=", t); - free(t); - - IOVEC_SET_STRING(iovec[j++], core_session); + set_iovec_field_free(iovec, &n_iovec, "COREDUMP_SESSION=", t); } if (sd_pid_get_owner_uid(pid, &owner_uid) >= 0) { r = asprintf(&core_owner_uid, "COREDUMP_OWNER_UID=" UID_FMT, owner_uid); if (r > 0) - IOVEC_SET_STRING(iovec[j++], core_owner_uid); + IOVEC_SET_STRING(iovec[n_iovec++], core_owner_uid); } if (sd_pid_get_slice(pid, &t) >= 0) { - core_slice = strjoina("COREDUMP_SLICE=", t); - free(t); - - IOVEC_SET_STRING(iovec[j++], core_slice); + set_iovec_field_free(iovec, &n_iovec, "COREDUMP_SLICE=", t); } - if (comm) { - core_comm = strjoina("COREDUMP_COMM=", comm); - IOVEC_SET_STRING(iovec[j++], core_comm); + if (comm && !set_iovec_string_field(iovec, &n_iovec, "COREDUMP_COMM=", comm)) { + return log_oom(); } - if (exe) { - core_exe = strjoina("COREDUMP_EXE=", exe); - IOVEC_SET_STRING(iovec[j++], core_exe); + if (exe && !set_iovec_string_field(iovec, &n_iovec, "COREDUMP_EXE=", exe)) { + return log_oom(); } if (get_process_cmdline(pid, 0, false, &t) >= 0) { - core_cmdline = strjoina("COREDUMP_CMDLINE=", t); - free(t); - - IOVEC_SET_STRING(iovec[j++], core_cmdline); + set_iovec_field_free(iovec, &n_iovec, "COREDUMP_CMDLINE=", t); } if (cg_pid_get_path_shifted(pid, NULL, &t) >= 0) { - core_cgroup = strjoina("COREDUMP_CGROUP=", t); - free(t); - - IOVEC_SET_STRING(iovec[j++], core_cgroup); + set_iovec_field_free(iovec, &n_iovec, "COREDUMP_CGROUP=", t); } if (compose_open_fds(pid, &t) >= 0) { - core_open_fds = strappend("COREDUMP_OPEN_FDS=", t); - free(t); - - if (core_open_fds) - IOVEC_SET_STRING(iovec[j++], core_open_fds); + set_iovec_field_free(iovec, &n_iovec, "COREDUMP_OPEN_FDS=", t); } p = procfs_file_alloca(pid, "status"); if (read_full_file(p, &t, NULL) >= 0) { - core_proc_status = strappend("COREDUMP_PROC_STATUS=", t); - free(t); - - if (core_proc_status) - IOVEC_SET_STRING(iovec[j++], core_proc_status); + set_iovec_field_free(iovec, &n_iovec, "COREDUMP_PROC_STATUS=", t); } p = procfs_file_alloca(pid, "maps"); if (read_full_file(p, &t, NULL) >= 0) { - core_proc_maps = strappend("COREDUMP_PROC_MAPS=", t); - free(t); - - if (core_proc_maps) - IOVEC_SET_STRING(iovec[j++], core_proc_maps); + set_iovec_field_free(iovec, &n_iovec, "COREDUMP_PROC_MAPS=", t); } p = procfs_file_alloca(pid, "limits"); if (read_full_file(p, &t, NULL) >= 0) { - core_proc_limits = strappend("COREDUMP_PROC_LIMITS=", t); - free(t); - - if (core_proc_limits) - IOVEC_SET_STRING(iovec[j++], core_proc_limits); + set_iovec_field_free(iovec, &n_iovec, "COREDUMP_PROC_LIMITS=", t); } p = procfs_file_alloca(pid, "cgroup"); if (read_full_file(p, &t, NULL) >=0) { - core_proc_cgroup = strappend("COREDUMP_PROC_CGROUP=", t); - free(t); - - if (core_proc_cgroup) - IOVEC_SET_STRING(iovec[j++], core_proc_cgroup); + set_iovec_field_free(iovec, &n_iovec, "COREDUMP_PROC_CGROUP=", t); } if (get_process_cwd(pid, &t) >= 0) { - core_cwd = strjoina("COREDUMP_CWD=", t); - free(t); - - IOVEC_SET_STRING(iovec[j++], core_cwd); + set_iovec_field_free(iovec, &n_iovec, "COREDUMP_CWD=", t); } if (get_process_root(pid, &t) >= 0) { - core_root = strjoina("COREDUMP_ROOT=", t); - free(t); - - IOVEC_SET_STRING(iovec[j++], core_root); + set_iovec_field_free(iovec, &n_iovec, "COREDUMP_ROOT=", t); } if (get_process_environ(pid, &t) >= 0) { - core_environ = strappend("COREDUMP_ENVIRON=", t); - free(t); - - if (core_environ) - IOVEC_SET_STRING(iovec[j++], core_environ); + set_iovec_field_free(iovec, &n_iovec, "COREDUMP_ENVIRON=", t); } core_timestamp = strjoin("COREDUMP_TIMESTAMP=", info[INFO_TIMESTAMP], "000000", NULL); if (core_timestamp) - IOVEC_SET_STRING(iovec[j++], core_timestamp); + IOVEC_SET_STRING(iovec[n_iovec++], core_timestamp); - IOVEC_SET_STRING(iovec[j++], "MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1"); - IOVEC_SET_STRING(iovec[j++], "PRIORITY=2"); + IOVEC_SET_STRING(iovec[n_iovec++], "MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1"); + IOVEC_SET_STRING(iovec[n_iovec++], "PRIORITY=2"); /* Vacuum before we write anything again */ coredump_vacuum(-1, arg_keep_free, arg_max_use); @@ -811,7 +749,7 @@ int main(int argc, char* argv[]) { const char *coredump_filename; coredump_filename = strjoina("COREDUMP_FILENAME=", filename); - IOVEC_SET_STRING(iovec[j++], coredump_filename); + IOVEC_SET_STRING(iovec[n_iovec++], coredump_filename); } /* Vacuum again, but exclude the coredump we just created */ @@ -849,7 +787,7 @@ int main(int argc, char* argv[]) { log: core_message = strjoin("MESSAGE=Process ", info[INFO_PID], " (", comm, ") of user ", info[INFO_UID], " dumped core.", NULL); if (core_message) - IOVEC_SET_STRING(iovec[j++], core_message); + IOVEC_SET_STRING(iovec[n_iovec++], core_message); /* Optionally store the entire coredump in the journal */ if (IN_SET(arg_storage, COREDUMP_STORAGE_JOURNAL, COREDUMP_STORAGE_BOTH) && @@ -860,13 +798,13 @@ log: r = allocate_journal_field(coredump_fd, (size_t) coredump_size, &coredump_data, &sz); if (r >= 0) { - iovec[j].iov_base = coredump_data; - iovec[j].iov_len = sz; - j++; + iovec[n_iovec].iov_base = coredump_data; + iovec[n_iovec].iov_len = sz; + n_iovec++; } } - r = sd_journal_sendv(iovec, j); + r = sd_journal_sendv(iovec, n_iovec); if (r < 0) log_error_errno(r, "Failed to log coredump: %m"); diff -rup systemd-228/src/journal/journald-server.c systemd-228-new/src/journal/journald-server.c --- systemd-228/src/journal/journald-server.c 2015-11-17 23:59:06.000000000 -0800 +++ systemd-228-new/src/journal/journald-server.c 2019-01-16 11:15:29.889275944 -0800 @@ -579,6 +579,7 @@ static void dispatch_message_real( o_uid[sizeof("OBJECT_UID=") + DECIMAL_STR_MAX(uid_t)], o_gid[sizeof("OBJECT_GID=") + DECIMAL_STR_MAX(gid_t)], o_owner_uid[sizeof("OBJECT_SYSTEMD_OWNER_UID=") + DECIMAL_STR_MAX(uid_t)]; + _cleanup_free_ char *cmdline1 = NULL, *cmdline2 = NULL; uid_t object_uid; gid_t object_gid; char *x; @@ -629,9 +630,9 @@ static void dispatch_message_real( r = get_process_cmdline(ucred->pid, 0, false, &t); if (r >= 0) { - x = strjoina("_CMDLINE=", t); - free(t); - IOVEC_SET_STRING(iovec[n++], x); + /* At most _SC_ARG_MAX (2MB usually), which is too much to put on stack. + * Let's use a heap allocation for this one. */ + cmdline1 = set_iovec_field_free(iovec, &n, "_CMDLINE=", t); } r = get_process_capeff(ucred->pid, &t); @@ -757,9 +758,7 @@ static void dispatch_message_real( r = get_process_cmdline(object_pid, 0, false, &t); if (r >= 0) { - x = strjoina("OBJECT_CMDLINE=", t); - free(t); - IOVEC_SET_STRING(iovec[n++], x); + cmdline2 = set_iovec_field_free(iovec, &n, "OBJECT_CMDLINE=", t); } #ifdef HAVE_AUDIT