1 /*
2  * Copyright (C) 2012-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 <fcntl.h>
20 #include <stdio.h>
21 #include <string.h>
22 #include <time.h>
23 #include <unistd.h>
24 
25 #include <log/logger.h>
26 #include <private/android_logger.h>
27 
28 #include "LogBuffer.h"
29 #include "LogBufferElement.h"
30 #include "LogCommand.h"
31 #include "LogReader.h"
32 #include "LogUtils.h"
33 
34 const uint64_t LogBufferElement::FLUSH_ERROR(0);
35 atomic_int_fast64_t LogBufferElement::sequence(1);
36 
LogBufferElement(log_id_t log_id,log_time realtime,uid_t uid,pid_t pid,pid_t tid,const char * msg,unsigned short len)37 LogBufferElement::LogBufferElement(log_id_t log_id, log_time realtime,
38                                    uid_t uid, pid_t pid, pid_t tid,
39                                    const char *msg, unsigned short len) :
40         mLogId(log_id),
41         mUid(uid),
42         mPid(pid),
43         mTid(tid),
44         mMsgLen(len),
45         mSequence(sequence.fetch_add(1, memory_order_relaxed)),
46         mRealTime(realtime) {
47     mMsg = new char[len];
48     memcpy(mMsg, msg, len);
49 }
50 
~LogBufferElement()51 LogBufferElement::~LogBufferElement() {
52     delete [] mMsg;
53 }
54 
getTag() const55 uint32_t LogBufferElement::getTag() const {
56     if (((mLogId != LOG_ID_EVENTS) && (mLogId != LOG_ID_SECURITY)) ||
57             !mMsg || (mMsgLen < sizeof(uint32_t))) {
58         return 0;
59     }
60     return le32toh(reinterpret_cast<android_event_header_t *>(mMsg)->tag);
61 }
62 
63 // caller must own and free character string
tidToName(pid_t tid)64 char *android::tidToName(pid_t tid) {
65     char *retval = NULL;
66     char buffer[256];
67     snprintf(buffer, sizeof(buffer), "/proc/%u/comm", tid);
68     int fd = open(buffer, O_RDONLY);
69     if (fd >= 0) {
70         ssize_t ret = read(fd, buffer, sizeof(buffer));
71         if (ret >= (ssize_t)sizeof(buffer)) {
72             ret = sizeof(buffer) - 1;
73         }
74         while ((ret > 0) && isspace(buffer[ret - 1])) {
75             --ret;
76         }
77         if (ret > 0) {
78             buffer[ret] = '\0';
79             retval = strdup(buffer);
80         }
81         close(fd);
82     }
83 
84     // if nothing for comm, check out cmdline
85     char *name = android::pidToName(tid);
86     if (!retval) {
87         retval = name;
88         name = NULL;
89     }
90 
91     // check if comm is truncated, see if cmdline has full representation
92     if (name) {
93         // impossible for retval to be NULL if name not NULL
94         size_t retval_len = strlen(retval);
95         size_t name_len = strlen(name);
96         // KISS: ToDo: Only checks prefix truncated, not suffix, or both
97         if ((retval_len < name_len)
98                 && !fast<strcmp>(retval, name + name_len - retval_len)) {
99             free(retval);
100             retval = name;
101         } else {
102             free(name);
103         }
104     }
105     return retval;
106 }
107 
108 // assumption: mMsg == NULL
populateDroppedMessage(char * & buffer,LogBuffer * parent)109 size_t LogBufferElement::populateDroppedMessage(char *&buffer,
110         LogBuffer *parent) {
111     static const char tag[] = "chatty";
112 
113     if (!__android_log_is_loggable(ANDROID_LOG_INFO, tag, ANDROID_LOG_VERBOSE)) {
114         return 0;
115     }
116 
117     static const char format_uid[] = "uid=%u%s%s expire %u line%s";
118     parent->lock();
119     const char *name = parent->uidToName(mUid);
120     parent->unlock();
121     const char *commName = android::tidToName(mTid);
122     if (!commName && (mTid != mPid)) {
123         commName = android::tidToName(mPid);
124     }
125     if (!commName) {
126         parent->lock();
127         commName = parent->pidToName(mPid);
128         parent->unlock();
129     }
130     if (name && name[0] && commName && (name[0] == commName[0])) {
131         size_t len = strlen(name + 1);
132         if (!strncmp(name + 1, commName + 1, len)) {
133             if (commName[len + 1] == '\0') {
134                 free(const_cast<char *>(commName));
135                 commName = NULL;
136             } else {
137                 free(const_cast<char *>(name));
138                 name = NULL;
139             }
140         }
141     }
142     if (name) {
143         char *buf = NULL;
144         asprintf(&buf, "(%s)", name);
145         if (buf) {
146             free(const_cast<char *>(name));
147             name = buf;
148         }
149     }
150     if (commName) {
151         char *buf = NULL;
152         asprintf(&buf, " %s", commName);
153         if (buf) {
154             free(const_cast<char *>(commName));
155             commName = buf;
156         }
157     }
158     // identical to below to calculate the buffer size required
159     size_t len = snprintf(NULL, 0, format_uid, mUid, name ? name : "",
160                           commName ? commName : "",
161                           mDropped, (mDropped > 1) ? "s" : "");
162 
163     size_t hdrLen;
164     // LOG_ID_SECURITY not strictly needed since spam filter not activated,
165     // but required for accuracy.
166     if ((mLogId == LOG_ID_EVENTS) || (mLogId == LOG_ID_SECURITY)) {
167         hdrLen = sizeof(android_log_event_string_t);
168     } else {
169         hdrLen = 1 + sizeof(tag);
170     }
171 
172     buffer = static_cast<char *>(calloc(1, hdrLen + len + 1));
173     if (!buffer) {
174         free(const_cast<char *>(name));
175         free(const_cast<char *>(commName));
176         return 0;
177     }
178 
179     size_t retval = hdrLen + len;
180     if ((mLogId == LOG_ID_EVENTS) || (mLogId == LOG_ID_SECURITY)) {
181         android_log_event_string_t *event =
182             reinterpret_cast<android_log_event_string_t *>(buffer);
183 
184         event->header.tag = htole32(LOGD_LOG_TAG);
185         event->type = EVENT_TYPE_STRING;
186         event->length = htole32(len);
187     } else {
188         ++retval;
189         buffer[0] = ANDROID_LOG_INFO;
190         strcpy(buffer + 1, tag);
191     }
192 
193     snprintf(buffer + hdrLen, len + 1, format_uid, mUid, name ? name : "",
194              commName ? commName : "",
195              mDropped, (mDropped > 1) ? "s" : "");
196     free(const_cast<char *>(name));
197     free(const_cast<char *>(commName));
198 
199     return retval;
200 }
201 
flushTo(SocketClient * reader,LogBuffer * parent,bool privileged)202 uint64_t LogBufferElement::flushTo(SocketClient *reader, LogBuffer *parent,
203                                    bool privileged) {
204     struct logger_entry_v4 entry;
205 
206     memset(&entry, 0, sizeof(struct logger_entry_v4));
207 
208     entry.hdr_size = privileged ?
209                          sizeof(struct logger_entry_v4) :
210                          sizeof(struct logger_entry_v3);
211     entry.lid = mLogId;
212     entry.pid = mPid;
213     entry.tid = mTid;
214     entry.uid = mUid;
215     entry.sec = mRealTime.tv_sec;
216     entry.nsec = mRealTime.tv_nsec;
217 
218     struct iovec iovec[2];
219     iovec[0].iov_base = &entry;
220     iovec[0].iov_len = entry.hdr_size;
221 
222     char *buffer = NULL;
223 
224     if (!mMsg) {
225         entry.len = populateDroppedMessage(buffer, parent);
226         if (!entry.len) {
227             return mSequence;
228         }
229         iovec[1].iov_base = buffer;
230     } else {
231         entry.len = mMsgLen;
232         iovec[1].iov_base = mMsg;
233     }
234     iovec[1].iov_len = entry.len;
235 
236     uint64_t retval = reader->sendDatav(iovec, 2) ? FLUSH_ERROR : mSequence;
237 
238     if (buffer) {
239         free(buffer);
240     }
241 
242     return retval;
243 }
244