• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
LogAudit(LogBuffer * buf,LogReader * reader,int fdDmesg)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 
onDataAvailable(SocketClient * cli)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 
logPrint(const char * fmt,...)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 
log(char * buf,size_t len)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 
getLogSocket()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