1 /*
2 * Copyright (C) 2021 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 "TrustyLog.h"
18 #include <private/android_logger.h>
19 #include "LogBuffer.h"
20
21 #include <fcntl.h>
22 #include <sys/stat.h>
23 #include <sys/types.h>
24 #include <unistd.h>
25
26 #define TRUSTY_LINE_BUFFER_SIZE 256
27 static const char trustyprefix[] = "trusty";
28
TrustyLog(LogBuffer * buf,int fdRead)29 TrustyLog::TrustyLog(LogBuffer* buf, int fdRead) : SocketListener(fdRead, false), logbuf(buf) {}
30
create(LogBuffer * buf)31 void TrustyLog::create(LogBuffer* buf) {
32 if (access("/sys/module/trusty_log/parameters/log_size", F_OK)) {
33 /* this device has the old driver which doesn't support poll() */
34 return;
35 }
36
37 int fd = TEMP_FAILURE_RETRY(open("/dev/trusty-log0", O_RDONLY | O_NDELAY | O_CLOEXEC));
38 if (fd >= 0) {
39 TrustyLog* tl = new TrustyLog(buf, fd);
40 if (tl->startListener()) {
41 delete tl;
42 }
43 }
44 }
45
46 /*
47 * Log a message, breaking it into smaller chunks if needed
48 */
LogMsg(const char * msg,size_t len)49 void TrustyLog::LogMsg(const char* msg, size_t len) {
50 char linebuffer[TRUSTY_LINE_BUFFER_SIZE + sizeof(trustyprefix) + 1];
51
52 while (len) {
53 size_t sublen = len;
54 if (sublen > TRUSTY_LINE_BUFFER_SIZE) {
55 sublen = TRUSTY_LINE_BUFFER_SIZE;
56 }
57
58 *linebuffer = ANDROID_LOG_INFO;
59 strcpy(linebuffer + 1, trustyprefix);
60 strncpy(linebuffer + 1 + sizeof(trustyprefix), msg, sublen);
61 timespec tp;
62 clock_gettime(CLOCK_REALTIME, &tp);
63 log_time now = log_time(tp.tv_sec, tp.tv_nsec);
64 // The Log() API appears to want a length that is 1 greater than what's
65 // actually being logged.
66 logbuf->Log(LOG_ID_KERNEL, now, AID_ROOT, 0 /*pid*/, 0 /*tid*/, linebuffer,
67 sizeof(trustyprefix) + sublen + 2);
68 msg += sublen;
69 len -= sublen;
70 }
71 }
72
onDataAvailable(SocketClient * cli)73 bool TrustyLog::onDataAvailable(SocketClient* cli) {
74 char buffer[4096];
75 ssize_t len = 0;
76 bool need_newline = false;
77 for (;;) {
78 ssize_t retval = 0;
79 if (len < (ssize_t)(sizeof(buffer) - 1)) {
80 retval = TEMP_FAILURE_RETRY(
81 read(cli->getSocket(), buffer + len, sizeof(buffer) - 1 - len));
82 }
83 if (retval > 0) {
84 len += retval;
85 }
86 if ((retval <= 0) && (len <= 0)) {
87 // nothing read and nothing to read
88 break;
89 }
90
91 // log the complete lines we have so far
92 char* linestart = buffer;
93 for (;;) {
94 char* lineend = static_cast<char*>(memchr(linestart, '\n', len));
95 if (lineend) {
96 // print one newline-terminated line
97 size_t linelen = lineend - linestart;
98 LogMsg(linestart, linelen);
99 linestart += (linelen + 1); // next line, skipping the newline
100 len -= (linelen + 1);
101 } else if (len >= TRUSTY_LINE_BUFFER_SIZE) {
102 // there was no newline, but there's enough data to print
103 LogMsg(linestart, TRUSTY_LINE_BUFFER_SIZE);
104 linestart += TRUSTY_LINE_BUFFER_SIZE;
105 len -= TRUSTY_LINE_BUFFER_SIZE;
106 } else {
107 if (len) {
108 if (need_newline) {
109 // still no newline after reading more, log what we have
110 // and return
111 LogMsg(linestart, len);
112 return true;
113 }
114 // there's some unterminated data left at the end of the
115 // buffer. Move it to the front and try to append more in
116 // the outer loop.
117 memmove(buffer, linestart, len);
118 need_newline = true;
119 }
120 break;
121 }
122 }
123 }
124 return true;
125 }
126