• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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