1 /*
2 * Copyright (C) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "binder_connector.h"
17
18 #include <cstdint>
19 #include <fcntl.h>
20 #include <sys/ioctl.h>
21 #include <sys/mman.h>
22 #include <unistd.h>
23
24 #include "__mutex_base"
25 #include "cerrno"
26 #include "hilog/log_c.h"
27 #include "hilog/log_cpp.h"
28 #include "iosfwd"
29 #include "ipc_debug.h"
30 #include "ipc_types.h"
31 #include "log_tags.h"
32 #include "new"
33 #include "string"
34 #include "sys_binder.h"
35
36 namespace OHOS {
37 #ifdef CONFIG_IPC_SINGLE
38 namespace IPC_SINGLE {
39 #endif
40
41 static constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_ID_IPC, "BinderConnector" };
42 std::mutex BinderConnector::skeletonMutex;
43 constexpr int SZ_1_M = 1048576;
44 constexpr int DOUBLE = 2;
45 static const int IPC_MMAP_SIZE = (SZ_1_M - sysconf(_SC_PAGE_SIZE) * DOUBLE);
46 static const std::string DRIVER_NAME = std::string("/dev/binder");
47 BinderConnector *BinderConnector::instance_ = nullptr;
48
BinderConnector(const std::string & deviceName)49 BinderConnector::BinderConnector(const std::string &deviceName)
50 : driverFD_(-1), vmAddr_(MAP_FAILED), deviceName_(deviceName), version_(0), featureSet_(0)
51 {}
52
~BinderConnector()53 BinderConnector::~BinderConnector()
54 {
55 if (vmAddr_ != MAP_FAILED) {
56 munmap(vmAddr_, IPC_MMAP_SIZE);
57 vmAddr_ = MAP_FAILED;
58 }
59
60 if (driverFD_ >= 0) {
61 close(driverFD_);
62 driverFD_ = -1;
63 }
64 };
65
IsDriverAlive()66 bool BinderConnector::IsDriverAlive()
67 {
68 return driverFD_ >= 0;
69 }
70
OpenDriver()71 bool BinderConnector::OpenDriver()
72 {
73 int fd = open(deviceName_.c_str(), O_RDWR);
74 if (fd < 0) {
75 ZLOGE(LABEL, "%s:fail to open", __func__);
76 #ifndef BUILD_PUBLIC_VERSION
77 ReportEvent(DbinderErrorCode::KERNEL_DRIVER_ERROR, DbinderErrorCode::ERROR_CODE,
78 DbinderErrorCode::OPEN_IPC_DRIVER_FAILURE);
79 #endif
80 return false;
81 }
82 int32_t version = 0;
83 int ret = ioctl(fd, BINDER_VERSION, &version);
84 if (ret != 0) {
85 ZLOGE(LABEL, "Get Binder version failed: %d", errno);
86 close(fd);
87 return false;
88 }
89 if (version != BINDER_CURRENT_PROTOCOL_VERSION) {
90 ZLOGE(LABEL, "Binder version not match! driver version:%d, ipc version:%d",
91 version, BINDER_CURRENT_PROTOCOL_VERSION);
92 close(fd);
93 return false;
94 }
95 uint64_t featureSet = 0;
96 ret = ioctl(fd, BINDER_FEATURE_SET, &featureSet);
97 if (ret != 0) {
98 ZLOGE(LABEL, "Get Binder featureSet failed: %d, disable all enhance feature.", errno);
99 featureSet = 0;
100 }
101 ZLOGD(LABEL, "%s:succ to open, fd=%d", __func__, fd);
102 driverFD_ = fd;
103 vmAddr_ = mmap(0, IPC_MMAP_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, driverFD_, 0);
104 if (vmAddr_ == MAP_FAILED) {
105 ZLOGE(LABEL, "%s:fail to mmap\n", __func__);
106 close(driverFD_);
107 driverFD_ = -1;
108 #ifndef BUILD_PUBLIC_VERSION
109 ReportEvent(DbinderErrorCode::KERNEL_DRIVER_ERROR, DbinderErrorCode::ERROR_CODE,
110 DbinderErrorCode::OPEN_IPC_DRIVER_FAILURE);
111 #endif
112 return false;
113 }
114 version_ = version;
115 featureSet_ = featureSet;
116 return true;
117 }
118
IsAccessTokenSupported()119 bool BinderConnector::IsAccessTokenSupported()
120 {
121 if (driverFD_ > 0) {
122 return featureSet_ & ACCESS_TOKEN_FAETURE_MASK;
123 }
124 return false;
125 }
126
WriteBinder(unsigned long request,void * value)127 int BinderConnector::WriteBinder(unsigned long request, void *value)
128 {
129 int err = -EINTR;
130
131 while (err == -EINTR) {
132 if (ioctl(driverFD_, request, value) >= 0) {
133 err = ERR_NONE;
134 } else {
135 err = -errno;
136 }
137
138 if (err == -EINTR) {
139 ZLOGE(LABEL, "%s:ioctl_binder returned EINTR", __func__);
140 #ifndef BUILD_PUBLIC_VERSION
141 ReportEvent(DbinderErrorCode::KERNEL_DRIVER_ERROR, DbinderErrorCode::ERROR_CODE,
142 DbinderErrorCode::WRITE_IPC_DRIVER_FAILURE);
143 #endif
144 }
145 }
146
147 return err;
148 }
149
ExitCurrentThread(unsigned long request)150 void BinderConnector::ExitCurrentThread(unsigned long request)
151 {
152 if (driverFD_ > 0) {
153 ioctl(driverFD_, request, 0);
154 }
155 }
156
GetInstance()157 BinderConnector *BinderConnector::GetInstance()
158 {
159 if (instance_ == nullptr) {
160 std::lock_guard<std::mutex> lockGuard(skeletonMutex);
161 if (instance_ == nullptr) {
162 auto temp = new (std::nothrow) BinderConnector(DRIVER_NAME);
163 if (temp == nullptr) {
164 ZLOGE(LABEL, "create BinderConnector object failed");
165 return nullptr;
166 }
167 if (!temp->OpenDriver()) {
168 delete temp;
169 temp = nullptr;
170 }
171 instance_ = temp;
172 }
173 }
174
175 return instance_;
176 }
177 #ifdef CONFIG_IPC_SINGLE
178 } // namespace IPC_SINGLE
179 #endif
180 } // namespace OHOS
181