log.cpp revision f86b5a6b90619e02d1d034ef7b0adc3b439f4abb
1da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes/*
2da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes * Copyright (C) 2015 The Android Open Source Project
3da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes *
4da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
5da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes * you may not use this file except in compliance with the License.
6da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes * You may obtain a copy of the License at
7da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes *
8da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
9da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes *
10da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes * Unless required by applicable law or agreed to in writing, software
11da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
12da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes * See the License for the specific language governing permissions and
14da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes * limitations under the License.
15da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes */
16da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes
17e5ce30fed81d1918a259be092dcd8bfffc3c2649Elliott Hughes#include "log.h"
18e5ce30fed81d1918a259be092dcd8bfffc3c2649Elliott Hughes
19da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes#include <stdlib.h>
20da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes#include <string.h>
21da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes#include <sys/uio.h>
22da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes
23da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes#include <selinux/selinux.h>
24da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes
25f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughesstatic const int kLogSeverityToKLogLevel[] = {
26f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes    KLOG_NOTICE_LEVEL, KLOG_DEBUG_LEVEL, KLOG_INFO_LEVEL,
27f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes    KLOG_WARNING_LEVEL, KLOG_ERROR_LEVEL, KLOG_ERROR_LEVEL,
28f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes};
29f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughesstatic_assert(arraysize(kLogSeverityToKLogLevel) == android::base::FATAL + 1,
30f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes              "Mismatch in size of kLogSeverityToKLogLevel and values in LogSeverity");
31da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes
32f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughesstatic void KernelLogger(android::base::LogId, android::base::LogSeverity severity,
33f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes                         const char* tag, const char*, unsigned int, const char* msg) {
34f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes    int level = kLogSeverityToKLogLevel[severity];
355db8d6aafa66cbeaef6bf736ff5ad5b711069d9eNick Kralevich    if (level > klog_get_level()) return;
365db8d6aafa66cbeaef6bf736ff5ad5b711069d9eNick Kralevich
37e5ce30fed81d1918a259be092dcd8bfffc3c2649Elliott Hughes    // The kernel's printk buffer is only 1024 bytes.
38e5ce30fed81d1918a259be092dcd8bfffc3c2649Elliott Hughes    // TODO: should we automatically break up long lines into multiple lines?
39e5ce30fed81d1918a259be092dcd8bfffc3c2649Elliott Hughes    // Or we could log but with something like "..." at the end?
40e5ce30fed81d1918a259be092dcd8bfffc3c2649Elliott Hughes    char buf[1024];
41f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes    size_t size = snprintf(buf, sizeof(buf), "<%d>%s: %s\n", level, tag, msg);
42f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes    if (size > sizeof(buf)) {
43f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes        size = snprintf(buf, sizeof(buf), "<%d>%s: %zu-byte message too long for printk\n",
44f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes                        level, tag, size);
45e5ce30fed81d1918a259be092dcd8bfffc3c2649Elliott Hughes    }
46da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes
47e5ce30fed81d1918a259be092dcd8bfffc3c2649Elliott Hughes    iovec iov[1];
48e5ce30fed81d1918a259be092dcd8bfffc3c2649Elliott Hughes    iov[0].iov_base = buf;
49f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes    iov[0].iov_len = size;
50e5ce30fed81d1918a259be092dcd8bfffc3c2649Elliott Hughes    klog_writev(level, iov, 1);
51da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes}
52da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes
53f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughesvoid InitKernelLogging(char* argv[]) {
54f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes    android::base::InitLogging(argv, &KernelLogger);
55f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes
56f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes    klog_init();
57f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes    klog_set_level(KLOG_NOTICE_LEVEL);
58da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes}
59da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes
60da40c00137f75543a69972f1be506e2d14a41845Elliott Hughesint selinux_klog_callback(int type, const char *fmt, ...) {
61f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes    android::base::LogSeverity severity = android::base::ERROR;
62da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes    if (type == SELINUX_WARNING) {
63f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes        severity = android::base::WARNING;
64da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes    } else if (type == SELINUX_INFO) {
65f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes        severity = android::base::INFO;
66da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes    }
67f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes    char buf[1024];
68da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes    va_list ap;
69da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes    va_start(ap, fmt);
70f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes    vsnprintf(buf, sizeof(buf), fmt, ap);
71da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes    va_end(ap);
72f86b5a6b90619e02d1d034ef7b0adc3b439f4abbElliott Hughes    KernelLogger(android::base::MAIN, severity, "selinux", nullptr, 0, buf);
73da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes    return 0;
74da40c00137f75543a69972f1be506e2d14a41845Elliott Hughes}
75