journald-native.c revision 1dfa7e79a60de680086b1d93fcc3629b463f58bd
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen/***
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen This file is part of systemd.
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen Copyright 2011 Lennart Poettering
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen systemd is free software; you can redistribute it and/or modify it
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen under the terms of the GNU Lesser General Public License as published by
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen the Free Software Foundation; either version 2.1 of the License, or
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen (at your option) any later version.
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen systemd is distributed in the hope that it will be useful, but
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen WITHOUT ANY WARRANTY; without even the implied warranty of
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen Lesser General Public License for more details.
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen You should have received a copy of the GNU Lesser General Public License
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen along with systemd; If not, see <http://www.gnu.org/licenses/>.
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen***/
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen#include <unistd.h>
2a73e0d39a9bec82c3800071e375d27164727e71Tom Gundersen#include <stddef.h>
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen#include <sys/epoll.h>
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen#include "socket-util.h"
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen#include "path-util.h"
a501033335ed402c8f7e86fe41a15531ba69abd7Tom Gundersen#include "journald.h"
a501033335ed402c8f7e86fe41a15531ba69abd7Tom Gundersen#include "journald-native.h"
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen#include "journald-kmsg.h"
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen#include "journald-console.h"
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen#include "journald-syslog.h"
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen#define ENTRY_SIZE_MAX (1024*1024*64)
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen#define DATA_SIZE_MAX (1024*1024*64)
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersenstatic bool valid_user_field(const char *p, size_t l) {
daeb71a36a98834664e4d95773a3629b746f4db8Tom Gundersen const char *a;
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen
3aeb37bc4f32b5edc334f2ac7c5d3c7b0a121328Tom Gundersen /* We kinda enforce POSIX syntax recommendations for
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen environment variables here, but make a couple of additional
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering requirements.
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen http://pubs.opengroup.org/onlinepubs/000095399/basedefs/xbd_chap08.html */
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen /* No empty field names */
a501033335ed402c8f7e86fe41a15531ba69abd7Tom Gundersen if (l <= 0)
a501033335ed402c8f7e86fe41a15531ba69abd7Tom Gundersen return false;
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen /* Don't allow names longer than 64 chars */
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen if (l > 64)
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen return false;
97f2d76d4f4dfab8b0629c09926a05a1e5621125Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen /* Variables starting with an underscore are protected */
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen if (p[0] == '_')
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek return false;
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek /* Don't allow digits as first character */
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek if (p[0] >= '0' && p[0] <= '9')
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek return false;
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek /* Only allow A-Z0-9 and '_' */
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek for (a = p; a < p + l; a++)
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek if (!((*a >= 'A' && *a <= 'Z') ||
5b9d4dc05560ddda89e48b6b39365824b15e1300Tom Gundersen (*a >= '0' && *a <= '9') ||
5b9d4dc05560ddda89e48b6b39365824b15e1300Tom Gundersen *a == '_'))
5b9d4dc05560ddda89e48b6b39365824b15e1300Tom Gundersen return false;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
5b9d4dc05560ddda89e48b6b39365824b15e1300Tom Gundersen return true;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen}
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersenvoid server_process_native_message(
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen Server *s,
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen const void *buffer, size_t buffer_size,
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen struct ucred *ucred,
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen struct timeval *tv,
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen const char *label, size_t label_len) {
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen struct iovec *iovec = NULL;
977085794d2996320e345433403de75f662b0622Tom Gundersen unsigned n = 0, m = 0, j, tn = (unsigned) -1;
977085794d2996320e345433403de75f662b0622Tom Gundersen const char *p;
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen size_t remaining;
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen int priority = LOG_INFO;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen char *identifier = NULL, *message = NULL;
5b9d4dc05560ddda89e48b6b39365824b15e1300Tom Gundersen
5b9d4dc05560ddda89e48b6b39365824b15e1300Tom Gundersen assert(s);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen assert(buffer || buffer_size == 0);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen p = buffer;
977085794d2996320e345433403de75f662b0622Tom Gundersen remaining = buffer_size;
977085794d2996320e345433403de75f662b0622Tom Gundersen
977085794d2996320e345433403de75f662b0622Tom Gundersen while (remaining > 0) {
977085794d2996320e345433403de75f662b0622Tom Gundersen const char *e, *q;
977085794d2996320e345433403de75f662b0622Tom Gundersen
977085794d2996320e345433403de75f662b0622Tom Gundersen e = memchr(p, '\n', remaining);
977085794d2996320e345433403de75f662b0622Tom Gundersen
977085794d2996320e345433403de75f662b0622Tom Gundersen if (!e) {
977085794d2996320e345433403de75f662b0622Tom Gundersen /* Trailing noise, let's ignore it, and flush what we collected */
977085794d2996320e345433403de75f662b0622Tom Gundersen log_debug("Received message with trailing noise, ignoring.");
977085794d2996320e345433403de75f662b0622Tom Gundersen break;
977085794d2996320e345433403de75f662b0622Tom Gundersen }
977085794d2996320e345433403de75f662b0622Tom Gundersen
977085794d2996320e345433403de75f662b0622Tom Gundersen if (e == p) {
977085794d2996320e345433403de75f662b0622Tom Gundersen /* Entry separator */
977085794d2996320e345433403de75f662b0622Tom Gundersen server_dispatch_message(s, iovec, n, m, ucred, tv, label, label_len, NULL, priority);
977085794d2996320e345433403de75f662b0622Tom Gundersen n = 0;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen priority = LOG_INFO;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen p++;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen remaining--;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen continue;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen }
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen if (*p == '.' || *p == '#') {
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen /* Ignore control commands for now, and
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen * comments too. */
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen remaining -= (e - p) + 1;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen p = e + 1;
d2df0d0ed3a88e491405b403e6022e6619750130Tom Gundersen continue;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen }
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen /* A property follows */
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen if (n+N_IOVEC_META_FIELDS >= m) {
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen struct iovec *c;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen unsigned u;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen u = MAX((n+N_IOVEC_META_FIELDS+1) * 2U, 4U);
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen c = realloc(iovec, u * sizeof(struct iovec));
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen if (!c) {
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen log_oom();
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen break;
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen }
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen iovec = c;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen m = u;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen }
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen q = memchr(p, '=', e - p);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen if (q) {
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen if (valid_user_field(p, q - p)) {
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen size_t l;
2fd069b18e525860514a70d3ea08410ca122d3e2Zbigniew Jędrzejewski-Szmek
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen l = e - p;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
187dc6e554f2d5b4b5a3bee72c73ff5df6418aa6Thomas Hindoe Paaboel Andersen /* If the field name starts with an
187dc6e554f2d5b4b5a3bee72c73ff5df6418aa6Thomas Hindoe Paaboel Andersen * underscore, skip the variable,
187dc6e554f2d5b4b5a3bee72c73ff5df6418aa6Thomas Hindoe Paaboel Andersen * since that indidates a trusted
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen * field */
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen iovec[n].iov_base = (char*) p;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen iovec[n].iov_len = l;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen n++;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen /* We need to determine the priority
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen * of this entry for the rate limiting
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen * logic */
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen if (l == 10 &&
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen memcmp(p, "PRIORITY=", 9) == 0 &&
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen p[9] >= '0' && p[9] <= '9')
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen priority = (priority & LOG_FACMASK) | (p[9] - '0');
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen else if (l == 17 &&
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen memcmp(p, "SYSLOG_FACILITY=", 16) == 0 &&
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen p[16] >= '0' && p[16] <= '9')
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen priority = (priority & LOG_PRIMASK) | ((p[16] - '0') << 3);
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen else if (l == 18 &&
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen memcmp(p, "SYSLOG_FACILITY=", 16) == 0 &&
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen p[16] >= '0' && p[16] <= '9' &&
489124365d1d391864898b9869dd668eea5b2e28Dave Reisner p[17] >= '0' && p[17] <= '9')
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen priority = (priority & LOG_PRIMASK) | (((p[16] - '0')*10 + (p[17] - '0')) << 3);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
98a375f6d5cac24eb80d6d4e00699851324afdecTom Gundersen else if (l >= 19 &&
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen memcmp(p, "SYSLOG_IDENTIFIER=", 18) == 0) {
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen char *t;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen t = strndup(p + 18, l - 18);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen if (t) {
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen free(identifier);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen identifier = t;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen }
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen } else if (l >= 8 &&
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen memcmp(p, "MESSAGE=", 8) == 0) {
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen char *t;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen t = strndup(p + 8, l - 8);
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen if (t) {
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen free(message);
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen message = t;
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen }
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen }
74df0fca09b3c31ed19e14ba80f996fdff772417Lennart Poettering }
74df0fca09b3c31ed19e14ba80f996fdff772417Lennart Poettering
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen remaining -= (e - p) + 1;
74df0fca09b3c31ed19e14ba80f996fdff772417Lennart Poettering p = e + 1;
74df0fca09b3c31ed19e14ba80f996fdff772417Lennart Poettering continue;
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen } else {
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen le64_t l_le;
ff83aac3647e21f31ac5e2b575ec1285dc585f6bTom Gundersen uint64_t l;
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen char *k;
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen if (remaining < e - p + 1 + sizeof(uint64_t) + 1) {
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen log_debug("Failed to parse message, ignoring.");
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen break;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen }
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen memcpy(&l_le, e + 1, sizeof(uint64_t));
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen l = le64toh(l_le);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen if (l > DATA_SIZE_MAX) {
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen log_debug("Received binary data block too large, ignoring.");
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen break;
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen }
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen if ((uint64_t) remaining < e - p + 1 + sizeof(uint64_t) + l + 1 ||
97f2d76d4f4dfab8b0629c09926a05a1e5621125Tom Gundersen e[1+sizeof(uint64_t)+l] != '\n') {
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek log_debug("Failed to parse message, ignoring.");
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen break;
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek }
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen k = malloc((e - p) + 1 + l);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen if (!k) {
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen log_oom();
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen break;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen }
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen memcpy(k, p, e - p);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen k[e - p] = '=';
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen memcpy(k + (e - p) + 1, e + 1 + sizeof(uint64_t), l);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen if (valid_user_field(p, e - p)) {
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen iovec[n].iov_base = k;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen iovec[n].iov_len = (e - p) + 1 + l;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen n++;
2ad8416dd057e7e3185169609ca3006e7649f576Zbigniew Jędrzejewski-Szmek } else
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen free(k);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen remaining -= (e - p) + 1 + sizeof(uint64_t) + l + 1;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen p = e + 1 + sizeof(uint64_t) + l + 1;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen }
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen }
b3e013148603aa670bc2c060ac63d48e54d76fc2Tom Gundersen
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen if (n <= 0)
b3e013148603aa670bc2c060ac63d48e54d76fc2Tom Gundersen goto finish;
b3e013148603aa670bc2c060ac63d48e54d76fc2Tom Gundersen
b3e013148603aa670bc2c060ac63d48e54d76fc2Tom Gundersen tn = n++;
b3e013148603aa670bc2c060ac63d48e54d76fc2Tom Gundersen IOVEC_SET_STRING(iovec[tn], "_TRANSPORT=journal");
b3e013148603aa670bc2c060ac63d48e54d76fc2Tom Gundersen
b3e013148603aa670bc2c060ac63d48e54d76fc2Tom Gundersen if (message) {
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen if (s->forward_to_syslog)
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen server_forward_syslog(s, priority, identifier, message, ucred, tv);
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen if (s->forward_to_kmsg)
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen server_forward_kmsg(s, priority, identifier, message, ucred);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen if (s->forward_to_console)
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen server_forward_console(s, priority, identifier, message, ucred);
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen }
be32eb9b7fbcb22e4b648086d644135e38279633Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen server_dispatch_message(s, iovec, n, m, ucred, tv, label, label_len, NULL, priority);
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersenfinish:
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen for (j = 0; j < n; j++) {
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen if (j == tn)
f1ac700248f231b7bdac2aafe8c35650efddb89fTom Gundersen continue;
f1ac700248f231b7bdac2aafe8c35650efddb89fTom Gundersen
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen if (iovec[j].iov_base < buffer ||
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen (const uint8_t*) iovec[j].iov_base >= (const uint8_t*) buffer + buffer_size)
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen free(iovec[j].iov_base);
f1ac700248f231b7bdac2aafe8c35650efddb89fTom Gundersen }
f1ac700248f231b7bdac2aafe8c35650efddb89fTom Gundersen
f1ac700248f231b7bdac2aafe8c35650efddb89fTom Gundersen free(iovec);
f1ac700248f231b7bdac2aafe8c35650efddb89fTom Gundersen free(identifier);
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen free(message);
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen}
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersenvoid server_process_native_file(
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen Server *s,
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen int fd,
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen struct ucred *ucred,
f1ac700248f231b7bdac2aafe8c35650efddb89fTom Gundersen struct timeval *tv,
f1ac700248f231b7bdac2aafe8c35650efddb89fTom Gundersen const char *label, size_t label_len) {
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen struct stat st;
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen _cleanup_free_ void *p = NULL;
f1ac700248f231b7bdac2aafe8c35650efddb89fTom Gundersen ssize_t n;
f1ac700248f231b7bdac2aafe8c35650efddb89fTom Gundersen int r;
f1ac700248f231b7bdac2aafe8c35650efddb89fTom Gundersen
f1ac700248f231b7bdac2aafe8c35650efddb89fTom Gundersen assert(s);
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen assert(fd >= 0);
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen if (!ucred || ucred->uid != 0) {
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen _cleanup_free_ char *sl = NULL, *k = NULL;
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen const char *e;
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering if (asprintf(&sl, "/proc/self/fd/%i", fd) < 0) {
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen log_oom();
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering return;
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen }
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering r = readlink_malloc(sl, &k);
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen if (r < 0) {
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen log_error("readlink(%s) failed: %m", sl);
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering return;
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering }
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen e = path_startswith(k, "/dev/shm/");
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen if (!e)
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen e = path_startswith(k, "/tmp/");
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen if (!e)
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen e = path_startswith(k, "/var/tmp/");
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen if (!e) {
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen log_error("Received file outside of allowed directories. Refusing.");
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen return;
55428d84f31b52da1c50b7469f14e15740547f20Tom Gundersen }
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen if (strchr(e, '/')) {
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering log_error("Received file in subdirectory of allowed directories. Refusing.");
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering return;
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering }
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering }
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen /* Data is in the passed file, since it didn't fit in a
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering * datagram. We can't map the file here, since clients might
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen * then truncate it and trigger a SIGBUS for us. So let's
55428d84f31b52da1c50b7469f14e15740547f20Tom Gundersen * stupidly read it */
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen if (fstat(fd, &st) < 0) {
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering log_error("Failed to stat passed file, ignoring: %m");
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering return;
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering }
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen if (!S_ISREG(st.st_mode)) {
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering log_error("File passed is not regular. Ignoring.");
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poettering return;
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen }
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen if (st.st_size <= 0)
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen return;
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen if (st.st_size > ENTRY_SIZE_MAX) {
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen log_error("File passed too large. Ignoring.");
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen return;
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen }
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen p = malloc(st.st_size);
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen if (!p) {
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen log_oom();
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen return;
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen }
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen n = pread(fd, p, st.st_size, 0);
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen if (n < 0)
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen log_error("Failed to read file, ignoring: %s", strerror(-n));
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen else if (n > 0)
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen server_process_native_message(s, p, n, ucred, tv, label, label_len);
977085794d2996320e345433403de75f662b0622Tom Gundersen}
977085794d2996320e345433403de75f662b0622Tom Gundersen
977085794d2996320e345433403de75f662b0622Tom Gundersenint server_open_native_socket(Server*s) {
977085794d2996320e345433403de75f662b0622Tom Gundersen union sockaddr_union sa;
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen int one, r;
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen struct epoll_event ev;
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen assert(s);
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen if (s->native_fd < 0) {
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen s->native_fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
a501033335ed402c8f7e86fe41a15531ba69abd7Tom Gundersen if (s->native_fd < 0) {
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen log_error("socket() failed: %m");
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen return -errno;
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen }
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen
af6f0d422c521374ee6a2dd92df5935a5a476ae5Tom Gundersen zero(sa);
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen sa.un.sun_family = AF_UNIX;
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen strncpy(sa.un.sun_path, "/run/systemd/journal/socket", sizeof(sa.un.sun_path));
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen unlink(sa.un.sun_path);
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen
43b3a5ef61859f06cdbaf26765cab8e1adac4296Tom Gundersen r = bind(s->native_fd, &sa.sa, offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path));
f61942250a43a123580d7bbe5d7873dc5118ed97Tom Gundersen if (r < 0) {
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen log_error("bind() failed: %m");
daeb71a36a98834664e4d95773a3629b746f4db8Tom Gundersen return -errno;
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen }
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen chmod(sa.un.sun_path, 0666);
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen } else
daeb71a36a98834664e4d95773a3629b746f4db8Tom Gundersen fd_nonblock(s->native_fd, 1);
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen one = 1;
daeb71a36a98834664e4d95773a3629b746f4db8Tom Gundersen r = setsockopt(s->native_fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one));
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen if (r < 0) {
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen log_error("SO_PASSCRED failed: %m");
daeb71a36a98834664e4d95773a3629b746f4db8Tom Gundersen return -errno;
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen }
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen
daeb71a36a98834664e4d95773a3629b746f4db8Tom Gundersen#ifdef HAVE_SELINUX
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen one = 1;
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen r = setsockopt(s->syslog_fd, SOL_SOCKET, SO_PASSSEC, &one, sizeof(one));
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen if (r < 0)
daeb71a36a98834664e4d95773a3629b746f4db8Tom Gundersen log_warning("SO_PASSSEC failed: %m");
daeb71a36a98834664e4d95773a3629b746f4db8Tom Gundersen#endif
daeb71a36a98834664e4d95773a3629b746f4db8Tom Gundersen
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen one = 1;
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen r = setsockopt(s->native_fd, SOL_SOCKET, SO_TIMESTAMP, &one, sizeof(one));
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen if (r < 0) {
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen log_error("SO_TIMESTAMP failed: %m");
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen return -errno;
3e137a1b9a0eac2bf43d493d3302c3c959b6ccdbTom Gundersen }
daeb71a36a98834664e4d95773a3629b746f4db8Tom Gundersen
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen zero(ev);
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen ev.events = EPOLLIN;
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen ev.data.fd = s->native_fd;
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen if (epoll_ctl(s->epoll_fd, EPOLL_CTL_ADD, s->native_fd, &ev) < 0) {
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen log_error("Failed to add native server fd to epoll object: %m");
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen return -errno;
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen }
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen return 0;
5fde13d748749f0e06e2e6cdd15f0980a79ea82cTom Gundersen}
16b9b87aeee9353b5b8dae6089a69752422a5b09Tom Gundersen