• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <limits.h>
19  #include <stdio.h>
20  #include <sys/cdefs.h>
21  #include <sys/prctl.h>
22  #include <sys/socket.h>
23  #include <sys/types.h>
24  #include <sys/un.h>
25  #include <unistd.h>
26  
27  #include <cutils/sockets.h>
28  #include <private/android_filesystem_config.h>
29  #include <private/android_logger.h>
30  
31  #include "LogBuffer.h"
32  #include "LogListener.h"
33  #include "LogUtils.h"
34  
LogListener(LogBufferInterface * buf,LogReader * reader)35  LogListener::LogListener(LogBufferInterface* buf, LogReader* reader)
36      : SocketListener(getLogSocket(), false), logbuf(buf), reader(reader) {
37  }
38  
onDataAvailable(SocketClient * cli)39  bool LogListener::onDataAvailable(SocketClient* cli) {
40      static bool name_set;
41      if (!name_set) {
42          prctl(PR_SET_NAME, "logd.writer");
43          name_set = true;
44      }
45  
46      char buffer[sizeof_log_id_t + sizeof(uint16_t) + sizeof(log_time) +
47                  LOGGER_ENTRY_MAX_PAYLOAD];
48      struct iovec iov = { buffer, sizeof(buffer) };
49  
50      alignas(4) char control[CMSG_SPACE(sizeof(struct ucred))];
51      struct msghdr hdr = {
52          NULL, 0, &iov, 1, control, sizeof(control), 0,
53      };
54  
55      int socket = cli->getSocket();
56  
57      // To clear the entire buffer is secure/safe, but this contributes to 1.68%
58      // overhead under logging load. We are safe because we check counts.
59      // memset(buffer, 0, sizeof(buffer));
60      ssize_t n = recvmsg(socket, &hdr, 0);
61      if (n <= (ssize_t)(sizeof(android_log_header_t))) {
62          return false;
63      }
64  
65      struct ucred* cred = NULL;
66  
67      struct cmsghdr* cmsg = CMSG_FIRSTHDR(&hdr);
68      while (cmsg != NULL) {
69          if (cmsg->cmsg_level == SOL_SOCKET &&
70              cmsg->cmsg_type == SCM_CREDENTIALS) {
71              cred = (struct ucred*)CMSG_DATA(cmsg);
72              break;
73          }
74          cmsg = CMSG_NXTHDR(&hdr, cmsg);
75      }
76  
77      struct ucred fake_cred;
78      if (cred == NULL) {
79          cred = &fake_cred;
80          cred->pid = 0;
81          cred->uid = DEFAULT_OVERFLOWUID;
82      }
83  
84      if (cred->uid == AID_LOGD) {
85          // ignore log messages we send to ourself.
86          // Such log messages are often generated by libraries we depend on
87          // which use standard Android logging.
88          return false;
89      }
90  
91      android_log_header_t* header =
92          reinterpret_cast<android_log_header_t*>(buffer);
93      if (/* header->id < LOG_ID_MIN || */ header->id >= LOG_ID_MAX ||
94          header->id == LOG_ID_KERNEL) {
95          return false;
96      }
97  
98      if ((header->id == LOG_ID_SECURITY) &&
99          (!__android_log_security() ||
100           !clientHasLogCredentials(cred->uid, cred->gid, cred->pid))) {
101          return false;
102      }
103  
104      // Check credential validity, acquire corrected details if not supplied.
105      if (cred->pid == 0) {
106          cred->pid = logbuf ? logbuf->tidToPid(header->tid)
107                             : android::tidToPid(header->tid);
108          if (cred->pid == getpid()) {
109              // We expect that /proc/<tid>/ is accessible to self even without
110              // readproc group, so that we will always drop messages that come
111              // from any of our logd threads and their library calls.
112              return false;  // ignore self
113          }
114      }
115      if (cred->uid == DEFAULT_OVERFLOWUID) {
116          uid_t uid =
117              logbuf ? logbuf->pidToUid(cred->pid) : android::pidToUid(cred->pid);
118          if (uid == AID_LOGD) {
119              uid = logbuf ? logbuf->pidToUid(header->tid)
120                           : android::pidToUid(cred->pid);
121          }
122          if (uid != AID_LOGD) cred->uid = uid;
123      }
124  
125      char* msg = ((char*)buffer) + sizeof(android_log_header_t);
126      n -= sizeof(android_log_header_t);
127  
128      // NB: hdr.msg_flags & MSG_TRUNC is not tested, silently passing a
129      // truncated message to the logs.
130  
131      if (logbuf != nullptr) {
132          int res = logbuf->log(
133              (log_id_t)header->id, header->realtime, cred->uid, cred->pid,
134              header->tid, msg,
135              ((size_t)n <= USHRT_MAX) ? (unsigned short)n : USHRT_MAX);
136          if (res > 0 && reader != nullptr) {
137              reader->notifyNewLog();
138          }
139      }
140  
141      return true;
142  }
143  
getLogSocket()144  int LogListener::getLogSocket() {
145      static const char socketName[] = "logdw";
146      int sock = android_get_control_socket(socketName);
147  
148      if (sock < 0) {  // logd started up in init.sh
149          sock = socket_local_server(
150              socketName, ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_DGRAM);
151  
152          int on = 1;
153          if (setsockopt(sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on))) {
154              return -1;
155          }
156      }
157      return sock;
158  }
159