• 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 <errno.h>
19 #include <limits.h>
20 #include <stdarg.h>
21 #include <stdlib.h>
22 #include <sys/klog.h>
23 #include <sys/prctl.h>
24 #include <sys/uio.h>
25 
26 #include "libaudit.h"
27 #include "LogAudit.h"
28 
LogAudit(LogBuffer * buf,LogReader * reader,int fdDmsg)29 LogAudit::LogAudit(LogBuffer *buf, LogReader *reader, int fdDmsg)
30         : SocketListener(getLogSocket(), false)
31         , logbuf(buf)
32         , reader(reader)
33         , fdDmesg(-1) {
34     logDmesg();
35     fdDmesg = fdDmsg;
36 }
37 
onDataAvailable(SocketClient * cli)38 bool LogAudit::onDataAvailable(SocketClient *cli) {
39     prctl(PR_SET_NAME, "logd.auditd");
40 
41     struct audit_message rep;
42 
43     rep.nlh.nlmsg_type = 0;
44     rep.nlh.nlmsg_len = 0;
45     rep.data[0] = '\0';
46 
47     if (audit_get_reply(cli->getSocket(), &rep, GET_REPLY_BLOCKING, 0) < 0) {
48         SLOGE("Failed on audit_get_reply with error: %s", strerror(errno));
49         return false;
50     }
51 
52     logPrint("type=%d %.*s", rep.nlh.nlmsg_type, rep.nlh.nlmsg_len, rep.data);
53 
54     return true;
55 }
56 
logPrint(const char * fmt,...)57 int LogAudit::logPrint(const char *fmt, ...) {
58     if (fmt == NULL) {
59         return -EINVAL;
60     }
61 
62     va_list args;
63 
64     char *str = NULL;
65     va_start(args, fmt);
66     int rc = vasprintf(&str, fmt, args);
67     va_end(args);
68 
69     if (rc < 0) {
70         return rc;
71     }
72 
73     char *cp;
74     while ((cp = strstr(str, "  "))) {
75         memmove(cp, cp + 1, strlen(cp + 1) + 1);
76     }
77 
78     if (fdDmesg >= 0) {
79         struct iovec iov[2];
80 
81         iov[0].iov_base = str;
82         iov[0].iov_len = strlen(str);
83         iov[1].iov_base = const_cast<char *>("\n");
84         iov[1].iov_len = 1;
85 
86         writev(fdDmesg, iov, sizeof(iov) / sizeof(iov[0]));
87     }
88 
89     pid_t pid = getpid();
90     pid_t tid = gettid();
91     uid_t uid = getuid();
92     log_time now;
93 
94     static const char audit_str[] = " audit(";
95     char *timeptr = strstr(str, audit_str);
96     if (timeptr
97             && ((cp = now.strptime(timeptr + sizeof(audit_str) - 1, "%s.%q")))
98             && (*cp == ':')) {
99         memcpy(timeptr + sizeof(audit_str) - 1, "0.0", 3);
100         memmove(timeptr + sizeof(audit_str) - 1 + 3, cp, strlen(cp) + 1);
101     } else {
102         now.strptime("", ""); // side effect of setting CLOCK_REALTIME
103     }
104 
105     static const char pid_str[] = " pid=";
106     char *pidptr = strstr(str, pid_str);
107     if (pidptr && isdigit(pidptr[sizeof(pid_str) - 1])) {
108         cp = pidptr + sizeof(pid_str) - 1;
109         pid = 0;
110         while (isdigit(*cp)) {
111             pid = (pid * 10) + (*cp - '0');
112             ++cp;
113         }
114         tid = pid;
115         uid = logbuf->pidToUid(pid);
116         memmove(pidptr, cp, strlen(cp) + 1);
117     }
118 
119     // log to events
120 
121     size_t l = strlen(str);
122     size_t n = l + sizeof(uint32_t) + sizeof(uint8_t) + sizeof(uint32_t);
123 
124     bool notify = false;
125 
126     char *newstr = reinterpret_cast<char *>(malloc(n));
127     if (!newstr) {
128         rc = -ENOMEM;
129     } else {
130         cp = newstr;
131         *cp++ = AUDITD_LOG_TAG & 0xFF;
132         *cp++ = (AUDITD_LOG_TAG >> 8) & 0xFF;
133         *cp++ = (AUDITD_LOG_TAG >> 16) & 0xFF;
134         *cp++ = (AUDITD_LOG_TAG >> 24) & 0xFF;
135         *cp++ = EVENT_TYPE_STRING;
136         *cp++ = l & 0xFF;
137         *cp++ = (l >> 8) & 0xFF;
138         *cp++ = (l >> 16) & 0xFF;
139         *cp++ = (l >> 24) & 0xFF;
140         memcpy(cp, str, l);
141 
142         logbuf->log(LOG_ID_EVENTS, now, uid, pid, tid, newstr,
143                     (n <= USHRT_MAX) ? (unsigned short) n : USHRT_MAX);
144         free(newstr);
145 
146         notify = true;
147     }
148 
149     // log to main
150 
151     static const char comm_str[] = " comm=\"";
152     const char *comm = strstr(str, comm_str);
153     const char *estr = str + strlen(str);
154     if (comm) {
155         estr = comm;
156         comm += sizeof(comm_str) - 1;
157     } else if (pid == getpid()) {
158         pid = tid;
159         comm = "auditd";
160     } else if (!(comm = logbuf->pidToName(pid))) {
161         comm = "unknown";
162     }
163 
164     const char *ecomm = strchr(comm, '"');
165     if (ecomm) {
166         ++ecomm;
167         l = ecomm - comm;
168     } else {
169         l = strlen(comm) + 1;
170         ecomm = "";
171     }
172     n = (estr - str) + strlen(ecomm) + l + 2;
173 
174     newstr = reinterpret_cast<char *>(malloc(n));
175     if (!newstr) {
176         rc = -ENOMEM;
177     } else {
178         *newstr = (strstr(str, " permissive=1")
179                 || strstr(str, " policy loaded "))
180                     ? ANDROID_LOG_INFO
181                     : ANDROID_LOG_WARN;
182         strlcpy(newstr + 1, comm, l);
183         strncpy(newstr + 1 + l, str, estr - str);
184         strcpy(newstr + 1 + l + (estr - str), ecomm);
185 
186         logbuf->log(LOG_ID_MAIN, now, uid, pid, tid, newstr,
187                     (n <= USHRT_MAX) ? (unsigned short) n : USHRT_MAX);
188         free(newstr);
189 
190         notify = true;
191     }
192 
193     free(str);
194 
195     if (notify) {
196         reader->notifyNewLog();
197     }
198 
199     return rc;
200 }
201 
logDmesg()202 void LogAudit::logDmesg() {
203     int len = klogctl(KLOG_SIZE_BUFFER, NULL, 0);
204     if (len <= 0) {
205         return;
206     }
207 
208     len++;
209     char buf[len];
210 
211     int rc = klogctl(KLOG_READ_ALL, buf, len);
212 
213     buf[len - 1] = '\0';
214 
215     for(char *tok = buf; (rc >= 0) && ((tok = strtok(tok, "\r\n"))); tok = NULL) {
216         char *audit = strstr(tok, " audit(");
217         if (!audit) {
218             continue;
219         }
220 
221         *audit++ = '\0';
222 
223         char *type = strstr(tok, "type=");
224         if (type) {
225             rc = logPrint("%s %s", type, audit);
226         } else {
227             rc = logPrint("%s", audit);
228         }
229     }
230 }
231 
getLogSocket()232 int LogAudit::getLogSocket() {
233     int fd = audit_open();
234     if (fd < 0) {
235         return fd;
236     }
237     if (audit_set_pid(fd, getpid(), WAIT_YES) < 0) {
238         audit_close(fd);
239         fd = -1;
240     }
241     return fd;
242 }
243