journald-native.c revision d18d46ecea80a7f07415edb9264af6a254fd70bb
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer This file is part of systemd.
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer Copyright 2011 Lennart Poettering
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer systemd is free software; you can redistribute it and/or modify it
0d6e798a784ef0ba6b95512e4453067b2f84a91aHarald Hoyer under the terms of the GNU Lesser General Public License as published by
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer the Free Software Foundation; either version 2.1 of the License, or
3486cb6cfa3d32a95c0daf02c7510fdf372507bfMartin Pitt (at your option) any later version.
3486cb6cfa3d32a95c0daf02c7510fdf372507bfMartin Pitt systemd is distributed in the hope that it will be useful, but
3486cb6cfa3d32a95c0daf02c7510fdf372507bfMartin Pitt WITHOUT ANY WARRANTY; without even the implied warranty of
3486cb6cfa3d32a95c0daf02c7510fdf372507bfMartin Pitt MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
4be4833ece2856e0cacc09f8f8b2c02b320751faMartin Pitt Lesser General Public License for more details.
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier You should have received a copy of the GNU Lesser General Public License
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier along with systemd; If not, see <http://www.gnu.org/licenses/>.
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalierbool valid_user_field(const char *p, size_t l, bool allow_protected) {
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier const char *a;
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier /* We kinda enforce POSIX syntax recommendations for
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier environment variables here, but make a couple of additional
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier requirements.
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier http://pubs.opengroup.org/onlinepubs/000095399/basedefs/xbd_chap08.html */
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier /* No empty field names */
b6f0c419e38a960873fe68bf8f89bbb0268eed02Harald Hoyer return false;
b6f0c419e38a960873fe68bf8f89bbb0268eed02Harald Hoyer /* Don't allow names longer than 64 chars */
b6f0c419e38a960873fe68bf8f89bbb0268eed02Harald Hoyer return false;
b6f0c419e38a960873fe68bf8f89bbb0268eed02Harald Hoyer /* Variables starting with an underscore are protected */
61fea35e14d84144e6e2122f5cd247f9c7e6245eEvgeny Vereshchagin /* Don't allow digits as first character */
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier return false;
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier /* Only allow A-Z0-9 and '_' */
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier for (a = p; a < p + l; a++)
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier return false;
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalierstatic bool allow_object_pid(struct ucred *ucred) {
c6a77179a4097df355f0f04b8f3260c76b5e515cRonny Chevalier const char *p;
8a8332f77e61d41f3bb28b8f929ed41e0ffaf721Zbigniew Jędrzejewski-Szmek char *identifier = NULL, *message = NULL;
8a8332f77e61d41f3bb28b8f929ed41e0ffaf721Zbigniew Jędrzejewski-Szmek assert(buffer || buffer_size == 0);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier const char *e, *q;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier /* Trailing noise, let's ignore it, and flush what we collected */
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier log_debug("Received message with trailing noise, ignoring.");
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (e == p) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier /* Entry separator */
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier server_dispatch_message(s, iovec, n, m, ucred, tv, label, label_len, NULL, priority, object_pid);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier /* Ignore control commands for now, and
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier * comments too. */
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier /* A property follows */
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier /* n received properties, +1 for _TRANSPORT */
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (!GREEDY_REALLOC(iovec, m, n + 1 + N_IOVEC_META_FIELDS +
8a8332f77e61d41f3bb28b8f929ed41e0ffaf721Zbigniew Jędrzejewski-Szmek !!object_pid * N_IOVEC_OBJECT_FIELDS)) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (valid_user_field(p, q - p, false)) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier /* If the field name starts with an
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier * underscore, skip the variable,
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier * since that indidates a trusted
739d81ddd005fae2bb82edce5b8a6173c7c48b34Zbigniew Jędrzejewski-Szmek /* We need to determine the priority
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier * of this entry for the rate limiting
edbced8a151c1b7ded685e2ec644950d2adec5f5Harald Hoyer if (l == 10 &&
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier priority = (priority & LOG_FACMASK) | (p[9] - '0');
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier else if (l == 17 &&
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier priority = (priority & LOG_PRIMASK) | ((p[16] - '0') << 3);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier else if (l == 18 &&
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier priority = (priority & LOG_PRIMASK) | (((p[16] - '0')*10 + (p[17] - '0')) << 3);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier else if (l >= 19 &&
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier } else if (l >= 8 &&
c7eda0133b6bf13a182337cbe8a61bf2faf9b32eEvgeny Vereshchagin l < strlen("OBJECT_PID=") + DECIMAL_STR_MAX(pid_t) &&
c7eda0133b6bf13a182337cbe8a61bf2faf9b32eEvgeny Vereshchagin memcpy(buf, p + strlen("OBJECT_PID="), l - strlen("OBJECT_PID="));
c7eda0133b6bf13a182337cbe8a61bf2faf9b32eEvgeny Vereshchagin /* ignore error */
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (remaining < e - p + 1 + sizeof(uint64_t) + 1) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier log_debug("Failed to parse message, ignoring.");
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier log_debug("Received binary data block too large, ignoring.");
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if ((uint64_t) remaining < e - p + 1 + sizeof(uint64_t) + l + 1 ||
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier log_debug("Failed to parse message, ignoring.");
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier k[e - p] = '=';
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier memcpy(k + (e - p) + 1, e + 1 + sizeof(uint64_t), l);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (valid_user_field(p, e - p, false)) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier remaining -= (e - p) + 1 + sizeof(uint64_t) + l + 1;
4be4833ece2856e0cacc09f8f8b2c02b320751faMartin Pitt IOVEC_SET_STRING(iovec[tn], "_TRANSPORT=journal");
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier server_forward_syslog(s, priority, identifier, message, ucred, tv);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier server_forward_kmsg(s, priority, identifier, message, ucred);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier server_forward_console(s, priority, identifier, message, ucred);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier server_forward_wall(s, priority, identifier, message, ucred);
3486cb6cfa3d32a95c0daf02c7510fdf372507bfMartin Pitt server_dispatch_message(s, iovec, n, m, ucred, tv, label, label_len, NULL, priority, object_pid);
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier for (j = 0; j < n; j++) {
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier (const uint8_t*) iovec[j].iov_base >= (const uint8_t*) buffer + buffer_size)
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier const char *e;
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier if (asprintf(&sl, "/proc/self/fd/%i", fd) < 0) {
53d90f9582f96208b3674da823ad1a3d2c3b1aa4Martin Pitt log_error("Received file outside of allowed directories. Refusing.");
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier log_error("Received file in subdirectory of allowed directories. Refusing.");
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier /* Data is in the passed file, since it didn't fit in a
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier * datagram. We can't map the file here, since clients might
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier * then truncate it and trigger a SIGBUS for us. So let's
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier * stupidly read it */
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier log_error("Failed to stat passed file, ignoring: %m");
889a90422dd47284dffa32b9234a6e58991b000cRonny Chevalier log_error("File passed is not regular. Ignoring.");
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer log_error("Failed to read file, ignoring: %s", strerror(-n));
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer else if (n > 0)
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer server_process_native_message(s, p, n, ucred, tv, label, label_len);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer s->native_fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer strncpy(sa.un.sun_path, "/run/systemd/journal/socket", sizeof(sa.un.sun_path));
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = bind(s->native_fd, &sa.sa, offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path));
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (r < 0) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = setsockopt(s->native_fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one));
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (r < 0) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = setsockopt(s->native_fd, SOL_SOCKET, SO_PASSSEC, &one, sizeof(one));
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = setsockopt(s->native_fd, SOL_SOCKET, SO_TIMESTAMP, &one, sizeof(one));
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (r < 0) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer r = sd_event_add_io(s->event, &s->native_event_source, s->native_fd, EPOLLIN, process_datagram, s);
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer if (r < 0) {
898720b7e9cf3bdf7a93e435cbed5dd6942ecf9bHarald Hoyer log_error("Failed to add native server fd to event loop: %s", strerror(-r));