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 <chre.h>
18
19 #include <pb_decode.h>
20 #include <cinttypes>
21
22 #include "chre/util/nanoapp/log.h"
23 #include "chre/util/time.h"
24 #include "permission_test.nanopb.h"
25 #include "send_message.h"
26
27 #define LOG_TAG "[PermissionTest]"
28
29 /**
30 * This nanoapp is compiled with the ability to refer to permission gated APIs
31 * but doesn't actually declare permissions to use them. Its purpose is to
32 * validate the permission gated APIs always return false for any of its
33 * requests to ensure CHRE implementations are validating nanoapp permissions
34 * prior to accepting a nanoapp request.
35 */
36
37 namespace chre {
38 namespace {
39
40 constexpr Nanoseconds kGnssMinInterval = Seconds(1);
41
checkAudioApis(uint32_t hostEndpointId)42 void checkAudioApis(uint32_t hostEndpointId) {
43 struct chreAudioSource audioSource;
44 for (uint32_t i = 0; chreAudioGetSource(i, &audioSource); i++) {
45 if (chreAudioConfigureSource(i, true /* enable */,
46 audioSource.minBufferDuration,
47 audioSource.minBufferDuration)) {
48 test_shared::sendTestResultWithMsgToHost(
49 hostEndpointId, permission_test_MessageType_TEST_RESULT,
50 false /* success */, "Configured audio without audio permission");
51 }
52
53 // TODO(b/174590023): Check chreAudioGetStatus once it's supported by our
54 // CHRE versions.
55 }
56 }
57
checkGnssApis(uint32_t hostEndpointId)58 void checkGnssApis(uint32_t hostEndpointId) {
59 if (chreGnssLocationSessionStartAsync(kGnssMinInterval.toRawNanoseconds(),
60 kGnssMinInterval.toRawNanoseconds(),
61 nullptr /* cookie */)) {
62 test_shared::sendTestResultWithMsgToHost(
63 hostEndpointId, permission_test_MessageType_TEST_RESULT,
64 false /* success */,
65 "Requested GNSS location without the GNSS permission");
66 }
67
68 if (chreGnssMeasurementSessionStartAsync(kGnssMinInterval.toRawNanoseconds(),
69 nullptr /* cookie */)) {
70 test_shared::sendTestResultWithMsgToHost(
71 hostEndpointId, permission_test_MessageType_TEST_RESULT,
72 false /* success */,
73 "Requested GNSS measurements without the GNSS permission");
74 }
75
76 if (chreGnssConfigurePassiveLocationListener(true /* enable */)) {
77 test_shared::sendTestResultWithMsgToHost(
78 hostEndpointId, permission_test_MessageType_TEST_RESULT,
79 false /* success */,
80 "Requested GNSS passive locations without the GNSS permission");
81 }
82 }
83
checkWifiApis(uint32_t hostEndpointId)84 void checkWifiApis(uint32_t hostEndpointId) {
85 if (chreWifiConfigureScanMonitorAsync(true /* enable */,
86 nullptr /* cookie */)) {
87 test_shared::sendTestResultWithMsgToHost(
88 hostEndpointId, permission_test_MessageType_TEST_RESULT,
89 false /* success */,
90 "Requested WiFi scan monitor without WiFi permission");
91 }
92
93 if (chreWifiRequestScanAsyncDefault(nullptr /* cookie */)) {
94 test_shared::sendTestResultWithMsgToHost(
95 hostEndpointId, permission_test_MessageType_TEST_RESULT,
96 false /* success */, "Requested WiFi scan without WiFi permission");
97 }
98
99 // RTT ranging not included in WiFi test because it requires a valid AP to
100 // request which can't be obtained due to invalid permissions.
101 }
102
checkWwanApis(uint32_t hostEndpointId)103 void checkWwanApis(uint32_t hostEndpointId) {
104 if (chreWwanGetCellInfoAsync(nullptr /* cookie */)) {
105 test_shared::sendTestResultWithMsgToHost(
106 hostEndpointId, permission_test_MessageType_TEST_RESULT,
107 false /* success */, "Requested cell info without WWAN permission");
108 }
109 }
110
111 // Call APIs that require permissions and verify that they all refuse requests
112 // from this nanoapp since it has no permissions.
checkPermissionGatedApis(uint32_t hostEndpointId)113 void checkPermissionGatedApis(uint32_t hostEndpointId) {
114 checkAudioApis(hostEndpointId);
115 checkGnssApis(hostEndpointId);
116 checkWifiApis(hostEndpointId);
117 checkWwanApis(hostEndpointId);
118 }
119
handleMessageFromHost(uint32_t senderInstanceId,const chreMessageFromHostData * hostData)120 void handleMessageFromHost(uint32_t senderInstanceId,
121 const chreMessageFromHostData *hostData) {
122 bool success = false;
123 uint32_t messageType = hostData->messageType;
124 if (senderInstanceId != CHRE_INSTANCE_ID) {
125 LOGE("Incorrect sender instance id: %" PRIu32, senderInstanceId);
126 } else if (messageType != permission_test_MessageType_TEST_COMMAND) {
127 LOGE("Invalid message type %" PRIu32, messageType);
128 } else {
129 // Method will abort if any failures are encountered.
130 checkPermissionGatedApis(hostData->hostEndpoint);
131 success = true;
132 }
133
134 test_shared::sendTestResultWithMsgToHost(
135 hostData->hostEndpoint,
136 permission_test_MessageType_TEST_RESULT /* messageType */, success,
137 nullptr /* errMessage */);
138 }
139
140 } // anonymous namespace
141
nanoappHandleEvent(uint32_t senderInstanceId,uint16_t eventType,const void * eventData)142 extern "C" void nanoappHandleEvent(uint32_t senderInstanceId,
143 uint16_t eventType, const void *eventData) {
144 if (eventType == CHRE_EVENT_MESSAGE_FROM_HOST) {
145 handleMessageFromHost(
146 senderInstanceId,
147 static_cast<const chreMessageFromHostData *>(eventData));
148 } else {
149 LOGW("Got unknown event type from senderInstanceId %" PRIu32
150 " and with eventType %" PRIu16,
151 senderInstanceId, eventType);
152 }
153 }
154
nanoappStart(void)155 extern "C" bool nanoappStart(void) {
156 return true;
157 }
158
nanoappEnd(void)159 extern "C" void nanoappEnd(void) {}
160
161 } // namespace chre
162