1 /*
2  * Copyright (C) 2022 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 #define LOG_TAG "binderRpcTest"
18 
19 #include <binder/RpcTransportTipcTrusty.h>
20 #include <trusty-gtest.h>
21 #include <trusty_ipc.h>
22 
23 #include "binderRpcTestFixture.h"
24 
25 using android::binder::unique_fd;
26 
27 namespace android {
28 
29 // Destructors need to be defined, even if pure virtual
~ProcessSession()30 ProcessSession::~ProcessSession() {}
31 
32 class TrustyProcessSession : public ProcessSession {
33 public:
~TrustyProcessSession()34     ~TrustyProcessSession() override {}
35 
setCustomExitStatusCheck(std::function<void (int wstatus)>)36     void setCustomExitStatusCheck(std::function<void(int wstatus)> /*f*/) override {
37         LOG_ALWAYS_FATAL("setCustomExitStatusCheck() not supported");
38     }
39 
terminate()40     void terminate() override { LOG_ALWAYS_FATAL("terminate() not supported"); }
41 };
42 
newFactory(RpcSecurity rpcSecurity)43 std::unique_ptr<RpcTransportCtxFactory> BinderRpc::newFactory(RpcSecurity rpcSecurity) {
44     switch (rpcSecurity) {
45         case RpcSecurity::RAW:
46             return RpcTransportCtxFactoryTipcTrusty::make();
47         default:
48             LOG_ALWAYS_FATAL("Unknown RpcSecurity %d", static_cast<int>(rpcSecurity));
49     }
50 }
51 
52 // This creates a new process serving an interface on a certain number of
53 // threads.
createRpcTestSocketServerProcessEtc(const BinderRpcOptions & options)54 std::unique_ptr<ProcessSession> BinderRpc::createRpcTestSocketServerProcessEtc(
55         const BinderRpcOptions& options) {
56     LOG_ALWAYS_FATAL_IF(std::any_of(options.numIncomingConnectionsBySession.begin(),
57                                     options.numIncomingConnectionsBySession.end(),
58                                     [](size_t n) { return n != 0; }),
59                         "Non-zero incoming connections on Trusty");
60 
61     RpcSecurity rpcSecurity = GetParam().security;
62     uint32_t clientVersion = GetParam().clientVersion;
63     uint32_t serverVersion = GetParam().serverVersion;
64 
65     auto ret = std::make_unique<TrustyProcessSession>();
66 
67     status_t status;
68     for (size_t i = 0; i < options.numSessions; i++) {
69         auto session = android::RpcSession::make(newFactory(rpcSecurity));
70 
71         EXPECT_TRUE(session->setProtocolVersion(clientVersion));
72         session->setMaxOutgoingConnections(options.numOutgoingConnections);
73         session->setFileDescriptorTransportMode(options.clientFileDescriptorTransportMode);
74 
75         status = session->setupPreconnectedClient({}, [&]() {
76             auto port = trustyIpcPort(serverVersion);
77             int rc = connect(port.c_str(), IPC_CONNECT_WAIT_FOR_PORT);
78             LOG_ALWAYS_FATAL_IF(rc < 0, "Failed to connect to service: %d", rc);
79             return unique_fd(rc);
80         });
81         if (options.allowConnectFailure && status != OK) {
82             ret->sessions.clear();
83             break;
84         }
85         LOG_ALWAYS_FATAL_IF(status != OK, "Failed to connect to service: %s",
86                             statusToString(status).c_str());
87         ret->sessions.push_back({session, session->getRootObject()});
88     }
89 
90     return ret;
91 }
92 
getTrustyBinderRpcParams()93 static std::vector<BinderRpc::ParamType> getTrustyBinderRpcParams() {
94     std::vector<BinderRpc::ParamType> ret;
95 
96     for (const auto& clientVersion : testVersions()) {
97         for (const auto& serverVersion : testVersions()) {
98             ret.push_back(BinderRpc::ParamType{
99                     .type = SocketType::TIPC,
100                     .security = RpcSecurity::RAW,
101                     .clientVersion = clientVersion,
102                     .serverVersion = serverVersion,
103                     // TODO: should we test both versions here?
104                     .singleThreaded = false,
105                     .noKernel = true,
106             });
107         }
108     }
109 
110     return ret;
111 }
112 
113 INSTANTIATE_TEST_SUITE_P(Trusty, BinderRpc, ::testing::ValuesIn(getTrustyBinderRpcParams()),
114                          BinderRpc::PrintParamInfo);
115 
116 } // namespace android
117 
118 PORT_GTEST(BinderRpcTest, "com.android.trusty.binderRpcTest");
119