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 "CommandListener.h"
18
19 #include <arpa/inet.h>
20 #include <ctype.h>
21 #include <dirent.h>
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <math.h>
25 #include <netinet/in.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <sys/prctl.h>
29 #include <sys/socket.h>
30 #include <sys/types.h>
31
32 #include <string>
33
34 #include <android-base/logging.h>
35 #include <android-base/stringprintf.h>
36 #include <cutils/sockets.h>
37 #include <log/log_properties.h>
38 #include <private/android_filesystem_config.h>
39 #include <sysutils/SocketClient.h>
40
41 #include "LogPermissions.h"
42
CommandListener(LogBuffer * buf,LogTags * tags,PruneList * prune,LogStatistics * stats)43 CommandListener::CommandListener(LogBuffer* buf, LogTags* tags, PruneList* prune,
44 LogStatistics* stats)
45 : FrameworkListener(getLogSocket()), buf_(buf), tags_(tags), prune_(prune), stats_(stats) {
46 registerCmd(new ClearCmd(this));
47 registerCmd(new GetBufSizeCmd(this));
48 registerCmd(new SetBufSizeCmd(this));
49 registerCmd(new GetBufSizeUsedCmd(this));
50 registerCmd(new GetStatisticsCmd(this));
51 registerCmd(new SetPruneListCmd(this));
52 registerCmd(new GetPruneListCmd(this));
53 registerCmd(new GetEventTagCmd(this));
54 registerCmd(new ReinitCmd(this));
55 registerCmd(new ExitCmd(this));
56 }
57
setname()58 static void setname() {
59 static bool name_set;
60 if (!name_set) {
61 prctl(PR_SET_NAME, "logd.control");
62 name_set = true;
63 }
64 }
65
runCommand(SocketClient * cli,int argc,char ** argv)66 int CommandListener::ClearCmd::runCommand(SocketClient* cli, int argc,
67 char** argv) {
68 setname();
69 uid_t uid = cli->getUid();
70 if (clientHasLogCredentials(cli)) {
71 uid = AID_ROOT;
72 }
73
74 if (argc < 2) {
75 cli->sendMsg("Missing Argument");
76 return 0;
77 }
78
79 int id = atoi(argv[1]);
80 if ((id < LOG_ID_MIN) || (LOG_ID_MAX <= id)) {
81 cli->sendMsg("Range Error");
82 return 0;
83 }
84
85 cli->sendMsg(buf()->Clear((log_id_t)id, uid) ? "success" : "busy");
86 return 0;
87 }
88
runCommand(SocketClient * cli,int argc,char ** argv)89 int CommandListener::GetBufSizeCmd::runCommand(SocketClient* cli, int argc,
90 char** argv) {
91 setname();
92 if (argc < 2) {
93 cli->sendMsg("Missing Argument");
94 return 0;
95 }
96
97 int id = atoi(argv[1]);
98 if ((id < LOG_ID_MIN) || (LOG_ID_MAX <= id)) {
99 cli->sendMsg("Range Error");
100 return 0;
101 }
102
103 unsigned long size = buf()->GetSize((log_id_t)id);
104 char buf[512];
105 snprintf(buf, sizeof(buf), "%lu", size);
106 cli->sendMsg(buf);
107 return 0;
108 }
109
runCommand(SocketClient * cli,int argc,char ** argv)110 int CommandListener::SetBufSizeCmd::runCommand(SocketClient* cli, int argc,
111 char** argv) {
112 setname();
113 if (!clientHasLogCredentials(cli)) {
114 cli->sendMsg("Permission Denied");
115 return 0;
116 }
117
118 if (argc < 3) {
119 cli->sendMsg("Missing Argument");
120 return 0;
121 }
122
123 int id = atoi(argv[1]);
124 if ((id < LOG_ID_MIN) || (LOG_ID_MAX <= id)) {
125 cli->sendMsg("Range Error");
126 return 0;
127 }
128
129 unsigned long size = atol(argv[2]);
130 if (buf()->SetSize((log_id_t)id, size)) {
131 cli->sendMsg("Range Error");
132 return 0;
133 }
134
135 cli->sendMsg("success");
136 return 0;
137 }
138
runCommand(SocketClient * cli,int argc,char ** argv)139 int CommandListener::GetBufSizeUsedCmd::runCommand(SocketClient* cli, int argc,
140 char** argv) {
141 setname();
142 if (argc < 2) {
143 cli->sendMsg("Missing Argument");
144 return 0;
145 }
146
147 int id = atoi(argv[1]);
148 if ((id < LOG_ID_MIN) || (LOG_ID_MAX <= id)) {
149 cli->sendMsg("Range Error");
150 return 0;
151 }
152
153 unsigned long size = stats()->Sizes((log_id_t)id);
154 char buf[512];
155 snprintf(buf, sizeof(buf), "%lu", size);
156 cli->sendMsg(buf);
157 return 0;
158 }
159
160 // This returns a string with a length prefix with the format <length>\n<data>\n\f. The length
161 // prefix includes the length of the prefix itself.
PackageString(const std::string & str)162 static std::string PackageString(const std::string& str) {
163 size_t overhead_length = 3; // \n \n \f.
164
165 // Number of digits needed to represent length(str + overhead_length).
166 size_t str_size_digits = 1 + static_cast<size_t>(log10(str.size() + overhead_length));
167 // Number of digits needed to represent the total size.
168 size_t total_size_digits =
169 1 + static_cast<size_t>(log10(str.size() + overhead_length + str_size_digits));
170
171 // If adding the size prefix causes a new digit to be required to represent the new total
172 // size, add it to the 'overhead_length'. This can only happen once, since each new digit
173 // allows for 10x the previous size to be recorded.
174 if (total_size_digits != str_size_digits) {
175 overhead_length++;
176 }
177
178 size_t total_size = str.size() + overhead_length + str_size_digits;
179 return android::base::StringPrintf("%zu\n%s\n\f", total_size, str.c_str());
180 }
181
runCommand(SocketClient * cli,int argc,char ** argv)182 int CommandListener::GetStatisticsCmd::runCommand(SocketClient* cli, int argc,
183 char** argv) {
184 setname();
185 uid_t uid = cli->getUid();
186 if (clientHasLogCredentials(cli)) {
187 uid = AID_ROOT;
188 }
189
190 unsigned int logMask = -1;
191 pid_t pid = 0;
192 if (argc > 1) {
193 logMask = 0;
194 for (int i = 1; i < argc; ++i) {
195 static const char _pid[] = "pid=";
196 if (!strncmp(argv[i], _pid, sizeof(_pid) - 1)) {
197 pid = atol(argv[i] + sizeof(_pid) - 1);
198 if (pid == 0) {
199 cli->sendMsg("PID Error");
200 return 0;
201 }
202 continue;
203 }
204
205 int id = atoi(argv[i]);
206 if ((id < LOG_ID_MIN) || (LOG_ID_MAX <= id)) {
207 cli->sendMsg("Range Error");
208 return 0;
209 }
210 logMask |= 1 << id;
211 }
212 }
213
214 cli->sendMsg(PackageString(stats()->Format(uid, pid, logMask)).c_str());
215 return 0;
216 }
217
runCommand(SocketClient * cli,int,char **)218 int CommandListener::GetPruneListCmd::runCommand(SocketClient* cli, int, char**) {
219 setname();
220 cli->sendMsg(PackageString(prune()->Format()).c_str());
221 return 0;
222 }
223
runCommand(SocketClient * cli,int argc,char ** argv)224 int CommandListener::SetPruneListCmd::runCommand(SocketClient* cli, int argc, char** argv) {
225 setname();
226 if (!clientHasLogCredentials(cli)) {
227 cli->sendMsg("Permission Denied");
228 return 0;
229 }
230
231 std::string str;
232 for (int i = 1; i < argc; ++i) {
233 if (str.length()) {
234 str += " ";
235 }
236 str += argv[i];
237 }
238
239 if (!prune()->Init(str.c_str())) {
240 cli->sendMsg("Invalid");
241 return 0;
242 }
243
244 cli->sendMsg("success");
245 return 0;
246 }
247
runCommand(SocketClient * cli,int argc,char ** argv)248 int CommandListener::GetEventTagCmd::runCommand(SocketClient* cli, int argc,
249 char** argv) {
250 setname();
251 uid_t uid = cli->getUid();
252 if (clientHasLogCredentials(cli)) {
253 uid = AID_ROOT;
254 }
255
256 const char* name = nullptr;
257 const char* format = nullptr;
258 const char* id = nullptr;
259 for (int i = 1; i < argc; ++i) {
260 static const char _name[] = "name=";
261 if (!strncmp(argv[i], _name, strlen(_name))) {
262 name = argv[i] + strlen(_name);
263 continue;
264 }
265
266 static const char _format[] = "format=";
267 if (!strncmp(argv[i], _format, strlen(_format))) {
268 format = argv[i] + strlen(_format);
269 continue;
270 }
271
272 static const char _id[] = "id=";
273 if (!strncmp(argv[i], _id, strlen(_id))) {
274 id = argv[i] + strlen(_id);
275 continue;
276 }
277 }
278
279 if (id) {
280 if (format || name) {
281 cli->sendMsg("can not mix id= with either format= or name=");
282 return 0;
283 }
284 cli->sendMsg(PackageString(tags()->formatEntry(atoi(id), uid)).c_str());
285 return 0;
286 }
287
288 cli->sendMsg(PackageString(tags()->formatGetEventTag(uid, name, format)).c_str());
289
290 return 0;
291 }
292
runCommand(SocketClient * cli,int,char **)293 int CommandListener::ReinitCmd::runCommand(SocketClient* cli, int /*argc*/,
294 char** /*argv*/) {
295 setname();
296
297 LOG(INFO) << "logd reinit";
298 buf()->Init();
299 prune()->Init(nullptr);
300
301 // This only works on userdebug and eng devices to re-read the
302 // /data/misc/logd/event-log-tags file right after /data is mounted.
303 // The operation is near to boot and should only happen once. There
304 // are races associated with its use since it can trigger a Rebuild
305 // of the file, but that is a can-not-happen since the file was not
306 // read yet. More dangerous if called later, but if all is well it
307 // should just skip over everything and not write any new entries.
308 if (__android_log_is_debuggable()) {
309 tags()->ReadFileEventLogTags(tags()->debug_event_log_tags);
310 }
311
312 cli->sendMsg("success");
313
314 return 0;
315 }
316
runCommand(SocketClient * cli,int,char **)317 int CommandListener::ExitCmd::runCommand(SocketClient* cli, int /*argc*/,
318 char** /*argv*/) {
319 setname();
320
321 cli->sendMsg("success");
322 parent_->release(cli);
323
324 return 0;
325 }
326
getLogSocket()327 int CommandListener::getLogSocket() {
328 static const char socketName[] = "logd";
329 int sock = android_get_control_socket(socketName);
330
331 if (sock < 0) {
332 sock = socket_local_server(
333 socketName, ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
334 }
335
336 return sock;
337 }
338