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 | } |