| File: | build-scan/../src/journal/journald-syslog.c |
| Warning: | line 371, column 37 Potential leak of memory pointed to by 'identifier' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ | |||
| 2 | ||||
| 3 | #include <stddef.h> | |||
| 4 | #include <sys/epoll.h> | |||
| 5 | #include <unistd.h> | |||
| 6 | ||||
| 7 | #include "sd-messages.h" | |||
| 8 | ||||
| 9 | #include "alloc-util.h" | |||
| 10 | #include "fd-util.h" | |||
| 11 | #include "format-util.h" | |||
| 12 | #include "io-util.h" | |||
| 13 | #include "journald-console.h" | |||
| 14 | #include "journald-kmsg.h" | |||
| 15 | #include "journald-server.h" | |||
| 16 | #include "journald-syslog.h" | |||
| 17 | #include "journald-wall.h" | |||
| 18 | #include "process-util.h" | |||
| 19 | #include "selinux-util.h" | |||
| 20 | #include "socket-util.h" | |||
| 21 | #include "stdio-util.h" | |||
| 22 | #include "string-util.h" | |||
| 23 | #include "syslog-util.h" | |||
| 24 | ||||
| 25 | /* Warn once every 30s if we missed syslog message */ | |||
| 26 | #define WARN_FORWARD_SYSLOG_MISSED_USEC(30 * ((usec_t) 1000000ULL)) (30 * USEC_PER_SEC((usec_t) 1000000ULL)) | |||
| 27 | ||||
| 28 | static void forward_syslog_iovec(Server *s, const struct iovec *iovec, unsigned n_iovec, const struct ucred *ucred, const struct timeval *tv) { | |||
| 29 | ||||
| 30 | static const union sockaddr_union sa = { | |||
| 31 | .un.sun_family = AF_UNIX1, | |||
| 32 | .un.sun_path = "/run/systemd/journal/syslog", | |||
| 33 | }; | |||
| 34 | struct msghdr msghdr = { | |||
| 35 | .msg_iov = (struct iovec *) iovec, | |||
| 36 | .msg_iovlen = n_iovec, | |||
| 37 | .msg_name = (struct sockaddr*) &sa.sa, | |||
| 38 | .msg_namelen = SOCKADDR_UN_LEN(sa.un)({ const struct sockaddr_un *_sa = &(sa.un); do { if ((__builtin_expect (!!(!(_sa->sun_family == 1)),0))) log_assert_failed_realm( LOG_REALM_SYSTEMD, ("_sa->sun_family == AF_UNIX"), "../src/journal/journald-syslog.c" , 38, __PRETTY_FUNCTION__); } while (0); __builtin_offsetof(struct sockaddr_un, sun_path) + (_sa->sun_path[0] == 0 ? 1 + strnlen (_sa->sun_path+1, sizeof(_sa->sun_path)-1) : strnlen(_sa ->sun_path, sizeof(_sa->sun_path))); }), | |||
| 39 | }; | |||
| 40 | struct cmsghdr *cmsg; | |||
| 41 | union { | |||
| 42 | struct cmsghdr cmsghdr; | |||
| 43 | uint8_t buf[CMSG_SPACE(sizeof(struct ucred))((((sizeof(struct ucred)) + sizeof (size_t) - 1) & (size_t ) ~(sizeof (size_t) - 1)) + (((sizeof (struct cmsghdr)) + sizeof (size_t) - 1) & (size_t) ~(sizeof (size_t) - 1)))]; | |||
| 44 | } control; | |||
| 45 | ||||
| 46 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/journal/journald-syslog.c" , 46, __PRETTY_FUNCTION__); } while (0); | |||
| 47 | assert(iovec)do { if ((__builtin_expect(!!(!(iovec)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("iovec"), "../src/journal/journald-syslog.c" , 47, __PRETTY_FUNCTION__); } while (0); | |||
| 48 | assert(n_iovec > 0)do { if ((__builtin_expect(!!(!(n_iovec > 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("n_iovec > 0"), "../src/journal/journald-syslog.c" , 48, __PRETTY_FUNCTION__); } while (0); | |||
| 49 | ||||
| 50 | if (ucred) { | |||
| 51 | zero(control)(({ size_t _l_ = (sizeof(control)); void *_x_ = (&(control )); _l_ == 0 ? _x_ : memset(_x_, 0, _l_); })); | |||
| 52 | msghdr.msg_control = &control; | |||
| 53 | msghdr.msg_controllen = sizeof(control); | |||
| 54 | ||||
| 55 | cmsg = CMSG_FIRSTHDR(&msghdr)((size_t) (&msghdr)->msg_controllen >= sizeof (struct cmsghdr) ? (struct cmsghdr *) (&msghdr)->msg_control : (struct cmsghdr *) 0); | |||
| 56 | cmsg->cmsg_level = SOL_SOCKET1; | |||
| 57 | cmsg->cmsg_type = SCM_CREDENTIALSSCM_CREDENTIALS; | |||
| 58 | cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred))((((sizeof (struct cmsghdr)) + sizeof (size_t) - 1) & (size_t ) ~(sizeof (size_t) - 1)) + (sizeof(struct ucred))); | |||
| 59 | memcpy(CMSG_DATA(cmsg)((cmsg)->__cmsg_data), ucred, sizeof(struct ucred)); | |||
| 60 | msghdr.msg_controllen = cmsg->cmsg_len; | |||
| 61 | } | |||
| 62 | ||||
| 63 | /* Forward the syslog message we received via /dev/log to | |||
| 64 | * /run/systemd/syslog. Unfortunately we currently can't set | |||
| 65 | * the SO_TIMESTAMP auxiliary data, and hence we don't. */ | |||
| 66 | ||||
| 67 | if (sendmsg(s->syslog_fd, &msghdr, MSG_NOSIGNALMSG_NOSIGNAL) >= 0) | |||
| 68 | return; | |||
| 69 | ||||
| 70 | /* The socket is full? I guess the syslog implementation is | |||
| 71 | * too slow, and we shouldn't wait for that... */ | |||
| 72 | if (errno(*__errno_location ()) == EAGAIN11) { | |||
| 73 | s->n_forward_syslog_missed++; | |||
| 74 | return; | |||
| 75 | } | |||
| 76 | ||||
| 77 | if (ucred && IN_SET(errno, ESRCH, EPERM)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){3, 1})/sizeof(int)]; switch((*__errno_location ())) { case 3: case 1: _found = 1; break; default: break; } _found ; })) { | |||
| 78 | struct ucred u; | |||
| 79 | ||||
| 80 | /* Hmm, presumably the sender process vanished | |||
| 81 | * by now, or we don't have CAP_SYS_AMDIN, so | |||
| 82 | * let's fix it as good as we can, and retry */ | |||
| 83 | ||||
| 84 | u = *ucred; | |||
| 85 | u.pid = getpid_cached(); | |||
| 86 | memcpy(CMSG_DATA(cmsg)((cmsg)->__cmsg_data), &u, sizeof(struct ucred)); | |||
| 87 | ||||
| 88 | if (sendmsg(s->syslog_fd, &msghdr, MSG_NOSIGNALMSG_NOSIGNAL) >= 0) | |||
| 89 | return; | |||
| 90 | ||||
| 91 | if (errno(*__errno_location ()) == EAGAIN11) { | |||
| 92 | s->n_forward_syslog_missed++; | |||
| 93 | return; | |||
| 94 | } | |||
| 95 | } | |||
| 96 | ||||
| 97 | if (errno(*__errno_location ()) != ENOENT2) | |||
| 98 | log_debug_errno(errno, "Failed to forward syslog message: %m")({ int _level = ((7)), _e = (((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/journal/journald-syslog.c", 98, __func__ , "Failed to forward syslog message: %m") : -abs(_e); }); | |||
| 99 | } | |||
| 100 | ||||
| 101 | static void forward_syslog_raw(Server *s, int priority, const char *buffer, size_t buffer_len, const struct ucred *ucred, const struct timeval *tv) { | |||
| 102 | struct iovec iovec; | |||
| 103 | ||||
| 104 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/journal/journald-syslog.c" , 104, __PRETTY_FUNCTION__); } while (0); | |||
| 105 | assert(buffer)do { if ((__builtin_expect(!!(!(buffer)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("buffer"), "../src/journal/journald-syslog.c" , 105, __PRETTY_FUNCTION__); } while (0); | |||
| 106 | ||||
| 107 | if (LOG_PRI(priority)((priority) & 0x07) > s->max_level_syslog) | |||
| 108 | return; | |||
| 109 | ||||
| 110 | iovec = IOVEC_MAKE((char *) buffer, buffer_len)(struct iovec) { .iov_base = ((char *) buffer), .iov_len = (buffer_len ) }; | |||
| 111 | forward_syslog_iovec(s, &iovec, 1, ucred, tv); | |||
| 112 | } | |||
| 113 | ||||
| 114 | void server_forward_syslog(Server *s, int priority, const char *identifier, const char *message, const struct ucred *ucred, const struct timeval *tv) { | |||
| 115 | struct iovec iovec[5]; | |||
| 116 | char header_priority[DECIMAL_STR_MAX(priority)(2+(sizeof(priority) <= 1 ? 3 : sizeof(priority) <= 2 ? 5 : sizeof(priority) <= 4 ? 10 : sizeof(priority) <= 8 ? 20 : sizeof(int[-2*(sizeof(priority) > 8)]))) + 3], header_time[64], | |||
| 117 | header_pid[STRLEN("[]: ")(sizeof("""[]: """) - 1) + DECIMAL_STR_MAX(pid_t)(2+(sizeof(pid_t) <= 1 ? 3 : sizeof(pid_t) <= 2 ? 5 : sizeof (pid_t) <= 4 ? 10 : sizeof(pid_t) <= 8 ? 20 : sizeof(int [-2*(sizeof(pid_t) > 8)]))) + 1]; | |||
| 118 | int n = 0; | |||
| 119 | time_t t; | |||
| 120 | struct tm *tm; | |||
| 121 | _cleanup_free___attribute__((cleanup(freep))) char *ident_buf = NULL((void*)0); | |||
| 122 | ||||
| 123 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/journal/journald-syslog.c" , 123, __PRETTY_FUNCTION__); } while (0); | |||
| 124 | assert(priority >= 0)do { if ((__builtin_expect(!!(!(priority >= 0)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("priority >= 0"), "../src/journal/journald-syslog.c" , 124, __PRETTY_FUNCTION__); } while (0); | |||
| 125 | assert(priority <= 999)do { if ((__builtin_expect(!!(!(priority <= 999)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("priority <= 999"), "../src/journal/journald-syslog.c" , 125, __PRETTY_FUNCTION__); } while (0); | |||
| 126 | assert(message)do { if ((__builtin_expect(!!(!(message)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("message"), "../src/journal/journald-syslog.c" , 126, __PRETTY_FUNCTION__); } while (0); | |||
| 127 | ||||
| 128 | if (LOG_PRI(priority)((priority) & 0x07) > s->max_level_syslog) | |||
| 129 | return; | |||
| 130 | ||||
| 131 | /* First: priority field */ | |||
| 132 | xsprintf(header_priority, "<%i>", priority)do { if ((__builtin_expect(!!(!(((size_t) snprintf(header_priority , __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p (typeof(header_priority), typeof(&*(header_priority))), sizeof (header_priority)/sizeof((header_priority)[0]), ((void)0))), "<%i>" , priority) < (__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p (typeof(header_priority), typeof(&*(header_priority))), sizeof (header_priority)/sizeof((header_priority)[0]), ((void)0))))) )),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD, ("xsprintf: " "header_priority" "[] must be big enough"), "../src/journal/journald-syslog.c" , 132, __PRETTY_FUNCTION__); } while (0); | |||
| 133 | iovec[n++] = IOVEC_MAKE_STRING(header_priority)(struct iovec) { .iov_base = ((char*) header_priority), .iov_len = (strlen(header_priority)) }; | |||
| 134 | ||||
| 135 | /* Second: timestamp */ | |||
| 136 | t = tv ? tv->tv_sec : ((time_t) (now(CLOCK_REALTIME0) / USEC_PER_SEC((usec_t) 1000000ULL))); | |||
| 137 | tm = localtime(&t); | |||
| 138 | if (!tm) | |||
| 139 | return; | |||
| 140 | if (strftime(header_time, sizeof(header_time), "%h %e %T ", tm) <= 0) | |||
| 141 | return; | |||
| 142 | iovec[n++] = IOVEC_MAKE_STRING(header_time)(struct iovec) { .iov_base = ((char*) header_time), .iov_len = (strlen(header_time)) }; | |||
| 143 | ||||
| 144 | /* Third: identifier and PID */ | |||
| 145 | if (ucred) { | |||
| 146 | if (!identifier) { | |||
| 147 | get_process_comm(ucred->pid, &ident_buf); | |||
| 148 | identifier = ident_buf; | |||
| 149 | } | |||
| 150 | ||||
| 151 | xsprintf(header_pid, "["PID_FMT"]: ", ucred->pid)do { if ((__builtin_expect(!!(!(((size_t) snprintf(header_pid , __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p (typeof(header_pid), typeof(&*(header_pid))), sizeof(header_pid )/sizeof((header_pid)[0]), ((void)0))), "[""%" "i""]: ", ucred ->pid) < (__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p (typeof(header_pid), typeof(&*(header_pid))), sizeof(header_pid )/sizeof((header_pid)[0]), ((void)0))))))),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("xsprintf: " "header_pid" "[] must be big enough" ), "../src/journal/journald-syslog.c", 151, __PRETTY_FUNCTION__ ); } while (0); | |||
| 152 | ||||
| 153 | if (identifier) | |||
| 154 | iovec[n++] = IOVEC_MAKE_STRING(identifier)(struct iovec) { .iov_base = ((char*) identifier), .iov_len = (strlen(identifier)) }; | |||
| 155 | ||||
| 156 | iovec[n++] = IOVEC_MAKE_STRING(header_pid)(struct iovec) { .iov_base = ((char*) header_pid), .iov_len = (strlen(header_pid)) }; | |||
| 157 | } else if (identifier) { | |||
| 158 | iovec[n++] = IOVEC_MAKE_STRING(identifier)(struct iovec) { .iov_base = ((char*) identifier), .iov_len = (strlen(identifier)) }; | |||
| 159 | iovec[n++] = IOVEC_MAKE_STRING(": ")(struct iovec) { .iov_base = ((char*) ": "), .iov_len = (strlen (": ")) }; | |||
| 160 | } | |||
| 161 | ||||
| 162 | /* Fourth: message */ | |||
| 163 | iovec[n++] = IOVEC_MAKE_STRING(message)(struct iovec) { .iov_base = ((char*) message), .iov_len = (strlen (message)) }; | |||
| 164 | ||||
| 165 | forward_syslog_iovec(s, iovec, n, ucred, tv); | |||
| 166 | } | |||
| 167 | ||||
| 168 | int syslog_fixup_facility(int priority) { | |||
| 169 | ||||
| 170 | if ((priority & LOG_FACMASK0x03f8) == 0) | |||
| 171 | return (priority & LOG_PRIMASK0x07) | LOG_USER(1<<3); | |||
| 172 | ||||
| 173 | return priority; | |||
| 174 | } | |||
| 175 | ||||
| 176 | size_t syslog_parse_identifier(const char **buf, char **identifier, char **pid) { | |||
| 177 | const char *p; | |||
| 178 | char *t; | |||
| 179 | size_t l, e; | |||
| 180 | ||||
| 181 | assert(buf)do { if ((__builtin_expect(!!(!(buf)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("buf"), "../src/journal/journald-syslog.c" , 181, __PRETTY_FUNCTION__); } while (0); | |||
| 182 | assert(identifier)do { if ((__builtin_expect(!!(!(identifier)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("identifier"), "../src/journal/journald-syslog.c" , 182, __PRETTY_FUNCTION__); } while (0); | |||
| 183 | assert(pid)do { if ((__builtin_expect(!!(!(pid)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("pid"), "../src/journal/journald-syslog.c" , 183, __PRETTY_FUNCTION__); } while (0); | |||
| 184 | ||||
| 185 | p = *buf; | |||
| 186 | ||||
| 187 | p += strspn(p, WHITESPACE" \t\n\r"); | |||
| 188 | l = strcspn(p, WHITESPACE" \t\n\r"); | |||
| 189 | ||||
| 190 | if (l <= 0 || | |||
| 191 | p[l-1] != ':') | |||
| 192 | return 0; | |||
| 193 | ||||
| 194 | e = l; | |||
| 195 | l--; | |||
| 196 | ||||
| 197 | if (l > 0 && p[l-1] == ']') { | |||
| 198 | size_t k = l-1; | |||
| 199 | ||||
| 200 | for (;;) { | |||
| 201 | ||||
| 202 | if (p[k] == '[') { | |||
| 203 | t = strndup(p+k+1, l-k-2); | |||
| 204 | if (t) | |||
| 205 | *pid = t; | |||
| 206 | ||||
| 207 | l = k; | |||
| 208 | break; | |||
| 209 | } | |||
| 210 | ||||
| 211 | if (k == 0) | |||
| 212 | break; | |||
| 213 | ||||
| 214 | k--; | |||
| 215 | } | |||
| 216 | } | |||
| 217 | ||||
| 218 | t = strndup(p, l); | |||
| 219 | if (t) | |||
| 220 | *identifier = t; | |||
| 221 | ||||
| 222 | /* Single space is used as separator */ | |||
| 223 | if (p[e] != '\0' && strchr(WHITESPACE" \t\n\r", p[e])) | |||
| 224 | e++; | |||
| 225 | ||||
| 226 | l = (p - *buf) + e; | |||
| 227 | *buf = p + e; | |||
| 228 | return l; | |||
| 229 | } | |||
| 230 | ||||
| 231 | static void syslog_skip_date(char **buf) { | |||
| 232 | enum { | |||
| 233 | LETTER, | |||
| 234 | SPACE, | |||
| 235 | NUMBER, | |||
| 236 | SPACE_OR_NUMBER, | |||
| 237 | COLON | |||
| 238 | } sequence[] = { | |||
| 239 | LETTER, LETTER, LETTER, | |||
| 240 | SPACE, | |||
| 241 | SPACE_OR_NUMBER, NUMBER, | |||
| 242 | SPACE, | |||
| 243 | SPACE_OR_NUMBER, NUMBER, | |||
| 244 | COLON, | |||
| 245 | SPACE_OR_NUMBER, NUMBER, | |||
| 246 | COLON, | |||
| 247 | SPACE_OR_NUMBER, NUMBER, | |||
| 248 | SPACE | |||
| 249 | }; | |||
| 250 | ||||
| 251 | char *p; | |||
| 252 | unsigned i; | |||
| 253 | ||||
| 254 | assert(buf)do { if ((__builtin_expect(!!(!(buf)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("buf"), "../src/journal/journald-syslog.c" , 254, __PRETTY_FUNCTION__); } while (0); | |||
| 255 | assert(*buf)do { if ((__builtin_expect(!!(!(*buf)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("*buf"), "../src/journal/journald-syslog.c" , 255, __PRETTY_FUNCTION__); } while (0); | |||
| 256 | ||||
| 257 | p = *buf; | |||
| 258 | ||||
| 259 | for (i = 0; i < ELEMENTSOF(sequence)__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p (typeof(sequence), typeof(&*(sequence))), sizeof(sequence )/sizeof((sequence)[0]), ((void)0))); i++, p++) { | |||
| 260 | ||||
| 261 | if (!*p) | |||
| 262 | return; | |||
| 263 | ||||
| 264 | switch (sequence[i]) { | |||
| 265 | ||||
| 266 | case SPACE: | |||
| 267 | if (*p != ' ') | |||
| 268 | return; | |||
| 269 | break; | |||
| 270 | ||||
| 271 | case SPACE_OR_NUMBER: | |||
| 272 | if (*p == ' ') | |||
| 273 | break; | |||
| 274 | ||||
| 275 | _fallthrough_; | |||
| 276 | case NUMBER: | |||
| 277 | if (*p < '0' || *p > '9') | |||
| 278 | return; | |||
| 279 | ||||
| 280 | break; | |||
| 281 | ||||
| 282 | case LETTER: | |||
| 283 | if (!(*p >= 'A' && *p <= 'Z') && | |||
| 284 | !(*p >= 'a' && *p <= 'z')) | |||
| 285 | return; | |||
| 286 | ||||
| 287 | break; | |||
| 288 | ||||
| 289 | case COLON: | |||
| 290 | if (*p != ':') | |||
| 291 | return; | |||
| 292 | break; | |||
| 293 | ||||
| 294 | } | |||
| 295 | } | |||
| 296 | ||||
| 297 | *buf = p; | |||
| 298 | } | |||
| 299 | ||||
| 300 | void server_process_syslog_message( | |||
| 301 | Server *s, | |||
| 302 | const char *buf, | |||
| 303 | size_t buf_len, | |||
| 304 | const struct ucred *ucred, | |||
| 305 | const struct timeval *tv, | |||
| 306 | const char *label, | |||
| 307 | size_t label_len) { | |||
| 308 | ||||
| 309 | char syslog_priority[sizeof("PRIORITY=") + DECIMAL_STR_MAX(int)(2+(sizeof(int) <= 1 ? 3 : sizeof(int) <= 2 ? 5 : sizeof (int) <= 4 ? 10 : sizeof(int) <= 8 ? 20 : sizeof(int[-2 *(sizeof(int) > 8)])))], | |||
| 310 | syslog_facility[sizeof("SYSLOG_FACILITY=") + DECIMAL_STR_MAX(int)(2+(sizeof(int) <= 1 ? 3 : sizeof(int) <= 2 ? 5 : sizeof (int) <= 4 ? 10 : sizeof(int) <= 8 ? 20 : sizeof(int[-2 *(sizeof(int) > 8)])))], *msg; | |||
| 311 | const char *message = NULL((void*)0), *syslog_identifier = NULL((void*)0), *syslog_pid = NULL((void*)0); | |||
| 312 | _cleanup_free___attribute__((cleanup(freep))) char *identifier = NULL((void*)0), *pid = NULL((void*)0); | |||
| 313 | int priority = LOG_USER(1<<3) | LOG_INFO6, r; | |||
| 314 | ClientContext *context = NULL((void*)0); | |||
| 315 | struct iovec *iovec; | |||
| 316 | size_t n = 0, m, i; | |||
| 317 | ||||
| 318 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/journal/journald-syslog.c" , 318, __PRETTY_FUNCTION__); } while (0); | |||
| ||||
| 319 | assert(buf)do { if ((__builtin_expect(!!(!(buf)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("buf"), "../src/journal/journald-syslog.c" , 319, __PRETTY_FUNCTION__); } while (0); | |||
| 320 | ||||
| 321 | if (ucred && pid_is_valid(ucred->pid)) { | |||
| 322 | r = client_context_get(s, ucred->pid, ucred, label, label_len, NULL((void*)0), &context); | |||
| 323 | if (r < 0) | |||
| 324 | log_warning_errno(r, "Failed to retrieve credentials for PID " PID_FMT ", ignoring: %m", ucred->pid)({ int _level = ((4)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal/journald-syslog.c", 324, __func__, "Failed to retrieve credentials for PID " "%" "i" ", ignoring: %m", ucred->pid) : -abs(_e); }); | |||
| 325 | } | |||
| 326 | ||||
| 327 | /* We are creating copy of the message because we want to forward original message verbatim to the legacy | |||
| 328 | syslog implementation */ | |||
| 329 | for (i = buf_len; i > 0; i--) | |||
| 330 | if (!strchr(WHITESPACE" \t\n\r", buf[i-1])) | |||
| 331 | break; | |||
| 332 | ||||
| 333 | msg = newa(char, i + 1)({ do { if ((__builtin_expect(!!(!(!size_multiply_overflow(sizeof (char), i + 1))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD , ("!size_multiply_overflow(sizeof(char), i + 1)"), "../src/journal/journald-syslog.c" , 333, __PRETTY_FUNCTION__); } while (0); (char*) __builtin_alloca (sizeof(char)*(i + 1)); }); | |||
| 334 | *((char *) mempcpy(msg, buf, i)) = 0; | |||
| 335 | msg = skip_leading_chars(msg, WHITESPACE" \t\n\r"); | |||
| 336 | ||||
| 337 | syslog_parse_priority((const char **)&msg, &priority, true1); | |||
| 338 | ||||
| 339 | if (!client_context_test_priority(context, priority)) | |||
| 340 | return; | |||
| 341 | ||||
| 342 | if (s->forward_to_syslog) | |||
| 343 | forward_syslog_raw(s, priority, buf, buf_len, ucred, tv); | |||
| 344 | ||||
| 345 | syslog_skip_date(&msg); | |||
| 346 | syslog_parse_identifier((const char**)&msg, &identifier, &pid); | |||
| 347 | ||||
| 348 | if (s->forward_to_kmsg) | |||
| 349 | server_forward_kmsg(s, priority, identifier, msg, ucred); | |||
| 350 | ||||
| 351 | if (s->forward_to_console) | |||
| 352 | server_forward_console(s, priority, identifier, msg, ucred); | |||
| 353 | ||||
| 354 | if (s->forward_to_wall) | |||
| 355 | server_forward_wall(s, priority, identifier, msg, ucred); | |||
| 356 | ||||
| 357 | m = N_IOVEC_META_FIELDS22 + 6 + client_context_extra_fields_n_iovec(context); | |||
| 358 | iovec = newa(struct iovec, m)({ do { if ((__builtin_expect(!!(!(!size_multiply_overflow(sizeof (struct iovec), m))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD , ("!size_multiply_overflow(sizeof(struct iovec), m)"), "../src/journal/journald-syslog.c" , 358, __PRETTY_FUNCTION__); } while (0); (struct iovec*) __builtin_alloca (sizeof(struct iovec)*(m)); }); | |||
| 359 | ||||
| 360 | iovec[n++] = IOVEC_MAKE_STRING("_TRANSPORT=syslog")(struct iovec) { .iov_base = ((char*) "_TRANSPORT=syslog"), . iov_len = (strlen("_TRANSPORT=syslog")) }; | |||
| 361 | ||||
| 362 | xsprintf(syslog_priority, "PRIORITY=%i", priority & LOG_PRIMASK)do { if ((__builtin_expect(!!(!(((size_t) snprintf(syslog_priority , __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p (typeof(syslog_priority), typeof(&*(syslog_priority))), sizeof (syslog_priority)/sizeof((syslog_priority)[0]), ((void)0))), "PRIORITY=%i" , priority & 0x07) < (__extension__ (__builtin_choose_expr ( !__builtin_types_compatible_p(typeof(syslog_priority), typeof (&*(syslog_priority))), sizeof(syslog_priority)/sizeof((syslog_priority )[0]), ((void)0))))))),0))) log_assert_failed_realm(LOG_REALM_SYSTEMD , ("xsprintf: " "syslog_priority" "[] must be big enough"), "../src/journal/journald-syslog.c" , 362, __PRETTY_FUNCTION__); } while (0); | |||
| 363 | iovec[n++] = IOVEC_MAKE_STRING(syslog_priority)(struct iovec) { .iov_base = ((char*) syslog_priority), .iov_len = (strlen(syslog_priority)) }; | |||
| 364 | ||||
| 365 | if (priority & LOG_FACMASK0x03f8) { | |||
| 366 | xsprintf(syslog_facility, "SYSLOG_FACILITY=%i", LOG_FAC(priority))do { if ((__builtin_expect(!!(!(((size_t) snprintf(syslog_facility , __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p (typeof(syslog_facility), typeof(&*(syslog_facility))), sizeof (syslog_facility)/sizeof((syslog_facility)[0]), ((void)0))), "SYSLOG_FACILITY=%i" , (((priority) & 0x03f8) >> 3)) < (__extension__ (__builtin_choose_expr( !__builtin_types_compatible_p(typeof (syslog_facility), typeof(&*(syslog_facility))), sizeof(syslog_facility )/sizeof((syslog_facility)[0]), ((void)0))))))),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("xsprintf: " "syslog_facility" "[] must be big enough" ), "../src/journal/journald-syslog.c", 366, __PRETTY_FUNCTION__ ); } while (0); | |||
| 367 | iovec[n++] = IOVEC_MAKE_STRING(syslog_facility)(struct iovec) { .iov_base = ((char*) syslog_facility), .iov_len = (strlen(syslog_facility)) }; | |||
| 368 | } | |||
| 369 | ||||
| 370 | if (identifier
| |||
| 371 | syslog_identifier = strjoina("SYSLOG_IDENTIFIER=", identifier)({ const char *_appendees_[] = { "SYSLOG_IDENTIFIER=", identifier }; char *_d_, *_p_; size_t _len_ = 0; size_t _i_; for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p (typeof(_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_ )/sizeof((_appendees_)[0]), ((void)0))) && _appendees_ [_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca (_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr ( !__builtin_types_compatible_p(typeof(_appendees_), typeof(& *(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0] ), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy (_p_, _appendees_[_i_]); *_p_ = 0; _d_; }); | |||
| ||||
| 372 | iovec[n++] = IOVEC_MAKE_STRING(syslog_identifier)(struct iovec) { .iov_base = ((char*) syslog_identifier), .iov_len = (strlen(syslog_identifier)) }; | |||
| 373 | } | |||
| 374 | ||||
| 375 | if (pid) { | |||
| 376 | syslog_pid = strjoina("SYSLOG_PID=", pid)({ const char *_appendees_[] = { "SYSLOG_PID=", pid }; char * _d_, *_p_; size_t _len_ = 0; size_t _i_; for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p (typeof(_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_ )/sizeof((_appendees_)[0]), ((void)0))) && _appendees_ [_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca (_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr ( !__builtin_types_compatible_p(typeof(_appendees_), typeof(& *(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0] ), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy (_p_, _appendees_[_i_]); *_p_ = 0; _d_; }); | |||
| 377 | iovec[n++] = IOVEC_MAKE_STRING(syslog_pid)(struct iovec) { .iov_base = ((char*) syslog_pid), .iov_len = (strlen(syslog_pid)) }; | |||
| 378 | } | |||
| 379 | ||||
| 380 | message = strjoina("MESSAGE=", msg)({ const char *_appendees_[] = { "MESSAGE=", msg }; char *_d_ , *_p_; size_t _len_ = 0; size_t _i_; for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr( !__builtin_types_compatible_p(typeof (_appendees_), typeof(&*(_appendees_))), sizeof(_appendees_ )/sizeof((_appendees_)[0]), ((void)0))) && _appendees_ [_i_]; _i_++) _len_ += strlen(_appendees_[_i_]); _p_ = _d_ = __builtin_alloca (_len_ + 1); for (_i_ = 0; _i_ < __extension__ (__builtin_choose_expr ( !__builtin_types_compatible_p(typeof(_appendees_), typeof(& *(_appendees_))), sizeof(_appendees_)/sizeof((_appendees_)[0] ), ((void)0))) && _appendees_[_i_]; _i_++) _p_ = stpcpy (_p_, _appendees_[_i_]); *_p_ = 0; _d_; }); | |||
| 381 | if (message) | |||
| 382 | iovec[n++] = IOVEC_MAKE_STRING(message)(struct iovec) { .iov_base = ((char*) message), .iov_len = (strlen (message)) }; | |||
| 383 | ||||
| 384 | server_dispatch_message(s, iovec, n, m, context, tv, priority, 0); | |||
| 385 | } | |||
| 386 | ||||
| 387 | int server_open_syslog_socket(Server *s) { | |||
| 388 | ||||
| 389 | static const union sockaddr_union sa = { | |||
| 390 | .un.sun_family = AF_UNIX1, | |||
| 391 | .un.sun_path = "/run/systemd/journal/dev-log", | |||
| 392 | }; | |||
| 393 | static const int one = 1; | |||
| 394 | int r; | |||
| 395 | ||||
| 396 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/journal/journald-syslog.c" , 396, __PRETTY_FUNCTION__); } while (0); | |||
| 397 | ||||
| 398 | if (s->syslog_fd < 0) { | |||
| 399 | s->syslog_fd = socket(AF_UNIX1, SOCK_DGRAMSOCK_DGRAM|SOCK_CLOEXECSOCK_CLOEXEC|SOCK_NONBLOCKSOCK_NONBLOCK, 0); | |||
| 400 | if (s->syslog_fd < 0) | |||
| 401 | return log_error_errno(errno, "socket() failed: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/journal/journald-syslog.c", 401, __func__, "socket() failed: %m") : -abs(_e); }); | |||
| 402 | ||||
| 403 | (void) unlink(sa.un.sun_path); | |||
| 404 | ||||
| 405 | r = bind(s->syslog_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)({ const struct sockaddr_un *_sa = &(sa.un); do { if ((__builtin_expect (!!(!(_sa->sun_family == 1)),0))) log_assert_failed_realm( LOG_REALM_SYSTEMD, ("_sa->sun_family == AF_UNIX"), "../src/journal/journald-syslog.c" , 405, __PRETTY_FUNCTION__); } while (0); __builtin_offsetof( struct sockaddr_un, sun_path) + (_sa->sun_path[0] == 0 ? 1 + strnlen(_sa->sun_path+1, sizeof(_sa->sun_path)-1) : strnlen (_sa->sun_path, sizeof(_sa->sun_path))); })); | |||
| 406 | if (r < 0) | |||
| 407 | return log_error_errno(errno, "bind(%s) failed: %m", sa.un.sun_path)({ int _level = ((3)), _e = (((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/journal/journald-syslog.c", 407, __func__, "bind(%s) failed: %m", sa.un.sun_path) : -abs(_e); }); | |||
| 408 | ||||
| 409 | (void) chmod(sa.un.sun_path, 0666); | |||
| 410 | } else | |||
| 411 | fd_nonblock(s->syslog_fd, 1); | |||
| 412 | ||||
| 413 | r = setsockopt(s->syslog_fd, SOL_SOCKET1, SO_PASSCRED16, &one, sizeof(one)); | |||
| 414 | if (r < 0) | |||
| 415 | return log_error_errno(errno, "SO_PASSCRED failed: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/journal/journald-syslog.c", 415, __func__, "SO_PASSCRED failed: %m") : -abs(_e); }); | |||
| 416 | ||||
| 417 | #if HAVE_SELINUX1 | |||
| 418 | if (mac_selinux_use()) { | |||
| 419 | r = setsockopt(s->syslog_fd, SOL_SOCKET1, SO_PASSSEC34, &one, sizeof(one)); | |||
| 420 | if (r < 0) | |||
| 421 | log_warning_errno(errno, "SO_PASSSEC failed: %m")({ int _level = ((4)), _e = (((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/journal/journald-syslog.c", 421, __func__, "SO_PASSSEC failed: %m") : -abs(_e); }); | |||
| 422 | } | |||
| 423 | #endif | |||
| 424 | ||||
| 425 | r = setsockopt(s->syslog_fd, SOL_SOCKET1, SO_TIMESTAMP29, &one, sizeof(one)); | |||
| 426 | if (r < 0) | |||
| 427 | return log_error_errno(errno, "SO_TIMESTAMP failed: %m")({ int _level = ((3)), _e = (((*__errno_location ()))), _realm = (LOG_REALM_SYSTEMD); (log_get_max_level_realm(_realm) >= ((_level) & 0x07)) ? log_internal_realm(((_realm) << 10 | (_level)), _e, "../src/journal/journald-syslog.c", 427, __func__, "SO_TIMESTAMP failed: %m") : -abs(_e); }); | |||
| 428 | ||||
| 429 | r = sd_event_add_io(s->event, &s->syslog_event_source, s->syslog_fd, EPOLLINEPOLLIN, server_process_datagram, s); | |||
| 430 | if (r < 0) | |||
| 431 | return log_error_errno(r, "Failed to add syslog server fd to event loop: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal/journald-syslog.c", 431, __func__, "Failed to add syslog server fd to event loop: %m" ) : -abs(_e); }); | |||
| 432 | ||||
| 433 | r = sd_event_source_set_priority(s->syslog_event_source, SD_EVENT_PRIORITY_NORMAL+5); | |||
| 434 | if (r < 0) | |||
| 435 | return log_error_errno(r, "Failed to adjust syslog event source priority: %m")({ int _level = ((3)), _e = ((r)), _realm = (LOG_REALM_SYSTEMD ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/journal/journald-syslog.c", 435, __func__, "Failed to adjust syslog event source priority: %m" ) : -abs(_e); }); | |||
| 436 | ||||
| 437 | return 0; | |||
| 438 | } | |||
| 439 | ||||
| 440 | void server_maybe_warn_forward_syslog_missed(Server *s) { | |||
| 441 | usec_t n; | |||
| 442 | ||||
| 443 | assert(s)do { if ((__builtin_expect(!!(!(s)),0))) log_assert_failed_realm (LOG_REALM_SYSTEMD, ("s"), "../src/journal/journald-syslog.c" , 443, __PRETTY_FUNCTION__); } while (0); | |||
| 444 | ||||
| 445 | if (s->n_forward_syslog_missed <= 0) | |||
| 446 | return; | |||
| 447 | ||||
| 448 | n = now(CLOCK_MONOTONIC1); | |||
| 449 | if (s->last_warn_forward_syslog_missed + WARN_FORWARD_SYSLOG_MISSED_USEC(30 * ((usec_t) 1000000ULL)) > n) | |||
| 450 | return; | |||
| 451 | ||||
| 452 | server_driver_message(s, 0, | |||
| 453 | "MESSAGE_ID=" SD_MESSAGE_FORWARD_SYSLOG_MISSED_STR"00" "27" "22" "9c" "a0" "64" "41" "81" "a7" "6c" "4e" "92" "45" "8a" "fa" "2e", | |||
| 454 | LOG_MESSAGE("Forwarding to syslog missed %u messages.","MESSAGE=" "Forwarding to syslog missed %u messages.", s-> n_forward_syslog_missed | |||
| 455 | s->n_forward_syslog_missed)"MESSAGE=" "Forwarding to syslog missed %u messages.", s-> n_forward_syslog_missed, | |||
| 456 | NULL((void*)0)); | |||
| 457 | ||||
| 458 | s->n_forward_syslog_missed = 0; | |||
| 459 | s->last_warn_forward_syslog_missed = n; | |||
| 460 | } |