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 <arpa/inet.h>
18 #include <ctype.h>
19 #include <dirent.h>
20 #include <errno.h>
21 #include <fcntl.h>
22 #include <netinet/in.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <sys/prctl.h>
26 #include <sys/socket.h>
27 #include <sys/types.h>
28
29 #include <string>
30
31 #include <android-base/stringprintf.h>
32 #include <cutils/sockets.h>
33 #include <private/android_filesystem_config.h>
34 #include <sysutils/SocketClient.h>
35
36 #include "CommandListener.h"
37 #include "LogCommand.h"
38 #include "LogUtils.h"
39
CommandListener(LogBuffer * buf,LogReader *,LogListener *)40 CommandListener::CommandListener(LogBuffer* buf, LogReader* /*reader*/,
41 LogListener* /*swl*/)
42 : FrameworkListener(getLogSocket()) {
43 // registerCmd(new ShutdownCmd(buf, writer, swl));
44 registerCmd(new ClearCmd(buf));
45 registerCmd(new GetBufSizeCmd(buf));
46 registerCmd(new SetBufSizeCmd(buf));
47 registerCmd(new GetBufSizeUsedCmd(buf));
48 registerCmd(new GetStatisticsCmd(buf));
49 registerCmd(new SetPruneListCmd(buf));
50 registerCmd(new GetPruneListCmd(buf));
51 registerCmd(new GetEventTagCmd(buf));
52 registerCmd(new ReinitCmd());
53 registerCmd(new ExitCmd(this));
54 }
55
ShutdownCmd(LogReader * reader,LogListener * swl)56 CommandListener::ShutdownCmd::ShutdownCmd(LogReader* reader, LogListener* swl)
57 : LogCommand("shutdown"), mReader(*reader), mSwl(*swl) {
58 }
59
runCommand(SocketClient *,int,char **)60 int CommandListener::ShutdownCmd::runCommand(SocketClient* /*cli*/,
61 int /*argc*/, char** /*argv*/) {
62 mSwl.stopListener();
63 mReader.stopListener();
64 exit(0);
65 }
66
ClearCmd(LogBuffer * buf)67 CommandListener::ClearCmd::ClearCmd(LogBuffer* buf)
68 : LogCommand("clear"), mBuf(*buf) {
69 }
70
setname()71 static void setname() {
72 static bool name_set;
73 if (!name_set) {
74 prctl(PR_SET_NAME, "logd.control");
75 name_set = true;
76 }
77 }
78
runCommand(SocketClient * cli,int argc,char ** argv)79 int CommandListener::ClearCmd::runCommand(SocketClient* cli, int argc,
80 char** argv) {
81 setname();
82 uid_t uid = cli->getUid();
83 if (clientHasLogCredentials(cli)) {
84 uid = AID_ROOT;
85 }
86
87 if (argc < 2) {
88 cli->sendMsg("Missing Argument");
89 return 0;
90 }
91
92 int id = atoi(argv[1]);
93 if ((id < LOG_ID_MIN) || (LOG_ID_MAX <= id)) {
94 cli->sendMsg("Range Error");
95 return 0;
96 }
97
98 cli->sendMsg(mBuf.clear((log_id_t)id, uid) ? "busy" : "success");
99 return 0;
100 }
101
GetBufSizeCmd(LogBuffer * buf)102 CommandListener::GetBufSizeCmd::GetBufSizeCmd(LogBuffer* buf)
103 : LogCommand("getLogSize"), mBuf(*buf) {
104 }
105
runCommand(SocketClient * cli,int argc,char ** argv)106 int CommandListener::GetBufSizeCmd::runCommand(SocketClient* cli, int argc,
107 char** argv) {
108 setname();
109 if (argc < 2) {
110 cli->sendMsg("Missing Argument");
111 return 0;
112 }
113
114 int id = atoi(argv[1]);
115 if ((id < LOG_ID_MIN) || (LOG_ID_MAX <= id)) {
116 cli->sendMsg("Range Error");
117 return 0;
118 }
119
120 unsigned long size = mBuf.getSize((log_id_t)id);
121 char buf[512];
122 snprintf(buf, sizeof(buf), "%lu", size);
123 cli->sendMsg(buf);
124 return 0;
125 }
126
SetBufSizeCmd(LogBuffer * buf)127 CommandListener::SetBufSizeCmd::SetBufSizeCmd(LogBuffer* buf)
128 : LogCommand("setLogSize"), mBuf(*buf) {
129 }
130
runCommand(SocketClient * cli,int argc,char ** argv)131 int CommandListener::SetBufSizeCmd::runCommand(SocketClient* cli, int argc,
132 char** argv) {
133 setname();
134 if (!clientHasLogCredentials(cli)) {
135 cli->sendMsg("Permission Denied");
136 return 0;
137 }
138
139 if (argc < 3) {
140 cli->sendMsg("Missing Argument");
141 return 0;
142 }
143
144 int id = atoi(argv[1]);
145 if ((id < LOG_ID_MIN) || (LOG_ID_MAX <= id)) {
146 cli->sendMsg("Range Error");
147 return 0;
148 }
149
150 unsigned long size = atol(argv[2]);
151 if (mBuf.setSize((log_id_t)id, size)) {
152 cli->sendMsg("Range Error");
153 return 0;
154 }
155
156 cli->sendMsg("success");
157 return 0;
158 }
159
GetBufSizeUsedCmd(LogBuffer * buf)160 CommandListener::GetBufSizeUsedCmd::GetBufSizeUsedCmd(LogBuffer* buf)
161 : LogCommand("getLogSizeUsed"), mBuf(*buf) {
162 }
163
runCommand(SocketClient * cli,int argc,char ** argv)164 int CommandListener::GetBufSizeUsedCmd::runCommand(SocketClient* cli, int argc,
165 char** argv) {
166 setname();
167 if (argc < 2) {
168 cli->sendMsg("Missing Argument");
169 return 0;
170 }
171
172 int id = atoi(argv[1]);
173 if ((id < LOG_ID_MIN) || (LOG_ID_MAX <= id)) {
174 cli->sendMsg("Range Error");
175 return 0;
176 }
177
178 unsigned long size = mBuf.getSizeUsed((log_id_t)id);
179 char buf[512];
180 snprintf(buf, sizeof(buf), "%lu", size);
181 cli->sendMsg(buf);
182 return 0;
183 }
184
GetStatisticsCmd(LogBuffer * buf)185 CommandListener::GetStatisticsCmd::GetStatisticsCmd(LogBuffer* buf)
186 : LogCommand("getStatistics"), mBuf(*buf) {
187 }
188
package_string(const std::string & str)189 static std::string package_string(const std::string& str) {
190 // Calculate total buffer size prefix, count is the string length w/o nul
191 char fmt[32];
192 for (size_t l = str.length(), y = 0, x = 6; y != x;
193 y = x, x = strlen(fmt) - 2) {
194 snprintf(fmt, sizeof(fmt), "%zu\n%%s\n\f", l + x);
195 }
196 return android::base::StringPrintf(fmt, str.c_str());
197 }
198
runCommand(SocketClient * cli,int argc,char ** argv)199 int CommandListener::GetStatisticsCmd::runCommand(SocketClient* cli, int argc,
200 char** argv) {
201 setname();
202 uid_t uid = cli->getUid();
203 if (clientHasLogCredentials(cli)) {
204 uid = AID_ROOT;
205 }
206
207 unsigned int logMask = -1;
208 pid_t pid = 0;
209 if (argc > 1) {
210 logMask = 0;
211 for (int i = 1; i < argc; ++i) {
212 static const char _pid[] = "pid=";
213 if (!strncmp(argv[i], _pid, sizeof(_pid) - 1)) {
214 pid = atol(argv[i] + sizeof(_pid) - 1);
215 if (pid == 0) {
216 cli->sendMsg("PID Error");
217 return 0;
218 }
219 continue;
220 }
221
222 int id = atoi(argv[i]);
223 if ((id < LOG_ID_MIN) || (LOG_ID_MAX <= id)) {
224 cli->sendMsg("Range Error");
225 return 0;
226 }
227 logMask |= 1 << id;
228 }
229 }
230
231 cli->sendMsg(
232 package_string(mBuf.formatStatistics(uid, pid, logMask)).c_str());
233 return 0;
234 }
235
GetPruneListCmd(LogBuffer * buf)236 CommandListener::GetPruneListCmd::GetPruneListCmd(LogBuffer* buf)
237 : LogCommand("getPruneList"), mBuf(*buf) {
238 }
239
runCommand(SocketClient * cli,int,char **)240 int CommandListener::GetPruneListCmd::runCommand(SocketClient* cli,
241 int /*argc*/, char** /*argv*/) {
242 setname();
243 cli->sendMsg(package_string(mBuf.formatPrune()).c_str());
244 return 0;
245 }
246
SetPruneListCmd(LogBuffer * buf)247 CommandListener::SetPruneListCmd::SetPruneListCmd(LogBuffer* buf)
248 : LogCommand("setPruneList"), mBuf(*buf) {
249 }
250
runCommand(SocketClient * cli,int argc,char ** argv)251 int CommandListener::SetPruneListCmd::runCommand(SocketClient* cli, int argc,
252 char** argv) {
253 setname();
254 if (!clientHasLogCredentials(cli)) {
255 cli->sendMsg("Permission Denied");
256 return 0;
257 }
258
259 std::string str;
260 for (int i = 1; i < argc; ++i) {
261 if (str.length()) {
262 str += " ";
263 }
264 str += argv[i];
265 }
266
267 int ret = mBuf.initPrune(str.c_str());
268
269 if (ret) {
270 cli->sendMsg("Invalid");
271 return 0;
272 }
273
274 cli->sendMsg("success");
275
276 return 0;
277 }
278
GetEventTagCmd(LogBuffer * buf)279 CommandListener::GetEventTagCmd::GetEventTagCmd(LogBuffer* buf)
280 : LogCommand("getEventTag"), mBuf(*buf) {
281 }
282
runCommand(SocketClient * cli,int argc,char ** argv)283 int CommandListener::GetEventTagCmd::runCommand(SocketClient* cli, int argc,
284 char** argv) {
285 setname();
286 uid_t uid = cli->getUid();
287 if (clientHasLogCredentials(cli)) {
288 uid = AID_ROOT;
289 }
290
291 const char* name = nullptr;
292 const char* format = nullptr;
293 const char* id = nullptr;
294 for (int i = 1; i < argc; ++i) {
295 static const char _name[] = "name=";
296 if (!strncmp(argv[i], _name, strlen(_name))) {
297 name = argv[i] + strlen(_name);
298 continue;
299 }
300
301 static const char _format[] = "format=";
302 if (!strncmp(argv[i], _format, strlen(_format))) {
303 format = argv[i] + strlen(_format);
304 continue;
305 }
306
307 static const char _id[] = "id=";
308 if (!strncmp(argv[i], _id, strlen(_id))) {
309 id = argv[i] + strlen(_id);
310 continue;
311 }
312 }
313
314 if (id) {
315 if (format || name) {
316 cli->sendMsg("can not mix id= with either format= or name=");
317 return 0;
318 }
319 cli->sendMsg(package_string(mBuf.formatEntry(atoi(id), uid)).c_str());
320 return 0;
321 }
322
323 cli->sendMsg(
324 package_string(mBuf.formatGetEventTag(uid, name, format)).c_str());
325
326 return 0;
327 }
328
ReinitCmd()329 CommandListener::ReinitCmd::ReinitCmd() : LogCommand("reinit") {
330 }
331
runCommand(SocketClient * cli,int,char **)332 int CommandListener::ReinitCmd::runCommand(SocketClient* cli, int /*argc*/,
333 char** /*argv*/) {
334 setname();
335
336 reinit_signal_handler(SIGHUP);
337
338 cli->sendMsg("success");
339
340 return 0;
341 }
342
ExitCmd(CommandListener * parent)343 CommandListener::ExitCmd::ExitCmd(CommandListener* parent)
344 : LogCommand("EXIT"), mParent(*parent) {
345 }
346
runCommand(SocketClient * cli,int,char **)347 int CommandListener::ExitCmd::runCommand(SocketClient* cli, int /*argc*/,
348 char** /*argv*/) {
349 setname();
350
351 cli->sendMsg("success");
352 release(cli);
353
354 return 0;
355 }
356
getLogSocket()357 int CommandListener::getLogSocket() {
358 static const char socketName[] = "logd";
359 int sock = android_get_control_socket(socketName);
360
361 if (sock < 0) {
362 sock = socket_local_server(
363 socketName, ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
364 }
365
366 return sock;
367 }
368