1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2011 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
24 #include <sys/epoll.h>
27 #include "socket-util.h"
28 #include "path-util.h"
29 #include "selinux-util.h"
30 #include "journald-server.h"
31 #include "journald-native.h"
32 #include "journald-kmsg.h"
33 #include "journald-console.h"
34 #include "journald-syslog.h"
35 #include "journald-wall.h"
36 #include "memfd-util.h"
38 bool valid_user_field(const char *p, size_t l, bool allow_protected) {
41 /* We kinda enforce POSIX syntax recommendations for
42 environment variables here, but make a couple of additional
45 http://pubs.opengroup.org/onlinepubs/000095399/basedefs/xbd_chap08.html */
47 /* No empty field names */
51 /* Don't allow names longer than 64 chars */
55 /* Variables starting with an underscore are protected */
56 if (!allow_protected && p[0] == '_')
59 /* Don't allow digits as first character */
60 if (p[0] >= '0' && p[0] <= '9')
63 /* Only allow A-Z0-9 and '_' */
64 for (a = p; a < p + l; a++)
65 if ((*a < 'A' || *a > 'Z') &&
66 (*a < '0' || *a > '9') &&
73 static bool allow_object_pid(const struct ucred *ucred) {
74 return ucred && ucred->uid == 0;
77 void server_process_native_message(
79 const void *buffer, size_t buffer_size,
80 const struct ucred *ucred,
81 const struct timeval *tv,
82 const char *label, size_t label_len) {
84 struct iovec *iovec = NULL;
85 unsigned n = 0, j, tn = (unsigned) -1;
87 size_t remaining, m = 0, entry_size = 0;
88 int priority = LOG_INFO;
89 char *identifier = NULL, *message = NULL;
93 assert(buffer || buffer_size == 0);
96 remaining = buffer_size;
98 while (remaining > 0) {
101 e = memchr(p, '\n', remaining);
104 /* Trailing noise, let's ignore it, and flush what we collected */
105 log_debug("Received message with trailing noise, ignoring.");
110 /* Entry separator */
112 if (entry_size + n + 1 > ENTRY_SIZE_MAX) { /* data + separators + trailer */
113 log_debug("Entry is too big with %u properties and %zu bytes, ignoring.", n, entry_size);
117 server_dispatch_message(s, iovec, n, m, ucred, tv, label, label_len, NULL, priority, object_pid);
127 if (*p == '.' || *p == '#') {
128 /* Ignore control commands for now, and
130 remaining -= (e - p) + 1;
135 /* A property follows */
137 /* n existing properties, 1 new, +1 for _TRANSPORT */
138 if (!GREEDY_REALLOC(iovec, m, n + 2 + N_IOVEC_META_FIELDS + N_IOVEC_OBJECT_FIELDS)) {
143 q = memchr(p, '=', e - p);
145 if (valid_user_field(p, q - p, false)) {
150 /* If the field name starts with an
151 * underscore, skip the variable,
152 * since that indidates a trusted
154 iovec[n].iov_base = (char*) p;
155 iovec[n].iov_len = l;
156 entry_size += iovec[n].iov_len;
159 /* We need to determine the priority
160 * of this entry for the rate limiting
163 startswith(p, "PRIORITY=") &&
164 p[9] >= '0' && p[9] <= '9')
165 priority = (priority & LOG_FACMASK) | (p[9] - '0');
168 startswith(p, "SYSLOG_FACILITY=") &&
169 p[16] >= '0' && p[16] <= '9')
170 priority = (priority & LOG_PRIMASK) | ((p[16] - '0') << 3);
173 startswith(p, "SYSLOG_FACILITY=") &&
174 p[16] >= '0' && p[16] <= '9' &&
175 p[17] >= '0' && p[17] <= '9')
176 priority = (priority & LOG_PRIMASK) | (((p[16] - '0')*10 + (p[17] - '0')) << 3);
179 startswith(p, "SYSLOG_IDENTIFIER=")) {
182 t = strndup(p + 18, l - 18);
188 startswith(p, "MESSAGE=")) {
191 t = strndup(p + 8, l - 8);
196 } else if (l > strlen("OBJECT_PID=") &&
197 l < strlen("OBJECT_PID=") + DECIMAL_STR_MAX(pid_t) &&
198 startswith(p, "OBJECT_PID=") &&
199 allow_object_pid(ucred)) {
200 char buf[DECIMAL_STR_MAX(pid_t)];
201 memcpy(buf, p + strlen("OBJECT_PID="), l - strlen("OBJECT_PID="));
205 parse_pid(buf, &object_pid);
209 remaining -= (e - p) + 1;
217 if (remaining < e - p + 1 + sizeof(uint64_t) + 1) {
218 log_debug("Failed to parse message, ignoring.");
222 memcpy(&l_le, e + 1, sizeof(uint64_t));
225 if (l > DATA_SIZE_MAX) {
226 log_debug("Received binary data block of %"PRIu64" bytes is too large, ignoring.", l);
230 if ((uint64_t) remaining < e - p + 1 + sizeof(uint64_t) + l + 1 ||
231 e[1+sizeof(uint64_t)+l] != '\n') {
232 log_debug("Failed to parse message, ignoring.");
236 k = malloc((e - p) + 1 + l);
244 memcpy(k + (e - p) + 1, e + 1 + sizeof(uint64_t), l);
246 if (valid_user_field(p, e - p, false)) {
247 iovec[n].iov_base = k;
248 iovec[n].iov_len = (e - p) + 1 + l;
249 entry_size += iovec[n].iov_len;
254 remaining -= (e - p) + 1 + sizeof(uint64_t) + l + 1;
255 p = e + 1 + sizeof(uint64_t) + l + 1;
263 IOVEC_SET_STRING(iovec[tn], "_TRANSPORT=journal");
264 entry_size += strlen("_TRANSPORT=journal");
266 if (entry_size + n + 1 > ENTRY_SIZE_MAX) { /* data + separators + trailer */
267 log_debug("Entry is too big with %u properties and %zu bytes, ignoring.",
273 if (s->forward_to_syslog)
274 server_forward_syslog(s, priority, identifier, message, ucred, tv);
276 if (s->forward_to_kmsg)
277 server_forward_kmsg(s, priority, identifier, message, ucred);
279 if (s->forward_to_console)
280 server_forward_console(s, priority, identifier, message, ucred);
282 if (s->forward_to_wall)
283 server_forward_wall(s, priority, identifier, message, ucred);
286 server_dispatch_message(s, iovec, n, m, ucred, tv, label, label_len, NULL, priority, object_pid);
289 for (j = 0; j < n; j++) {
293 if (iovec[j].iov_base < buffer ||
294 (const uint8_t*) iovec[j].iov_base >= (const uint8_t*) buffer + buffer_size)
295 free(iovec[j].iov_base);
303 void server_process_native_file(
306 const struct ucred *ucred,
307 const struct timeval *tv,
308 const char *label, size_t label_len) {
314 /* Data is in the passed fd, since it didn't fit in a
320 /* If it's a memfd, check if it is sealed. If so, we can just
321 * use map it and use it, and do not need to copy the data
323 sealed = memfd_get_sealed(fd) > 0;
325 if (!sealed && (!ucred || ucred->uid != 0)) {
326 _cleanup_free_ char *sl = NULL, *k = NULL;
329 /* If this is not a sealed memfd, and the peer is unknown or
330 * unprivileged, then verify the path. */
332 if (asprintf(&sl, "/proc/self/fd/%i", fd) < 0) {
337 r = readlink_malloc(sl, &k);
339 log_error_errno(errno, "readlink(%s) failed: %m", sl);
343 e = path_startswith(k, "/dev/shm/");
345 e = path_startswith(k, "/tmp/");
347 e = path_startswith(k, "/var/tmp/");
349 log_error("Received file outside of allowed directories. Refusing.");
353 if (!filename_is_valid(e)) {
354 log_error("Received file in subdirectory of allowed directories. Refusing.");
359 if (fstat(fd, &st) < 0) {
360 log_error_errno(errno, "Failed to stat passed file, ignoring: %m");
364 if (!S_ISREG(st.st_mode)) {
365 log_error("File passed is not regular. Ignoring.");
372 if (st.st_size > ENTRY_SIZE_MAX) {
373 log_error("File passed too large. Ignoring.");
381 /* The file is sealed, we can just map it and use it. */
383 ps = PAGE_ALIGN(st.st_size);
384 p = mmap(NULL, ps, PROT_READ, MAP_PRIVATE, fd, 0);
385 if (p == MAP_FAILED) {
386 log_error_errno(errno, "Failed to map memfd, ignoring: %m");
390 server_process_native_message(s, p, st.st_size, ucred, tv, label, label_len);
391 assert_se(munmap(p, ps) >= 0);
393 _cleanup_free_ void *p = NULL;
396 /* The file is not sealed, we can't map the file here, since
397 * clients might then truncate it and trigger a SIGBUS for
398 * us. So let's stupidly read it */
400 p = malloc(st.st_size);
406 n = pread(fd, p, st.st_size, 0);
408 log_error_errno(n, "Failed to read file, ignoring: %m");
410 server_process_native_message(s, p, n, ucred, tv, label, label_len);
414 int server_open_native_socket(Server*s) {
415 static const int one = 1;
420 if (s->native_fd < 0) {
421 union sockaddr_union sa = {
422 .un.sun_family = AF_UNIX,
423 .un.sun_path = "/run/systemd/journal/socket",
426 s->native_fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
427 if (s->native_fd < 0)
428 return log_error_errno(errno, "socket() failed: %m");
430 unlink(sa.un.sun_path);
432 r = bind(s->native_fd, &sa.sa, offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path));
434 return log_error_errno(errno, "bind(%s) failed: %m", sa.un.sun_path);
436 chmod(sa.un.sun_path, 0666);
438 fd_nonblock(s->native_fd, 1);
440 r = setsockopt(s->native_fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one));
442 return log_error_errno(errno, "SO_PASSCRED failed: %m");
445 if (mac_selinux_use()) {
446 r = setsockopt(s->native_fd, SOL_SOCKET, SO_PASSSEC, &one, sizeof(one));
448 log_warning_errno(errno, "SO_PASSSEC failed: %m");
452 r = setsockopt(s->native_fd, SOL_SOCKET, SO_TIMESTAMP, &one, sizeof(one));
454 return log_error_errno(errno, "SO_TIMESTAMP failed: %m");
456 r = sd_event_add_io(s->event, &s->native_event_source, s->native_fd, EPOLLIN, server_process_datagram, s);
458 return log_error_errno(r, "Failed to add native server fd to event loop: %m");