blob: fc9e30ff4e7d3d990b6edd214a98eb59e2588614 [file] [log] [blame]
Mark Salyzyn0175b072014-02-26 09:50:16 -08001/*
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
Mark Salyzyne0fa2912014-04-28 16:39:04 -070017#include <limits.h>
Mark Salyzyn8daa9af2014-04-28 14:07:23 -070018#include <sys/prctl.h>
Mark Salyzyn0175b072014-02-26 09:50:16 -080019#include <sys/socket.h>
20#include <sys/types.h>
21#include <sys/un.h>
22#include <unistd.h>
23
24#include <cutils/sockets.h>
25#include <log/logger.h>
Mark Salyzynb5f6e452015-01-16 13:38:07 -080026#include <private/android_logger.h>
Mark Salyzyn0175b072014-02-26 09:50:16 -080027
28#include "LogListener.h"
29
30LogListener::LogListener(LogBuffer *buf, LogReader *reader)
31 : SocketListener(getLogSocket(), false)
32 , logbuf(buf)
33 , reader(reader)
34{ }
35
36bool LogListener::onDataAvailable(SocketClient *cli) {
Mark Salyzyn8daa9af2014-04-28 14:07:23 -070037 prctl(PR_SET_NAME, "logd.writer");
38
Mark Salyzyn8444eb82014-04-24 09:43:23 -070039 char buffer[sizeof_log_id_t + sizeof(uint16_t) + sizeof(log_time)
Mark Salyzynb059cf52014-03-18 15:30:17 -070040 + LOGGER_ENTRY_MAX_PAYLOAD];
Mark Salyzyn0175b072014-02-26 09:50:16 -080041 struct iovec iov = { buffer, sizeof(buffer) };
42 memset(buffer, 0, sizeof(buffer));
43
44 char control[CMSG_SPACE(sizeof(struct ucred))];
45 struct msghdr hdr = {
46 NULL,
47 0,
48 &iov,
49 1,
50 control,
51 sizeof(control),
52 0,
53 };
54
55 int socket = cli->getSocket();
56
57 ssize_t n = recvmsg(socket, &hdr, 0);
Mark Salyzynb5f6e452015-01-16 13:38:07 -080058 if (n <= (ssize_t)(sizeof(android_log_header_t))) {
Mark Salyzyn0175b072014-02-26 09:50:16 -080059 return false;
60 }
61
62 struct ucred *cred = NULL;
63
64 struct cmsghdr *cmsg = CMSG_FIRSTHDR(&hdr);
65 while (cmsg != NULL) {
66 if (cmsg->cmsg_level == SOL_SOCKET
67 && cmsg->cmsg_type == SCM_CREDENTIALS) {
68 cred = (struct ucred *)CMSG_DATA(cmsg);
69 break;
70 }
71 cmsg = CMSG_NXTHDR(&hdr, cmsg);
72 }
73
74 if (cred == NULL) {
75 return false;
76 }
77
78 if (cred->uid == getuid()) {
79 // ignore log messages we send to ourself.
80 // Such log messages are often generated by libraries we depend on
81 // which use standard Android logging.
82 return false;
83 }
84
Mark Salyzynb5f6e452015-01-16 13:38:07 -080085 android_log_header_t *header = reinterpret_cast<android_log_header_t *>(buffer);
86 if (/* header->id < LOG_ID_MIN || */ header->id >= LOG_ID_MAX) {
Mark Salyzyn0175b072014-02-26 09:50:16 -080087 return false;
88 }
Mark Salyzyn0175b072014-02-26 09:50:16 -080089
Mark Salyzynb5f6e452015-01-16 13:38:07 -080090 char *msg = ((char *)buffer) + sizeof(android_log_header_t);
91 n -= sizeof(android_log_header_t);
Mark Salyzyn0175b072014-02-26 09:50:16 -080092
Mark Salyzyn22e287d2014-03-21 13:12:16 -070093 // NB: hdr.msg_flags & MSG_TRUNC is not tested, silently passing a
94 // truncated message to the logs.
Mark Salyzyne0fa2912014-04-28 16:39:04 -070095
Mark Salyzynb5f6e452015-01-16 13:38:07 -080096 logbuf->log((log_id_t)header->id, header->realtime,
97 cred->uid, cred->pid, header->tid, msg,
Mark Salyzyn6e2c0f72014-05-02 15:47:24 -070098 ((size_t) n <= USHRT_MAX) ? (unsigned short) n : USHRT_MAX);
Mark Salyzyne0fa2912014-04-28 16:39:04 -070099 reader->notifyNewLog();
Mark Salyzyn0175b072014-02-26 09:50:16 -0800100
101 return true;
102}
103
104int LogListener::getLogSocket() {
Mark Salyzyndfc47e82014-03-24 10:26:47 -0700105 static const char socketName[] = "logdw";
106 int sock = android_get_control_socket(socketName);
107
108 if (sock < 0) {
109 sock = socket_local_server(socketName,
110 ANDROID_SOCKET_NAMESPACE_RESERVED,
111 SOCK_DGRAM);
112 }
113
Mark Salyzyn0175b072014-02-26 09:50:16 -0800114 int on = 1;
115 if (setsockopt(sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)) < 0) {
116 return -1;
117 }
118 return sock;
119}