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 <android-base/unique_fd.h>
18 #include <binder/IPCThreadState.h>
19 #include <gtest/gtest.h>
20 #include <poll.h>
21 #include <trusty/metrics/metrics.h>
22 #include <trusty/tipc.h>
23
24 #define TIPC_DEV "/dev/trusty-ipc-dev0"
25 #define CRASHER_PORT "com.android.trusty.metrics.test.crasher"
26
27 namespace android {
28 namespace trusty {
29 namespace metrics {
30
31 using android::base::unique_fd;
32
TriggerCrash()33 static void TriggerCrash() {
34 size_t num_retries = 6;
35 int fd = -1;
36
37 for (size_t i = 0; i < num_retries; i++) {
38 /* It's possible to time out waiting for crasher TA to restart. */
39 fd = tipc_connect(TIPC_DEV, CRASHER_PORT);
40 if (fd >= 0) {
41 break;
42 }
43 }
44
45 unique_fd crasher(fd);
46 ASSERT_GE(crasher, 0);
47
48 int msg = 0;
49 int rc = write(crasher, &msg, sizeof(msg));
50 ASSERT_EQ(rc, sizeof(msg));
51 }
52
53 class TrustyMetricsTest : public TrustyMetrics, public ::testing::Test {
54 public:
TrustyMetricsTest()55 TrustyMetricsTest() : TrustyMetrics(TIPC_DEV) {}
56
HandleCrash(const std::string & app_id)57 virtual void HandleCrash(const std::string& app_id) override { crashed_app_ = app_id; }
58
HandleEventDrop()59 virtual void HandleEventDrop() override { event_drop_count_++; }
60
SetUp()61 virtual void SetUp() override {
62 auto ret = Open();
63 ASSERT_TRUE(ret.ok()) << ret.error();
64
65 /* Drain events (if any) and reset state */
66 DrainEvents();
67 crashed_app_.clear();
68 event_drop_count_ = 0;
69 }
70
DrainEvents()71 void DrainEvents() {
72 while (WaitForEvent(1000 /* 1 second timeout */).ok()) {
73 auto ret = HandleEvent();
74 ASSERT_TRUE(ret.ok()) << ret.error();
75 }
76 }
77
WaitForAndHandleEvent()78 void WaitForAndHandleEvent() {
79 auto ret = WaitForEvent(30000 /* 30 second timeout */);
80 ASSERT_TRUE(ret.ok()) << ret.error();
81
82 ret = HandleEvent();
83 ASSERT_TRUE(ret.ok()) << ret.error();
84 }
85
86 std::string crashed_app_;
87 size_t event_drop_count_;
88 };
89
TEST_F(TrustyMetricsTest,Crash)90 TEST_F(TrustyMetricsTest, Crash) {
91 TriggerCrash();
92 WaitForAndHandleEvent();
93
94 /* Check that no event was dropped. */
95 ASSERT_EQ(event_drop_count_, 0);
96
97 /* Check that correct TA crashed. */
98 ASSERT_EQ(crashed_app_, "36f5b435-5bd3-4526-8b76-200e3a7e79f3:crasher");
99 }
100
TEST_F(TrustyMetricsTest,PollSet)101 TEST_F(TrustyMetricsTest, PollSet) {
102 int binder_fd;
103 int rc = IPCThreadState::self()->setupPolling(&binder_fd);
104 ASSERT_EQ(rc, 0);
105 ASSERT_GE(binder_fd, 0);
106
107 TriggerCrash();
108
109 struct pollfd pfds[] = {
110 {
111 .fd = binder_fd,
112 .events = POLLIN,
113 },
114 {
115 .fd = GetRawFd(),
116 .events = POLLIN,
117 },
118 };
119
120 rc = poll(pfds, 2, 30000 /* 30 second timeout */);
121 /* We expect one event on the metrics fd. */
122 ASSERT_EQ(rc, 1);
123 ASSERT_TRUE(pfds[1].revents & POLLIN);
124
125 auto ret = HandleEvent();
126 ASSERT_TRUE(ret.ok()) << ret.error();
127
128 /* Check that no event was dropped. */
129 ASSERT_EQ(event_drop_count_, 0);
130
131 /* Check that correct TA crashed. */
132 ASSERT_EQ(crashed_app_, "36f5b435-5bd3-4526-8b76-200e3a7e79f3:crasher");
133 }
134
TEST_F(TrustyMetricsTest,EventDrop)135 TEST_F(TrustyMetricsTest, EventDrop) {
136 /* We know the size of the internal event queue is less than this. */
137 size_t num_events = 3;
138
139 ASSERT_EQ(event_drop_count_, 0);
140
141 for (auto i = 0; i < num_events; i++) {
142 TriggerCrash();
143 }
144
145 for (auto i = 0; i < num_events; i++) {
146 WaitForAndHandleEvent();
147 if (event_drop_count_ > 0) {
148 break;
149 }
150 }
151
152 ASSERT_EQ(event_drop_count_, 1);
153 }
154
155 } // namespace metrics
156 } // namespace trusty
157 } // namespace android
158