• 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 <stdint.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <sys/prctl.h>
26 #include <sys/uio.h>
27 #include <syslog.h>
28 
29 #include <fstream>
30 #include <sstream>
31 
32 #include <android-base/macros.h>
33 #include <log/log_properties.h>
34 #include <private/android_filesystem_config.h>
35 #include <private/android_logger.h>
36 
37 #include "LogAudit.h"
38 #include "LogBuffer.h"
39 #include "LogKlog.h"
40 #include "LogReader.h"
41 #include "LogUtils.h"
42 #include "libaudit.h"
43 
44 #define KMSG_PRIORITY(PRI)                               \
45     '<', '0' + LOG_MAKEPRI(LOG_AUTH, LOG_PRI(PRI)) / 10, \
46         '0' + LOG_MAKEPRI(LOG_AUTH, LOG_PRI(PRI)) % 10, '>'
47 
LogAudit(LogBuffer * buf,LogReader * reader,int fdDmesg)48 LogAudit::LogAudit(LogBuffer* buf, LogReader* reader, int fdDmesg)
49     : SocketListener(getLogSocket(), false),
50       logbuf(buf),
51       reader(reader),
52       fdDmesg(fdDmesg),
53       main(__android_logger_property_get_bool("ro.logd.auditd.main",
54                                               BOOL_DEFAULT_TRUE)),
55       events(__android_logger_property_get_bool("ro.logd.auditd.events",
56                                                 BOOL_DEFAULT_TRUE)),
57       initialized(false) {
58     static const char auditd_message[] = { KMSG_PRIORITY(LOG_INFO),
59                                            'l',
60                                            'o',
61                                            'g',
62                                            'd',
63                                            '.',
64                                            'a',
65                                            'u',
66                                            'd',
67                                            'i',
68                                            't',
69                                            'd',
70                                            ':',
71                                            ' ',
72                                            's',
73                                            't',
74                                            'a',
75                                            'r',
76                                            't',
77                                            '\n' };
78     write(fdDmesg, auditd_message, sizeof(auditd_message));
79 }
80 
onDataAvailable(SocketClient * cli)81 bool LogAudit::onDataAvailable(SocketClient* cli) {
82     if (!initialized) {
83         prctl(PR_SET_NAME, "logd.auditd");
84         initialized = true;
85     }
86 
87     struct audit_message rep;
88 
89     rep.nlh.nlmsg_type = 0;
90     rep.nlh.nlmsg_len = 0;
91     rep.data[0] = '\0';
92 
93     if (audit_get_reply(cli->getSocket(), &rep, GET_REPLY_BLOCKING, 0) < 0) {
94         SLOGE("Failed on audit_get_reply with error: %s", strerror(errno));
95         return false;
96     }
97 
98     logPrint("type=%d %.*s", rep.nlh.nlmsg_type, rep.nlh.nlmsg_len, rep.data);
99 
100     return true;
101 }
102 
hasMetadata(char * str,int str_len)103 static inline bool hasMetadata(char* str, int str_len) {
104     // need to check and see if str already contains bug metadata from
105     // possibility of stuttering if log audit crashes and then reloads kernel
106     // messages. Kernel denials that contain metadata will either end in
107     // "b/[0-9]+$" or "b/[0-9]+  duplicate messages suppressed$" which will put
108     // a '/' character at either 9 or 39 indices away from the end of the str.
109     return str_len >= 39 &&
110            (str[str_len - 9] == '/' || str[str_len - 39] == '/');
111 }
112 
populateDenialMap()113 std::map<std::string, std::string> LogAudit::populateDenialMap() {
114     std::ifstream bug_file("/vendor/etc/selinux/selinux_denial_metadata");
115     std::string line;
116     // allocate a map for the static map pointer in auditParse to keep track of,
117     // this function only runs once
118     std::map<std::string, std::string> denial_to_bug;
119     if (bug_file.good()) {
120         std::string scontext;
121         std::string tcontext;
122         std::string tclass;
123         std::string bug_num;
124         while (std::getline(bug_file, line)) {
125             std::stringstream split_line(line);
126             split_line >> scontext >> tcontext >> tclass >> bug_num;
127             denial_to_bug.emplace(scontext + tcontext + tclass, bug_num);
128         }
129     }
130     return denial_to_bug;
131 }
132 
denialParse(const std::string & denial,char terminator,const std::string & search_term)133 std::string LogAudit::denialParse(const std::string& denial, char terminator,
134                                   const std::string& search_term) {
135     size_t start_index = denial.find(search_term);
136     if (start_index != std::string::npos) {
137         start_index += search_term.length();
138         return denial.substr(
139             start_index, denial.find(terminator, start_index) - start_index);
140     }
141     return "";
142 }
143 
auditParse(const std::string & string,uid_t uid,std::string * bug_num)144 void LogAudit::auditParse(const std::string& string, uid_t uid,
145                           std::string* bug_num) {
146     if (!__android_log_is_debuggable()) {
147         bug_num->assign("");
148         return;
149     }
150     static std::map<std::string, std::string> denial_to_bug =
151         populateDenialMap();
152     std::string scontext = denialParse(string, ':', "scontext=u:object_r:");
153     std::string tcontext = denialParse(string, ':', "tcontext=u:object_r:");
154     std::string tclass = denialParse(string, ' ', "tclass=");
155     if (scontext.empty()) {
156         scontext = denialParse(string, ':', "scontext=u:r:");
157     }
158     if (tcontext.empty()) {
159         tcontext = denialParse(string, ':', "tcontext=u:r:");
160     }
161     auto search = denial_to_bug.find(scontext + tcontext + tclass);
162     if (search != denial_to_bug.end()) {
163         bug_num->assign(" b/" + search->second);
164     } else {
165         bug_num->assign("");
166     }
167 
168     // Ensure the uid name is not null before passing it to the bug string.
169     if (uid >= AID_APP_START && uid <= AID_APP_END) {
170         char* uidname = android::uidToName(uid);
171         if (uidname) {
172             bug_num->append(" app=");
173             bug_num->append(uidname);
174             free(uidname);
175         }
176     }
177 }
178 
logPrint(const char * fmt,...)179 int LogAudit::logPrint(const char* fmt, ...) {
180     if (fmt == nullptr) {
181         return -EINVAL;
182     }
183 
184     va_list args;
185 
186     char* str = nullptr;
187     va_start(args, fmt);
188     int rc = vasprintf(&str, fmt, args);
189     va_end(args);
190 
191     if (rc < 0) {
192         return rc;
193     }
194     char* cp;
195     // Work around kernels missing
196     // https://github.com/torvalds/linux/commit/b8f89caafeb55fba75b74bea25adc4e4cd91be67
197     // Such kernels improperly add newlines inside audit messages.
198     while ((cp = strchr(str, '\n'))) {
199         *cp = ' ';
200     }
201 
202     while ((cp = strstr(str, "  "))) {
203         memmove(cp, cp + 1, strlen(cp + 1) + 1);
204     }
205     pid_t pid = getpid();
206     pid_t tid = gettid();
207     uid_t uid = AID_LOGD;
208     static const char pid_str[] = " pid=";
209     char* pidptr = strstr(str, pid_str);
210     if (pidptr && isdigit(pidptr[sizeof(pid_str) - 1])) {
211         cp = pidptr + sizeof(pid_str) - 1;
212         pid = 0;
213         while (isdigit(*cp)) {
214             pid = (pid * 10) + (*cp - '0');
215             ++cp;
216         }
217         tid = pid;
218         logbuf->wrlock();
219         uid = logbuf->pidToUid(pid);
220         logbuf->unlock();
221         memmove(pidptr, cp, strlen(cp) + 1);
222     }
223 
224     bool info = strstr(str, " permissive=1") || strstr(str, " policy loaded ");
225     static std::string denial_metadata;
226     if ((fdDmesg >= 0) && initialized) {
227         struct iovec iov[4];
228         static const char log_info[] = { KMSG_PRIORITY(LOG_INFO) };
229         static const char log_warning[] = { KMSG_PRIORITY(LOG_WARNING) };
230         static const char newline[] = "\n";
231 
232         // Dedupe messages, checking for identical messages starting with avc:
233         static unsigned count;
234         static char* last_str;
235         static bool last_info;
236 
237         if (last_str != nullptr) {
238             static const char avc[] = "): avc: ";
239             char* avcl = strstr(last_str, avc);
240             bool skip = false;
241 
242             if (avcl) {
243                 char* avcr = strstr(str, avc);
244 
245                 skip = avcr &&
246                        !fastcmp<strcmp>(avcl + strlen(avc), avcr + strlen(avc));
247                 if (skip) {
248                     ++count;
249                     free(last_str);
250                     last_str = strdup(str);
251                     last_info = info;
252                 }
253             }
254             if (!skip) {
255                 static const char resume[] = " duplicate messages suppressed\n";
256                 iov[0].iov_base = last_info ? const_cast<char*>(log_info)
257                                             : const_cast<char*>(log_warning);
258                 iov[0].iov_len =
259                     last_info ? sizeof(log_info) : sizeof(log_warning);
260                 iov[1].iov_base = last_str;
261                 iov[1].iov_len = strlen(last_str);
262                 iov[2].iov_base = const_cast<char*>(denial_metadata.c_str());
263                 iov[2].iov_len = denial_metadata.length();
264                 if (count > 1) {
265                     iov[3].iov_base = const_cast<char*>(resume);
266                     iov[3].iov_len = strlen(resume);
267                 } else {
268                     iov[3].iov_base = const_cast<char*>(newline);
269                     iov[3].iov_len = strlen(newline);
270                 }
271 
272                 writev(fdDmesg, iov, arraysize(iov));
273                 free(last_str);
274                 last_str = nullptr;
275             }
276         }
277         if (last_str == nullptr) {
278             count = 0;
279             last_str = strdup(str);
280             last_info = info;
281         }
282         if (count == 0) {
283             auditParse(str, uid, &denial_metadata);
284             iov[0].iov_base = info ? const_cast<char*>(log_info)
285                                    : const_cast<char*>(log_warning);
286             iov[0].iov_len = info ? sizeof(log_info) : sizeof(log_warning);
287             iov[1].iov_base = str;
288             iov[1].iov_len = strlen(str);
289             iov[2].iov_base = const_cast<char*>(denial_metadata.c_str());
290             iov[2].iov_len = denial_metadata.length();
291             iov[3].iov_base = const_cast<char*>(newline);
292             iov[3].iov_len = strlen(newline);
293 
294             writev(fdDmesg, iov, arraysize(iov));
295         }
296     }
297 
298     if (!main && !events) {
299         free(str);
300         return 0;
301     }
302 
303     log_time now(log_time::EPOCH);
304 
305     static const char audit_str[] = " audit(";
306     char* timeptr = strstr(str, audit_str);
307     if (timeptr &&
308         ((cp = now.strptime(timeptr + sizeof(audit_str) - 1, "%s.%q"))) &&
309         (*cp == ':')) {
310         memcpy(timeptr + sizeof(audit_str) - 1, "0.0", 3);
311         memmove(timeptr + sizeof(audit_str) - 1 + 3, cp, strlen(cp) + 1);
312         if (!isMonotonic()) {
313             if (android::isMonotonic(now)) {
314                 LogKlog::convertMonotonicToReal(now);
315             }
316         } else {
317             if (!android::isMonotonic(now)) {
318                 LogKlog::convertRealToMonotonic(now);
319             }
320         }
321     } else if (isMonotonic()) {
322         now = log_time(CLOCK_MONOTONIC);
323     } else {
324         now = log_time(CLOCK_REALTIME);
325     }
326 
327     // log to events
328 
329     size_t str_len = strnlen(str, LOGGER_ENTRY_MAX_PAYLOAD);
330     if (((fdDmesg < 0) || !initialized) && !hasMetadata(str, str_len))
331         auditParse(str, uid, &denial_metadata);
332     str_len = (str_len + denial_metadata.length() <= LOGGER_ENTRY_MAX_PAYLOAD)
333                   ? str_len + denial_metadata.length()
334                   : LOGGER_ENTRY_MAX_PAYLOAD;
335     size_t message_len = str_len + sizeof(android_log_event_string_t);
336 
337     log_mask_t notify = 0;
338 
339     if (events) {  // begin scope for event buffer
340         uint32_t buffer[(message_len + sizeof(uint32_t) - 1) / sizeof(uint32_t)];
341 
342         android_log_event_string_t* event =
343             reinterpret_cast<android_log_event_string_t*>(buffer);
344         event->header.tag = htole32(AUDITD_LOG_TAG);
345         event->type = EVENT_TYPE_STRING;
346         event->length = htole32(str_len);
347         memcpy(event->data, str, str_len - denial_metadata.length());
348         memcpy(event->data + str_len - denial_metadata.length(),
349                denial_metadata.c_str(), denial_metadata.length());
350 
351         rc = logbuf->log(
352             LOG_ID_EVENTS, now, uid, pid, tid, reinterpret_cast<char*>(event),
353             (message_len <= UINT16_MAX) ? (uint16_t)message_len : UINT16_MAX);
354         if (rc >= 0) {
355             notify |= 1 << LOG_ID_EVENTS;
356         }
357         // end scope for event buffer
358     }
359 
360     // log to main
361 
362     static const char comm_str[] = " comm=\"";
363     const char* comm = strstr(str, comm_str);
364     const char* estr = str + strlen(str);
365     const char* commfree = nullptr;
366     if (comm) {
367         estr = comm;
368         comm += sizeof(comm_str) - 1;
369     } else if (pid == getpid()) {
370         pid = tid;
371         comm = "auditd";
372     } else {
373         logbuf->wrlock();
374         comm = commfree = logbuf->pidToName(pid);
375         logbuf->unlock();
376         if (!comm) {
377             comm = "unknown";
378         }
379     }
380 
381     const char* ecomm = strchr(comm, '"');
382     if (ecomm) {
383         ++ecomm;
384         str_len = ecomm - comm;
385     } else {
386         str_len = strlen(comm) + 1;
387         ecomm = "";
388     }
389     size_t prefix_len = estr - str;
390     if (prefix_len > LOGGER_ENTRY_MAX_PAYLOAD) {
391         prefix_len = LOGGER_ENTRY_MAX_PAYLOAD;
392     }
393     size_t suffix_len = strnlen(ecomm, LOGGER_ENTRY_MAX_PAYLOAD - prefix_len);
394     message_len =
395         str_len + prefix_len + suffix_len + denial_metadata.length() + 2;
396 
397     if (main) {  // begin scope for main buffer
398         char newstr[message_len];
399 
400         *newstr = info ? ANDROID_LOG_INFO : ANDROID_LOG_WARN;
401         strlcpy(newstr + 1, comm, str_len);
402         strncpy(newstr + 1 + str_len, str, prefix_len);
403         strncpy(newstr + 1 + str_len + prefix_len, ecomm, suffix_len);
404         strncpy(newstr + 1 + str_len + prefix_len + suffix_len,
405                 denial_metadata.c_str(), denial_metadata.length());
406 
407         rc = logbuf->log(
408             LOG_ID_MAIN, now, uid, pid, tid, newstr,
409             (message_len <= UINT16_MAX) ? (uint16_t)message_len : UINT16_MAX);
410 
411         if (rc >= 0) {
412             notify |= 1 << LOG_ID_MAIN;
413         }
414         // end scope for main buffer
415     }
416 
417     free(const_cast<char*>(commfree));
418     free(str);
419 
420     if (notify) {
421         reader->notifyNewLog(notify);
422         if (rc < 0) {
423             rc = message_len;
424         }
425     }
426 
427     return rc;
428 }
429 
log(char * buf,size_t len)430 int LogAudit::log(char* buf, size_t len) {
431     char* audit = strstr(buf, " audit(");
432     if (!audit || (audit >= &buf[len])) {
433         return 0;
434     }
435 
436     *audit = '\0';
437 
438     int rc;
439     char* type = strstr(buf, "type=");
440     if (type && (type < &buf[len])) {
441         rc = logPrint("%s %s", type, audit + 1);
442     } else {
443         rc = logPrint("%s", audit + 1);
444     }
445     *audit = ' ';
446     return rc;
447 }
448 
getLogSocket()449 int LogAudit::getLogSocket() {
450     int fd = audit_open();
451     if (fd < 0) {
452         return fd;
453     }
454     if (audit_setup(fd, getpid()) < 0) {
455         audit_close(fd);
456         fd = -1;
457     }
458     return fd;
459 }
460