blob: 3811daaa05b5b103c028247ddea3e8f03154c0ac [file] [log] [blame]
William Roberts29d238d2013-02-08 09:45:26 +09001/*
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>
Mark Salyzyn29eb5702015-03-03 16:21:27 -080018#include <endian.h>
William Roberts29d238d2013-02-08 09:45:26 +090019#include <errno.h>
Mark Salyzyne0fa2912014-04-28 16:39:04 -070020#include <limits.h>
William Roberts29d238d2013-02-08 09:45:26 +090021#include <stdarg.h>
22#include <stdlib.h>
Mark Salyzyn317bfb92016-02-23 08:55:43 -080023#include <string.h>
Mark Salyzyn8daa9af2014-04-28 14:07:23 -070024#include <sys/prctl.h>
Mark Salyzyne9bebd02014-04-03 09:55:26 -070025#include <sys/uio.h>
Mark Salyzyn7ee2aef2014-09-28 14:41:50 -070026#include <syslog.h>
William Roberts29d238d2013-02-08 09:45:26 +090027
Mark Salyzyne3aeeee2015-03-17 07:56:32 -070028#include <private/android_filesystem_config.h>
Mark Salyzyn29eb5702015-03-03 16:21:27 -080029#include <private/android_logger.h>
30
William Roberts29d238d2013-02-08 09:45:26 +090031#include "libaudit.h"
32#include "LogAudit.h"
Mark Salyzyn317bfb92016-02-23 08:55:43 -080033#include "LogBuffer.h"
Mark Salyzynae4d9282014-10-15 08:49:39 -070034#include "LogKlog.h"
Mark Salyzyn317bfb92016-02-23 08:55:43 -080035#include "LogReader.h"
William Roberts29d238d2013-02-08 09:45:26 +090036
Mark Salyzynccbadc62015-03-12 12:25:35 -070037#define KMSG_PRIORITY(PRI) \
38 '<', \
39 '0' + LOG_MAKEPRI(LOG_AUTH, LOG_PRI(PRI)) / 10, \
40 '0' + LOG_MAKEPRI(LOG_AUTH, LOG_PRI(PRI)) % 10, \
Mark Salyzyn7ee2aef2014-09-28 14:41:50 -070041 '>'
42
Mark Salyzyn77187782015-05-12 15:21:31 -070043LogAudit::LogAudit(LogBuffer *buf, LogReader *reader, int fdDmesg) :
44 SocketListener(getLogSocket(), false),
45 logbuf(buf),
46 reader(reader),
47 fdDmesg(fdDmesg),
48 initialized(false) {
Sami Tolvanena742d102016-06-14 18:04:43 +000049 static const char auditd_message[] = { KMSG_PRIORITY(LOG_INFO),
50 'l', 'o', 'g', 'd', '.', 'a', 'u', 'd', 'i', 't', 'd', ':',
51 ' ', 's', 't', 'a', 'r', 't', '\n' };
52 write(fdDmesg, auditd_message, sizeof(auditd_message));
William Roberts29d238d2013-02-08 09:45:26 +090053}
54
55bool LogAudit::onDataAvailable(SocketClient *cli) {
Mark Salyzyneb06de72014-10-13 09:59:37 -070056 if (!initialized) {
57 prctl(PR_SET_NAME, "logd.auditd");
58 initialized = true;
59 }
Mark Salyzyn8daa9af2014-04-28 14:07:23 -070060
William Roberts29d238d2013-02-08 09:45:26 +090061 struct audit_message rep;
62
Mark Salyzyne0fa2912014-04-28 16:39:04 -070063 rep.nlh.nlmsg_type = 0;
64 rep.nlh.nlmsg_len = 0;
65 rep.data[0] = '\0';
66
William Roberts29d238d2013-02-08 09:45:26 +090067 if (audit_get_reply(cli->getSocket(), &rep, GET_REPLY_BLOCKING, 0) < 0) {
68 SLOGE("Failed on audit_get_reply with error: %s", strerror(errno));
69 return false;
70 }
71
Mark Salyzyneb06de72014-10-13 09:59:37 -070072 logPrint("type=%d %.*s",
73 rep.nlh.nlmsg_type, rep.nlh.nlmsg_len, rep.data);
William Roberts29d238d2013-02-08 09:45:26 +090074
75 return true;
76}
77
William Roberts29d238d2013-02-08 09:45:26 +090078int LogAudit::logPrint(const char *fmt, ...) {
79 if (fmt == NULL) {
80 return -EINVAL;
81 }
82
83 va_list args;
84
85 char *str = NULL;
86 va_start(args, fmt);
87 int rc = vasprintf(&str, fmt, args);
88 va_end(args);
89
90 if (rc < 0) {
91 return rc;
92 }
93
Mark Salyzyne4369d62014-05-27 10:06:34 -070094 char *cp;
95 while ((cp = strstr(str, " "))) {
96 memmove(cp, cp + 1, strlen(cp + 1) + 1);
97 }
98
Sami Tolvanena742d102016-06-14 18:04:43 +000099 bool info = strstr(str, " permissive=1") || strstr(str, " policy loaded ");
Mark Salyzyneb06de72014-10-13 09:59:37 -0700100 if ((fdDmesg >= 0) && initialized) {
Mark Salyzyn6bdeee02014-09-19 11:59:42 -0700101 struct iovec iov[3];
Mark Salyzyn7ee2aef2014-09-28 14:41:50 -0700102 static const char log_info[] = { KMSG_PRIORITY(LOG_INFO) };
103 static const char log_warning[] = { KMSG_PRIORITY(LOG_WARNING) };
Mark Salyzyn4d205f82016-07-15 15:45:58 -0700104 static const char newline[] = "\n";
Mark Salyzyne9bebd02014-04-03 09:55:26 -0700105
Mark Salyzyn4d205f82016-07-15 15:45:58 -0700106 // Dedupe messages, checking for identical messages starting with avc:
107 static unsigned count;
108 static char *last_str;
109 static bool last_info;
Mark Salyzyne9bebd02014-04-03 09:55:26 -0700110
Mark Salyzyn4d205f82016-07-15 15:45:58 -0700111 if (last_str != NULL) {
112 static const char avc[] = "): avc: ";
113 char *avcl = strstr(last_str, avc);
114 bool skip = false;
115
116 if (avcl) {
117 char *avcr = strstr(str, avc);
118
119 skip = avcr && !strcmp(avcl + strlen(avc), avcr + strlen(avc));
120 if (skip) {
121 ++count;
122 free(last_str);
123 last_str = strdup(str);
124 last_info = info;
125 }
126 }
127 if (!skip) {
128 static const char resume[] = " duplicate messages suppressed\n";
129
130 iov[0].iov_base = last_info ?
131 const_cast<char *>(log_info) :
132 const_cast<char *>(log_warning);
133 iov[0].iov_len = last_info ?
134 sizeof(log_info) :
135 sizeof(log_warning);
136 iov[1].iov_base = last_str;
137 iov[1].iov_len = strlen(last_str);
138 if (count > 1) {
139 iov[2].iov_base = const_cast<char *>(resume);
140 iov[2].iov_len = strlen(resume);
141 } else {
142 iov[2].iov_base = const_cast<char *>(newline);
143 iov[2].iov_len = strlen(newline);
144 }
145
146 writev(fdDmesg, iov, sizeof(iov) / sizeof(iov[0]));
147 free(last_str);
148 last_str = NULL;
149 }
150 }
151 if (last_str == NULL) {
152 count = 0;
153 last_str = strdup(str);
154 last_info = info;
155 }
156 if (count == 0) {
157 iov[0].iov_base = info ?
158 const_cast<char *>(log_info) :
159 const_cast<char *>(log_warning);
160 iov[0].iov_len = info ?
161 sizeof(log_info) :
162 sizeof(log_warning);
163 iov[1].iov_base = str;
164 iov[1].iov_len = strlen(str);
165 iov[2].iov_base = const_cast<char *>(newline);
166 iov[2].iov_len = strlen(newline);
167
168 writev(fdDmesg, iov, sizeof(iov) / sizeof(iov[0]));
169 }
Mark Salyzyne9bebd02014-04-03 09:55:26 -0700170 }
171
William Roberts29d238d2013-02-08 09:45:26 +0900172 pid_t pid = getpid();
173 pid_t tid = gettid();
Mark Salyzyne3aeeee2015-03-17 07:56:32 -0700174 uid_t uid = AID_LOGD;
William Roberts29d238d2013-02-08 09:45:26 +0900175 log_time now;
176
177 static const char audit_str[] = " audit(";
178 char *timeptr = strstr(str, audit_str);
William Roberts29d238d2013-02-08 09:45:26 +0900179 if (timeptr
180 && ((cp = now.strptime(timeptr + sizeof(audit_str) - 1, "%s.%q")))
181 && (*cp == ':')) {
182 memcpy(timeptr + sizeof(audit_str) - 1, "0.0", 3);
Mark Salyzyne4369d62014-05-27 10:06:34 -0700183 memmove(timeptr + sizeof(audit_str) - 1 + 3, cp, strlen(cp) + 1);
Mark Salyzynb6bee332015-09-08 08:56:32 -0700184 if (!isMonotonic()) {
185 if (android::isMonotonic(now)) {
186 LogKlog::convertMonotonicToReal(now);
187 }
188 } else {
189 if (!android::isMonotonic(now)) {
190 LogKlog::convertRealToMonotonic(now);
191 }
Mark Salyzynae4d9282014-10-15 08:49:39 -0700192 }
Mark Salyzynb6bee332015-09-08 08:56:32 -0700193 } else if (isMonotonic()) {
194 now = log_time(CLOCK_MONOTONIC);
William Roberts29d238d2013-02-08 09:45:26 +0900195 } else {
Mark Salyzynb6bee332015-09-08 08:56:32 -0700196 now = log_time(CLOCK_REALTIME);
William Roberts29d238d2013-02-08 09:45:26 +0900197 }
198
199 static const char pid_str[] = " pid=";
200 char *pidptr = strstr(str, pid_str);
201 if (pidptr && isdigit(pidptr[sizeof(pid_str) - 1])) {
202 cp = pidptr + sizeof(pid_str) - 1;
203 pid = 0;
204 while (isdigit(*cp)) {
205 pid = (pid * 10) + (*cp - '0');
206 ++cp;
207 }
208 tid = pid;
Mark Salyzyned777e92015-06-24 16:22:54 -0700209 logbuf->lock();
William Roberts29d238d2013-02-08 09:45:26 +0900210 uid = logbuf->pidToUid(pid);
Mark Salyzyned777e92015-06-24 16:22:54 -0700211 logbuf->unlock();
Mark Salyzyne4369d62014-05-27 10:06:34 -0700212 memmove(pidptr, cp, strlen(cp) + 1);
William Roberts29d238d2013-02-08 09:45:26 +0900213 }
214
Mark Salyzyne4369d62014-05-27 10:06:34 -0700215 // log to events
216
Mark Salyzynddda2122015-10-02 09:22:52 -0700217 size_t l = strnlen(str, LOGGER_ENTRY_MAX_PAYLOAD);
Mark Salyzyn29eb5702015-03-03 16:21:27 -0800218 size_t n = l + sizeof(android_log_event_string_t);
Mark Salyzyne4369d62014-05-27 10:06:34 -0700219
220 bool notify = false;
William Roberts29d238d2013-02-08 09:45:26 +0900221
Mark Salyzynddda2122015-10-02 09:22:52 -0700222 { // begin scope for event buffer
223 uint32_t buffer[(n + sizeof(uint32_t) - 1) / sizeof(uint32_t)];
224
225 android_log_event_string_t *event
226 = reinterpret_cast<android_log_event_string_t *>(buffer);
Mark Salyzyn29eb5702015-03-03 16:21:27 -0800227 event->header.tag = htole32(AUDITD_LOG_TAG);
Nick Kralevich58ba58a2015-04-07 01:25:43 -0700228 event->type = EVENT_TYPE_STRING;
229 event->length = htole32(l);
230 memcpy(event->data, str, l);
Mark Salyzyne4369d62014-05-27 10:06:34 -0700231
Mark Salyzyn202e1532015-02-09 08:21:05 -0800232 rc = logbuf->log(LOG_ID_EVENTS, now, uid, pid, tid,
233 reinterpret_cast<char *>(event),
234 (n <= USHRT_MAX) ? (unsigned short) n : USHRT_MAX);
Mark Salyzyn202e1532015-02-09 08:21:05 -0800235 if (rc >= 0) {
236 notify = true;
237 }
Mark Salyzynddda2122015-10-02 09:22:52 -0700238 // end scope for event buffer
William Roberts29d238d2013-02-08 09:45:26 +0900239 }
240
Mark Salyzyne4369d62014-05-27 10:06:34 -0700241 // log to main
242
243 static const char comm_str[] = " comm=\"";
244 const char *comm = strstr(str, comm_str);
245 const char *estr = str + strlen(str);
Mark Salyzyn758058f2015-08-21 16:44:30 -0700246 const char *commfree = NULL;
Mark Salyzyne4369d62014-05-27 10:06:34 -0700247 if (comm) {
248 estr = comm;
249 comm += sizeof(comm_str) - 1;
250 } else if (pid == getpid()) {
251 pid = tid;
252 comm = "auditd";
Mark Salyzyned777e92015-06-24 16:22:54 -0700253 } else {
254 logbuf->lock();
255 comm = commfree = logbuf->pidToName(pid);
256 logbuf->unlock();
257 if (!comm) {
258 comm = "unknown";
259 }
Mark Salyzyne4369d62014-05-27 10:06:34 -0700260 }
261
262 const char *ecomm = strchr(comm, '"');
263 if (ecomm) {
264 ++ecomm;
265 l = ecomm - comm;
266 } else {
267 l = strlen(comm) + 1;
268 ecomm = "";
269 }
Mark Salyzynddda2122015-10-02 09:22:52 -0700270 size_t b = estr - str;
271 if (b > LOGGER_ENTRY_MAX_PAYLOAD) {
272 b = LOGGER_ENTRY_MAX_PAYLOAD;
273 }
274 size_t e = strnlen(ecomm, LOGGER_ENTRY_MAX_PAYLOAD - b);
275 n = b + e + l + 2;
Mark Salyzyne4369d62014-05-27 10:06:34 -0700276
Mark Salyzynddda2122015-10-02 09:22:52 -0700277 { // begin scope for main buffer
278 char newstr[n];
279
Mark Salyzyn6bdeee02014-09-19 11:59:42 -0700280 *newstr = info ? ANDROID_LOG_INFO : ANDROID_LOG_WARN;
Mark Salyzyne4369d62014-05-27 10:06:34 -0700281 strlcpy(newstr + 1, comm, l);
Mark Salyzynddda2122015-10-02 09:22:52 -0700282 strncpy(newstr + 1 + l, str, b);
283 strncpy(newstr + 1 + l + b, ecomm, e);
Mark Salyzyne4369d62014-05-27 10:06:34 -0700284
Mark Salyzyn202e1532015-02-09 08:21:05 -0800285 rc = logbuf->log(LOG_ID_MAIN, now, uid, pid, tid, newstr,
286 (n <= USHRT_MAX) ? (unsigned short) n : USHRT_MAX);
Mark Salyzyne4369d62014-05-27 10:06:34 -0700287
Mark Salyzyn202e1532015-02-09 08:21:05 -0800288 if (rc >= 0) {
289 notify = true;
290 }
Mark Salyzynddda2122015-10-02 09:22:52 -0700291 // end scope for main buffer
Mark Salyzyne4369d62014-05-27 10:06:34 -0700292 }
293
Mark Salyzyn758058f2015-08-21 16:44:30 -0700294 free(const_cast<char *>(commfree));
William Roberts29d238d2013-02-08 09:45:26 +0900295 free(str);
296
Mark Salyzyne4369d62014-05-27 10:06:34 -0700297 if (notify) {
298 reader->notifyNewLog();
Mark Salyzyn202e1532015-02-09 08:21:05 -0800299 if (rc < 0) {
300 rc = n;
301 }
Mark Salyzyne4369d62014-05-27 10:06:34 -0700302 }
William Roberts29d238d2013-02-08 09:45:26 +0900303
304 return rc;
305}
306
Mark Salyzyn151beac2015-09-04 11:37:42 -0700307int LogAudit::log(char *buf, size_t len) {
Mark Salyzyneb06de72014-10-13 09:59:37 -0700308 char *audit = strstr(buf, " audit(");
Mark Salyzyn151beac2015-09-04 11:37:42 -0700309 if (!audit || (audit >= &buf[len])) {
Mark Salyzynae4d9282014-10-15 08:49:39 -0700310 return 0;
William Roberts29d238d2013-02-08 09:45:26 +0900311 }
312
Mark Salyzyneb06de72014-10-13 09:59:37 -0700313 *audit = '\0';
William Roberts29d238d2013-02-08 09:45:26 +0900314
Mark Salyzyneb06de72014-10-13 09:59:37 -0700315 int rc;
316 char *type = strstr(buf, "type=");
Mark Salyzyn151beac2015-09-04 11:37:42 -0700317 if (type && (type < &buf[len])) {
Mark Salyzyneb06de72014-10-13 09:59:37 -0700318 rc = logPrint("%s %s", type, audit + 1);
319 } else {
320 rc = logPrint("%s", audit + 1);
William Roberts29d238d2013-02-08 09:45:26 +0900321 }
Mark Salyzyneb06de72014-10-13 09:59:37 -0700322 *audit = ' ';
323 return rc;
William Roberts29d238d2013-02-08 09:45:26 +0900324}
325
326int LogAudit::getLogSocket() {
327 int fd = audit_open();
328 if (fd < 0) {
329 return fd;
330 }
Nick Kralevichc234a1b2014-11-19 13:33:22 -0800331 if (audit_setup(fd, getpid()) < 0) {
William Roberts29d238d2013-02-08 09:45:26 +0900332 audit_close(fd);
333 fd = -1;
334 }
335 return fd;
336}