journald-native.c revision be2155ce705c1c1a25fa5b2927e2e02f4b3c7a35
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering This file is part of systemd.
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering Copyright 2011 Lennart Poettering
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering systemd is free software; you can redistribute it and/or modify it
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering under the terms of the GNU Lesser General Public License as published by
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering the Free Software Foundation; either version 2.1 of the License, or
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering (at your option) any later version.
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering systemd is distributed in the hope that it will be useful, but
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering Lesser General Public License for more details.
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering You should have received a copy of the GNU Lesser General Public License
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poetteringstatic bool valid_user_field(const char *p, size_t l) {
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering const char *a;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering /* We kinda enforce POSIX syntax recommendations for
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering environment variables here, but make a couple of additional
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering http://pubs.opengroup.org/onlinepubs/000095399/basedefs/xbd_chap08.html */
5ffa8c818120e35c89becd938d160235c069dd12Zbigniew Jędrzejewski-Szmek /* No empty field names */
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering /* Don't allow names longer than 64 chars */
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering /* Variables starting with an underscore are protected */
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering if (p[0] == '_')
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering /* Don't allow digits as first character */
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering /* Only allow A-Z0-9 and '_' */
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering for (a = p; a < p + l; a++)
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering unsigned n = 0, m = 0, j, tn = (unsigned) -1;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering const char *p;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering char *identifier = NULL, *message = NULL;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering const char *e, *q;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering /* Trailing noise, let's ignore it, and flush what we collected */
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering log_debug("Received message with trailing noise, ignoring.");
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering /* Entry separator */
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering server_dispatch_message(s, iovec, n, m, ucred, tv, label, label_len, NULL, priority);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering /* Ignore control commands for now, and
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering * comments too. */
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering /* A property follows */
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering u = MAX((n+N_IOVEC_META_FIELDS+1) * 2U, 4U);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering c = realloc(iovec, u * sizeof(struct iovec));
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering /* If the field name starts with an
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering * underscore, skip the variable,
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering * since that indidates a trusted
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering /* We need to determine the priority
507f22bd0172bff5e5d98145b1419bd472a2c57fZbigniew Jędrzejewski-Szmek * of this entry for the rate limiting
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering if (l == 10 &&
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering priority = (priority & LOG_FACMASK) | (p[9] - '0');
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering else if (l == 17 &&
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering memcmp(p, "SYSLOG_FACILITY=", 16) == 0 &&
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering priority = (priority & LOG_PRIMASK) | ((p[16] - '0') << 3);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering else if (l == 18 &&
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering memcmp(p, "SYSLOG_FACILITY=", 16) == 0 &&
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering priority = (priority & LOG_PRIMASK) | (((p[16] - '0')*10 + (p[17] - '0')) << 3);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering else if (l >= 19 &&
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering memcmp(p, "SYSLOG_IDENTIFIER=", 18) == 0) {
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering } else if (l >= 8 &&
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering if (remaining < e - p + 1 + sizeof(uint64_t) + 1) {
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering log_debug("Failed to parse message, ignoring.");
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering log_debug("Received binary data block too large, ignoring.");
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering if ((uint64_t) remaining < e - p + 1 + sizeof(uint64_t) + l + 1 ||
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering log_debug("Failed to parse message, ignoring.");
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering k[e - p] = '=';
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering memcpy(k + (e - p) + 1, e + 1 + sizeof(uint64_t), l);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering remaining -= (e - p) + 1 + sizeof(uint64_t) + l + 1;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering IOVEC_SET_STRING(iovec[tn], "_TRANSPORT=journal");
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering server_forward_syslog(s, priority, identifier, message, ucred, tv);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering server_forward_kmsg(s, priority, identifier, message, ucred);
4b94f3b8f7693f076e5c85bc2c02cf028192d8deZbigniew Jędrzejewski-Szmek server_forward_console(s, priority, identifier, message, ucred);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering server_dispatch_message(s, iovec, n, m, ucred, tv, label, label_len, NULL, priority);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering for (j = 0; j < n; j++) {
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering (const uint8_t*) iovec[j].iov_base >= (const uint8_t*) buffer + buffer_size)
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering _cleanup_free_ char *sl = NULL, *k = NULL;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering const char *e;
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering if (asprintf(&sl, "/proc/self/fd/%i", fd) < 0) {
527b7a421ff3927d4f3f170b1b143452e88ae1dcLennart Poettering log_error("readlink(%s) failed: %m", sl);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering log_error("Received file outside of allowed directories. Refusing.");
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering log_error("Received file in subdirectory of allowed directories. Refusing.");
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering /* Data is in the passed file, since it didn't fit in a
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering * datagram. We can't map the file here, since clients might
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering * then truncate it and trigger a SIGBUS for us. So let's
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering * stupidly read it */
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering log_error("Failed to stat passed file, ignoring: %m");
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering log_error("File passed is not regular. Ignoring.");
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering log_error("File passed too large. Ignoring.");
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering log_error("Failed to read file, ignoring: %s", strerror(-n));
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering else if (n > 0)
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering server_process_native_message(s, p, n, ucred, tv, label, label_len);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering s->native_fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering strncpy(sa.un.sun_path, "/run/systemd/journal/socket", sizeof(sa.un.sun_path));
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering r = bind(s->native_fd, &sa.sa, offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path));
f9a810bedacf1da7c505c1786a2416d592665926Lennart Poettering r = setsockopt(s->native_fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one));
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering r = setsockopt(s->native_fd, SOL_SOCKET, SO_PASSSEC, &one, sizeof(one));
151b9b9662a90455262ce575a8a8ae74bf4ff336Lennart Poettering r = setsockopt(s->native_fd, SOL_SOCKET, SO_TIMESTAMP, &one, sizeof(one));
ef63833d532dd86bdba63211e6a1363cbb3ef61dLennart Poettering if (epoll_ctl(s->epoll_fd, EPOLL_CTL_ADD, s->native_fd, &ev) < 0) {
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt log_error("Failed to add native server fd to epoll object: %m");