blob: c6b248bdc53b3acfca374dce946aa655f2c0dc8a [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
17#include <sys/socket.h>
18#include <sys/types.h>
19#include <sys/un.h>
20#include <unistd.h>
21
22#include <cutils/sockets.h>
23#include <log/logger.h>
24
25#include "LogListener.h"
26
27LogListener::LogListener(LogBuffer *buf, LogReader *reader)
28 : SocketListener(getLogSocket(), false)
29 , logbuf(buf)
30 , reader(reader)
31{ }
32
33bool LogListener::onDataAvailable(SocketClient *cli) {
34 char buffer[1024];
35 struct iovec iov = { buffer, sizeof(buffer) };
36 memset(buffer, 0, sizeof(buffer));
37
38 char control[CMSG_SPACE(sizeof(struct ucred))];
39 struct msghdr hdr = {
40 NULL,
41 0,
42 &iov,
43 1,
44 control,
45 sizeof(control),
46 0,
47 };
48
49 int socket = cli->getSocket();
50
51 ssize_t n = recvmsg(socket, &hdr, 0);
52 if (n <= (ssize_t) sizeof_log_id_t) {
53 return false;
54 }
55
56 struct ucred *cred = NULL;
57
58 struct cmsghdr *cmsg = CMSG_FIRSTHDR(&hdr);
59 while (cmsg != NULL) {
60 if (cmsg->cmsg_level == SOL_SOCKET
61 && cmsg->cmsg_type == SCM_CREDENTIALS) {
62 cred = (struct ucred *)CMSG_DATA(cmsg);
63 break;
64 }
65 cmsg = CMSG_NXTHDR(&hdr, cmsg);
66 }
67
68 if (cred == NULL) {
69 return false;
70 }
71
72 if (cred->uid == getuid()) {
73 // ignore log messages we send to ourself.
74 // Such log messages are often generated by libraries we depend on
75 // which use standard Android logging.
76 return false;
77 }
78
79 // First log element is always log_id.
80 log_id_t log_id = (log_id_t) *((typeof_log_id_t *) buffer);
81 if (log_id < 0 || log_id >= LOG_ID_MAX) {
82 return false;
83 }
84
85 char *msg = ((char *)buffer) + sizeof_log_id_t;
86 n -= sizeof_log_id_t;
87
88 log_time realtime(msg);
89 msg += sizeof(log_time);
90 n -= sizeof(log_time);
91
92 unsigned short len = n;
93 if (len == n) {
94 logbuf->log(log_id, realtime, cred->uid, cred->pid, msg, len);
95 reader->notifyNewLog();
96 }
97
98 return true;
99}
100
101int LogListener::getLogSocket() {
102 int sock = android_get_control_socket("logdw");
103 int on = 1;
104 if (setsockopt(sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)) < 0) {
105 return -1;
106 }
107 return sock;
108}