Marco Nelissen | a8d4298 | 2021-12-02 10:49:52 -0800 | [diff] [blame] | 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> |
Marco Nelissen | 468ce59 | 2022-02-04 15:05:20 -0800 | [diff] [blame] | 24 | #include <unistd.h> |
Marco Nelissen | a8d4298 | 2021-12-02 10:49:52 -0800 | [diff] [blame] | 25 | |
| 26 | #define TRUSTY_LINE_BUFFER_SIZE 256 |
| 27 | static const char trustyprefix[] = "trusty"; |
| 28 | |
| 29 | TrustyLog::TrustyLog(LogBuffer* buf, int fdRead) : SocketListener(fdRead, false), logbuf(buf) {} |
| 30 | |
| 31 | void TrustyLog::create(LogBuffer* buf) { |
Marco Nelissen | 468ce59 | 2022-02-04 15:05:20 -0800 | [diff] [blame] | 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 | |
Marco Nelissen | a8d4298 | 2021-12-02 10:49:52 -0800 | [diff] [blame] | 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 | |
Marco Nelissen | caa341e | 2022-03-03 19:22:16 -0800 | [diff] [blame] | 46 | /* |
| 47 | * Log a message, breaking it into smaller chunks if needed |
| 48 | */ |
| 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 | |
Marco Nelissen | a8d4298 | 2021-12-02 10:49:52 -0800 | [diff] [blame] | 73 | bool TrustyLog::onDataAvailable(SocketClient* cli) { |
| 74 | char buffer[4096]; |
Marco Nelissen | a8d4298 | 2021-12-02 10:49:52 -0800 | [diff] [blame] | 75 | ssize_t len = 0; |
Marco Nelissen | 0e6014f | 2022-06-07 08:25:32 -0700 | [diff] [blame] | 76 | bool need_newline = false; |
Marco Nelissen | a8d4298 | 2021-12-02 10:49:52 -0800 | [diff] [blame] | 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) { |
Marco Nelissen | caa341e | 2022-03-03 19:22:16 -0800 | [diff] [blame] | 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; |
Marco Nelissen | a8d4298 | 2021-12-02 10:49:52 -0800 | [diff] [blame] | 106 | } else { |
| 107 | if (len) { |
Marco Nelissen | 0e6014f | 2022-06-07 08:25:32 -0700 | [diff] [blame] | 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 | } |
Marco Nelissen | a8d4298 | 2021-12-02 10:49:52 -0800 | [diff] [blame] | 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); |
Marco Nelissen | 0e6014f | 2022-06-07 08:25:32 -0700 | [diff] [blame] | 118 | need_newline = true; |
Marco Nelissen | a8d4298 | 2021-12-02 10:49:52 -0800 | [diff] [blame] | 119 | } |
| 120 | break; |
| 121 | } |
| 122 | } |
| 123 | } |
| 124 | return true; |
| 125 | } |