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