1/* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <ctype.h> 18#include <endian.h> 19#include <errno.h> 20#include <limits.h> 21#include <stdarg.h> 22#include <stdlib.h> 23#include <sys/prctl.h> 24#include <sys/uio.h> 25#include <syslog.h> 26 27#include <private/android_filesystem_config.h> 28#include <private/android_logger.h> 29 30#include "libaudit.h" 31#include "LogAudit.h" 32#include "LogKlog.h" 33 34#define KMSG_PRIORITY(PRI) \ 35 '<', \ 36 '0' + LOG_MAKEPRI(LOG_AUTH, LOG_PRI(PRI)) / 10, \ 37 '0' + LOG_MAKEPRI(LOG_AUTH, LOG_PRI(PRI)) % 10, \ 38 '>' 39 40LogAudit::LogAudit(LogBuffer *buf, LogReader *reader, int fdDmesg) : 41 SocketListener(getLogSocket(), false), 42 logbuf(buf), 43 reader(reader), 44 fdDmesg(fdDmesg), 45 initialized(false) { 46 static const char auditd_message[] = { KMSG_PRIORITY(LOG_INFO), 47 'l', 'o', 'g', 'd', '.', 'a', 'u', 'd', 'i', 't', 'd', ':', 48 ' ', 's', 't', 'a', 'r', 't', '\n' }; 49 write(fdDmesg, auditd_message, sizeof(auditd_message)); 50} 51 52bool LogAudit::onDataAvailable(SocketClient *cli) { 53 if (!initialized) { 54 prctl(PR_SET_NAME, "logd.auditd"); 55 initialized = true; 56 } 57 58 struct audit_message rep; 59 60 rep.nlh.nlmsg_type = 0; 61 rep.nlh.nlmsg_len = 0; 62 rep.data[0] = '\0'; 63 64 if (audit_get_reply(cli->getSocket(), &rep, GET_REPLY_BLOCKING, 0) < 0) { 65 SLOGE("Failed on audit_get_reply with error: %s", strerror(errno)); 66 return false; 67 } 68 69 logPrint("type=%d %.*s", 70 rep.nlh.nlmsg_type, rep.nlh.nlmsg_len, rep.data); 71 72 return true; 73} 74 75int LogAudit::logPrint(const char *fmt, ...) { 76 if (fmt == NULL) { 77 return -EINVAL; 78 } 79 80 va_list args; 81 82 char *str = NULL; 83 va_start(args, fmt); 84 int rc = vasprintf(&str, fmt, args); 85 va_end(args); 86 87 if (rc < 0) { 88 return rc; 89 } 90 91 char *cp; 92 while ((cp = strstr(str, " "))) { 93 memmove(cp, cp + 1, strlen(cp + 1) + 1); 94 } 95 96 bool info = strstr(str, " permissive=1") || strstr(str, " policy loaded "); 97 if ((fdDmesg >= 0) && initialized) { 98 struct iovec iov[3]; 99 static const char log_info[] = { KMSG_PRIORITY(LOG_INFO) }; 100 static const char log_warning[] = { KMSG_PRIORITY(LOG_WARNING) }; 101 102 iov[0].iov_base = info ? const_cast<char *>(log_info) 103 : const_cast<char *>(log_warning); 104 iov[0].iov_len = info ? sizeof(log_info) : sizeof(log_warning); 105 iov[1].iov_base = str; 106 iov[1].iov_len = strlen(str); 107 iov[2].iov_base = const_cast<char *>("\n"); 108 iov[2].iov_len = 1; 109 110 writev(fdDmesg, iov, sizeof(iov) / sizeof(iov[0])); 111 } 112 113 pid_t pid = getpid(); 114 pid_t tid = gettid(); 115 uid_t uid = AID_LOGD; 116 log_time now; 117 118 static const char audit_str[] = " audit("; 119 char *timeptr = strstr(str, audit_str); 120 if (timeptr 121 && ((cp = now.strptime(timeptr + sizeof(audit_str) - 1, "%s.%q"))) 122 && (*cp == ':')) { 123 memcpy(timeptr + sizeof(audit_str) - 1, "0.0", 3); 124 memmove(timeptr + sizeof(audit_str) - 1 + 3, cp, strlen(cp) + 1); 125 // 126 // We are either in 1970ish (MONOTONIC) or 2015+ish (REALTIME) so to 127 // differentiate without prejudice, we use 1980 to delineate, earlier 128 // is monotonic, later is real. 129 // 130# define EPOCH_PLUS_10_YEARS (10 * 1461 / 4 * 24 * 60 * 60) 131 if (now.tv_sec < EPOCH_PLUS_10_YEARS) { 132 LogKlog::convertMonotonicToReal(now); 133 } 134 } else { 135 now.strptime("", ""); // side effect of setting CLOCK_REALTIME 136 } 137 138 static const char pid_str[] = " pid="; 139 char *pidptr = strstr(str, pid_str); 140 if (pidptr && isdigit(pidptr[sizeof(pid_str) - 1])) { 141 cp = pidptr + sizeof(pid_str) - 1; 142 pid = 0; 143 while (isdigit(*cp)) { 144 pid = (pid * 10) + (*cp - '0'); 145 ++cp; 146 } 147 tid = pid; 148 logbuf->lock(); 149 uid = logbuf->pidToUid(pid); 150 logbuf->unlock(); 151 memmove(pidptr, cp, strlen(cp) + 1); 152 } 153 154 // log to events 155 156 size_t l = strlen(str); 157 size_t n = l + sizeof(android_log_event_string_t); 158 159 bool notify = false; 160 161 android_log_event_string_t *event = static_cast<android_log_event_string_t *>(malloc(n)); 162 if (!event) { 163 rc = -ENOMEM; 164 } else { 165 event->header.tag = htole32(AUDITD_LOG_TAG); 166 event->type = EVENT_TYPE_STRING; 167 event->length = htole32(l); 168 memcpy(event->data, str, l); 169 170 rc = logbuf->log(LOG_ID_EVENTS, now, uid, pid, tid, 171 reinterpret_cast<char *>(event), 172 (n <= USHRT_MAX) ? (unsigned short) n : USHRT_MAX); 173 free(event); 174 175 if (rc >= 0) { 176 notify = true; 177 } 178 } 179 180 // log to main 181 182 static const char comm_str[] = " comm=\""; 183 const char *comm = strstr(str, comm_str); 184 const char *estr = str + strlen(str); 185 char *commfree = NULL; 186 if (comm) { 187 estr = comm; 188 comm += sizeof(comm_str) - 1; 189 } else if (pid == getpid()) { 190 pid = tid; 191 comm = "auditd"; 192 } else { 193 logbuf->lock(); 194 comm = commfree = logbuf->pidToName(pid); 195 logbuf->unlock(); 196 if (!comm) { 197 comm = "unknown"; 198 } 199 } 200 201 const char *ecomm = strchr(comm, '"'); 202 if (ecomm) { 203 ++ecomm; 204 l = ecomm - comm; 205 } else { 206 l = strlen(comm) + 1; 207 ecomm = ""; 208 } 209 n = (estr - str) + strlen(ecomm) + l + 2; 210 211 char *newstr = static_cast<char *>(malloc(n)); 212 if (!newstr) { 213 rc = -ENOMEM; 214 } else { 215 *newstr = info ? ANDROID_LOG_INFO : ANDROID_LOG_WARN; 216 strlcpy(newstr + 1, comm, l); 217 strncpy(newstr + 1 + l, str, estr - str); 218 strcpy(newstr + 1 + l + (estr - str), ecomm); 219 220 rc = logbuf->log(LOG_ID_MAIN, now, uid, pid, tid, newstr, 221 (n <= USHRT_MAX) ? (unsigned short) n : USHRT_MAX); 222 free(newstr); 223 224 if (rc >= 0) { 225 notify = true; 226 } 227 } 228 229 free(commfree); 230 free(str); 231 232 if (notify) { 233 reader->notifyNewLog(); 234 if (rc < 0) { 235 rc = n; 236 } 237 } 238 239 return rc; 240} 241 242int LogAudit::log(char *buf) { 243 char *audit = strstr(buf, " audit("); 244 if (!audit) { 245 return 0; 246 } 247 248 *audit = '\0'; 249 250 int rc; 251 char *type = strstr(buf, "type="); 252 if (type) { 253 rc = logPrint("%s %s", type, audit + 1); 254 } else { 255 rc = logPrint("%s", audit + 1); 256 } 257 *audit = ' '; 258 return rc; 259} 260 261int LogAudit::getLogSocket() { 262 int fd = audit_open(); 263 if (fd < 0) { 264 return fd; 265 } 266 if (audit_setup(fd, getpid()) < 0) { 267 audit_close(fd); 268 fd = -1; 269 } 270 return fd; 271} 272