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 <string.h> 24 #include <sys/prctl.h> 25 #include <sys/uio.h> 26 #include <syslog.h> 27 28 #include <log/logger.h> 29 #include <private/android_filesystem_config.h> 30 #include <private/android_logger.h> 31 32 #include "libaudit.h" 33 #include "LogAudit.h" 34 #include "LogBuffer.h" 35 #include "LogKlog.h" 36 #include "LogReader.h" 37 38 #define KMSG_PRIORITY(PRI) \ 39 '<', \ 40 '0' + LOG_MAKEPRI(LOG_AUTH, LOG_PRI(PRI)) / 10, \ 41 '0' + LOG_MAKEPRI(LOG_AUTH, LOG_PRI(PRI)) % 10, \ 42 '>' 43 44 LogAudit::LogAudit(LogBuffer *buf, LogReader *reader, int fdDmesg) : 45 SocketListener(getLogSocket(), false), 46 logbuf(buf), 47 reader(reader), 48 fdDmesg(fdDmesg), 49 initialized(false) { 50 static const char auditd_message[] = { KMSG_PRIORITY(LOG_INFO), 51 'l', 'o', 'g', 'd', '.', 'a', 'u', 'd', 'i', 't', 'd', ':', 52 ' ', 's', 't', 'a', 'r', 't', '\n' }; 53 write(fdDmesg, auditd_message, sizeof(auditd_message)); 54 } 55 56 bool LogAudit::onDataAvailable(SocketClient *cli) { 57 if (!initialized) { 58 prctl(PR_SET_NAME, "logd.auditd"); 59 initialized = true; 60 } 61 62 struct audit_message rep; 63 64 rep.nlh.nlmsg_type = 0; 65 rep.nlh.nlmsg_len = 0; 66 rep.data[0] = '\0'; 67 68 if (audit_get_reply(cli->getSocket(), &rep, GET_REPLY_BLOCKING, 0) < 0) { 69 SLOGE("Failed on audit_get_reply with error: %s", strerror(errno)); 70 return false; 71 } 72 73 logPrint("type=%d %.*s", 74 rep.nlh.nlmsg_type, rep.nlh.nlmsg_len, rep.data); 75 76 return true; 77 } 78 79 int LogAudit::logPrint(const char *fmt, ...) { 80 if (fmt == NULL) { 81 return -EINVAL; 82 } 83 84 va_list args; 85 86 char *str = NULL; 87 va_start(args, fmt); 88 int rc = vasprintf(&str, fmt, args); 89 va_end(args); 90 91 if (rc < 0) { 92 return rc; 93 } 94 95 char *cp; 96 while ((cp = strstr(str, " "))) { 97 memmove(cp, cp + 1, strlen(cp + 1) + 1); 98 } 99 100 bool info = strstr(str, " permissive=1") || strstr(str, " policy loaded "); 101 if ((fdDmesg >= 0) && initialized) { 102 struct iovec iov[3]; 103 static const char log_info[] = { KMSG_PRIORITY(LOG_INFO) }; 104 static const char log_warning[] = { KMSG_PRIORITY(LOG_WARNING) }; 105 106 iov[0].iov_base = info ? const_cast<char *>(log_info) 107 : const_cast<char *>(log_warning); 108 iov[0].iov_len = info ? sizeof(log_info) : sizeof(log_warning); 109 iov[1].iov_base = str; 110 iov[1].iov_len = strlen(str); 111 iov[2].iov_base = const_cast<char *>("\n"); 112 iov[2].iov_len = 1; 113 114 writev(fdDmesg, iov, sizeof(iov) / sizeof(iov[0])); 115 } 116 117 pid_t pid = getpid(); 118 pid_t tid = gettid(); 119 uid_t uid = AID_LOGD; 120 log_time now; 121 122 static const char audit_str[] = " audit("; 123 char *timeptr = strstr(str, audit_str); 124 if (timeptr 125 && ((cp = now.strptime(timeptr + sizeof(audit_str) - 1, "%s.%q"))) 126 && (*cp == ':')) { 127 memcpy(timeptr + sizeof(audit_str) - 1, "0.0", 3); 128 memmove(timeptr + sizeof(audit_str) - 1 + 3, cp, strlen(cp) + 1); 129 if (!isMonotonic()) { 130 if (android::isMonotonic(now)) { 131 LogKlog::convertMonotonicToReal(now); 132 } 133 } else { 134 if (!android::isMonotonic(now)) { 135 LogKlog::convertRealToMonotonic(now); 136 } 137 } 138 } else if (isMonotonic()) { 139 now = log_time(CLOCK_MONOTONIC); 140 } else { 141 now = log_time(CLOCK_REALTIME); 142 } 143 144 static const char pid_str[] = " pid="; 145 char *pidptr = strstr(str, pid_str); 146 if (pidptr && isdigit(pidptr[sizeof(pid_str) - 1])) { 147 cp = pidptr + sizeof(pid_str) - 1; 148 pid = 0; 149 while (isdigit(*cp)) { 150 pid = (pid * 10) + (*cp - '0'); 151 ++cp; 152 } 153 tid = pid; 154 logbuf->lock(); 155 uid = logbuf->pidToUid(pid); 156 logbuf->unlock(); 157 memmove(pidptr, cp, strlen(cp) + 1); 158 } 159 160 // log to events 161 162 size_t l = strnlen(str, LOGGER_ENTRY_MAX_PAYLOAD); 163 size_t n = l + sizeof(android_log_event_string_t); 164 165 bool notify = false; 166 167 { // begin scope for event buffer 168 uint32_t buffer[(n + sizeof(uint32_t) - 1) / sizeof(uint32_t)]; 169 170 android_log_event_string_t *event 171 = reinterpret_cast<android_log_event_string_t *>(buffer); 172 event->header.tag = htole32(AUDITD_LOG_TAG); 173 event->type = EVENT_TYPE_STRING; 174 event->length = htole32(l); 175 memcpy(event->data, str, l); 176 177 rc = logbuf->log(LOG_ID_EVENTS, now, uid, pid, tid, 178 reinterpret_cast<char *>(event), 179 (n <= USHRT_MAX) ? (unsigned short) n : USHRT_MAX); 180 if (rc >= 0) { 181 notify = true; 182 } 183 // end scope for event buffer 184 } 185 186 // log to main 187 188 static const char comm_str[] = " comm=\""; 189 const char *comm = strstr(str, comm_str); 190 const char *estr = str + strlen(str); 191 const char *commfree = NULL; 192 if (comm) { 193 estr = comm; 194 comm += sizeof(comm_str) - 1; 195 } else if (pid == getpid()) { 196 pid = tid; 197 comm = "auditd"; 198 } else { 199 logbuf->lock(); 200 comm = commfree = logbuf->pidToName(pid); 201 logbuf->unlock(); 202 if (!comm) { 203 comm = "unknown"; 204 } 205 } 206 207 const char *ecomm = strchr(comm, '"'); 208 if (ecomm) { 209 ++ecomm; 210 l = ecomm - comm; 211 } else { 212 l = strlen(comm) + 1; 213 ecomm = ""; 214 } 215 size_t b = estr - str; 216 if (b > LOGGER_ENTRY_MAX_PAYLOAD) { 217 b = LOGGER_ENTRY_MAX_PAYLOAD; 218 } 219 size_t e = strnlen(ecomm, LOGGER_ENTRY_MAX_PAYLOAD - b); 220 n = b + e + l + 2; 221 222 { // begin scope for main buffer 223 char newstr[n]; 224 225 *newstr = info ? ANDROID_LOG_INFO : ANDROID_LOG_WARN; 226 strlcpy(newstr + 1, comm, l); 227 strncpy(newstr + 1 + l, str, b); 228 strncpy(newstr + 1 + l + b, ecomm, e); 229 230 rc = logbuf->log(LOG_ID_MAIN, now, uid, pid, tid, newstr, 231 (n <= USHRT_MAX) ? (unsigned short) n : USHRT_MAX); 232 233 if (rc >= 0) { 234 notify = true; 235 } 236 // end scope for main buffer 237 } 238 239 free(const_cast<char *>(commfree)); 240 free(str); 241 242 if (notify) { 243 reader->notifyNewLog(); 244 if (rc < 0) { 245 rc = n; 246 } 247 } 248 249 return rc; 250 } 251 252 int LogAudit::log(char *buf, size_t len) { 253 char *audit = strstr(buf, " audit("); 254 if (!audit || (audit >= &buf[len])) { 255 return 0; 256 } 257 258 *audit = '\0'; 259 260 int rc; 261 char *type = strstr(buf, "type="); 262 if (type && (type < &buf[len])) { 263 rc = logPrint("%s %s", type, audit + 1); 264 } else { 265 rc = logPrint("%s", audit + 1); 266 } 267 *audit = ' '; 268 return rc; 269 } 270 271 int LogAudit::getLogSocket() { 272 int fd = audit_open(); 273 if (fd < 0) { 274 return fd; 275 } 276 if (audit_setup(fd, getpid()) < 0) { 277 audit_close(fd); 278 fd = -1; 279 } 280 return fd; 281 } 282