• 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 "lmks_server.h"
17 
18 #include <sys/socket.h>
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #include <thread>
22 #include <unistd.h>
23 
24 #include "securec.h"
25 #include "hilog/log.h"
26 
27 namespace OHOS {
28 namespace LMKS {
29 
30 namespace {
31 #ifdef __MUSL__
32 const std::string LMKS_SOCKET_NAME = "/dev/unix/socket/lmks";
33 #else
34 const std::string LMKS_SOCKET_NAME = "/dev/socket/lmks";
35 #endif
36 constexpr uint32_t LISTEN_CLIENTS = 5;          // 5: max num of clients
37 constexpr uint32_t WAIT_DELAY_US = 100 * 1000;  // 100ms
38 
39 constexpr int LMKS_CMD_TARGET = 0;
40 constexpr int LMKS_CMD_PROCPRIO = 1;
41 constexpr int LMKS_CMD_PROCREMOVE = 2;
42 constexpr int LMKS_CMD_PROCPURGE = 3;
43 constexpr uid_t LMKS_ID_ROOT = 0;                  // chown owner
44 constexpr gid_t LMKS_ID_SYSTEM = 1000;             // chown group
45 constexpr mode_t SOCKET_PERM = 0666;               // root system can read and write lmks socket
46 constexpr struct timeval SOCKET_TIMEOUT = {5, 0};  // 5, 0: { 5 sec, 0 msec } for timeout
47 }  // namespace
48 
49 using namespace OHOS::HiviewDFX;
50 static constexpr HiLogLabel LABEL = {LOG_CORE, 0, "LmksServer"};
51 
LmksServer()52 LmksServer::LmksServer() : isStart_(false), socketFd_(-1), socketAddrLen_(0), lmksUtils_(nullptr)
53 {
54     memset_s(&socketAddr_, sizeof(socketAddr_), 0, sizeof(socketAddr_));
55 }
56 
~LmksServer()57 LmksServer::~LmksServer()
58 {
59     CloseSocket();
60 }
61 
StartServer()62 void LmksServer::StartServer()
63 {
64     if (isStart_) {
65         HiLog::Error(LABEL, "Lmks server has started.");
66         return;
67     }
68 
69     if (RegisterSocket() != 0) {
70         HiLog::Error(LABEL, "Register error.");
71         return;
72     }
73 
74     isStart_ = true;
75     if (lmksUtils_ == nullptr) {
76         lmksUtils_ = std::make_shared<LmksUtils>();
77     }
78 
79     while (1) {
80         int connectFd = WaitConnection();
81         if (connectFd < 0) {
82             usleep(WAIT_DELAY_US);
83             continue;
84         }
85 
86         LMKS_PACKET cmds;
87         int len = RecvSocketMessage(connectFd, (void *)cmds, sizeof(cmds));
88         if (len <= 0) {
89             HiLog::Error(LABEL, "Failed to read socket message, len %{public}d", len);
90             close(connectFd);
91             continue;
92         }
93 
94         ProcessMessage(connectFd, cmds, len);
95     }
96 
97     // close socket
98     CloseSocket();
99 }
100 
RegisterSocket()101 int LmksServer::RegisterSocket()
102 {
103     if (socketFd_ > 0) {
104         HiLog::Error(LABEL, "Lmks server has already register.");
105         return -1;
106     }
107 
108     socketFd_ = socket(AF_LOCAL, SOCK_SEQPACKET, 0);
109     if (socketFd_ < 0) {
110         HiLog::Error(LABEL, "Failed to create socket, err %{public}s", strerror(errno));
111         return (-errno);
112     }
113 
114     if (memset_s(&socketAddr_, sizeof(socketAddr_), 0, sizeof(socketAddr_)) != 0) {
115         HiLog::Error(LABEL, "Failed to memset socket addr, err %{public}s", strerror(errno));
116         return (-errno);
117     }
118 
119     if (strcpy_s(socketAddr_.sun_path, sizeof(socketAddr_.sun_path), LMKS_SOCKET_NAME.c_str()) != 0) {
120         HiLog::Error(LABEL, "Failed to snprint32_tf_s socket addr, err %{public}s", strerror(errno));
121         return (-errno);
122     }
123 
124     socketAddr_.sun_family = AF_LOCAL;
125     socketAddrLen_ = offsetof(struct sockaddr_un, sun_path) + LMKS_SOCKET_NAME.length() + 1;
126 
127     if ((unlink(socketAddr_.sun_path) != 0) && (errno != ENOENT)) {
128         HiLog::Error(LABEL, "Failed to unlink, err %{public}s", strerror(errno));
129         return (-errno);
130     }
131 
132     int reuseAddr = 0;
133     if ((setsockopt(socketFd_, SOL_SOCKET, SO_REUSEADDR, &reuseAddr, sizeof(reuseAddr)) != 0) ||
134         (setsockopt(socketFd_, SOL_SOCKET, SO_RCVTIMEO, &SOCKET_TIMEOUT, sizeof(SOCKET_TIMEOUT)) != 0) ||
135         (setsockopt(socketFd_, SOL_SOCKET, SO_SNDTIMEO, &SOCKET_TIMEOUT, sizeof(SOCKET_TIMEOUT)) != 0)) {
136         HiLog::Error(LABEL, "Failed to set opt of socket %d, err %{public}s", socketFd_, strerror(errno));
137         return (-errno);
138     }
139 
140     if (bind(socketFd_, reinterpret_cast<struct sockaddr *>(&socketAddr_), socketAddrLen_) < 0) {
141         HiLog::Error(LABEL, "Failed to bind socket fd %d, err %{public}s", socketFd_, strerror(errno));
142         return (-errno);
143     }
144 
145     if (chown(socketAddr_.sun_path, LMKS_ID_ROOT, LMKS_ID_SYSTEM)) {
146         HiLog::Error(LABEL, "Failed to chown socket. err %{public}s", strerror(errno));
147         return (-errno);
148     }
149 
150     if (chmod(socketAddr_.sun_path, SOCKET_PERM)) {
151         HiLog::Error(LABEL, "Failed to chmod socket. err %{public}s", strerror(errno));
152         if ((unlink(socketAddr_.sun_path) != 0) && (errno != ENOENT)) {
153             HiLog::Error(LABEL, "Failed to unlink, err %{public}s", strerror(errno));
154         }
155         return (-errno);
156     }
157 
158     if (listen(socketFd_, LISTEN_CLIENTS) != 0) {
159         HiLog::Error(LABEL, "Failed to listen socket fd %d, err %{public}s", socketFd_, strerror(errno));
160         return (-errno);
161     }
162 
163     return 0;
164 }
165 
WaitConnection()166 int LmksServer::WaitConnection()
167 {
168     if (socketFd_ < 0) {
169         HiLog::Error(LABEL, "lmks server not register.");
170         return -1;
171     }
172 
173     struct sockaddr_un clientAddr;
174     socklen_t clientLen = sizeof(clientAddr);
175 
176     if (memset_s(&clientAddr, clientLen, 0, clientLen) != 0) {
177         HiLog::Warn(LABEL, "Failed to memset client addr, err %{public}s", strerror(errno));
178     }
179 
180     int connFd = accept(socketFd_, reinterpret_cast<struct sockaddr *>(&clientAddr), &clientLen);
181     if (connFd < 0) {
182         HiLog::Warn(LABEL, "Accept warning %{public}s", strerror(errno));
183         return (-errno);
184     }
185 
186     if ((setsockopt(connFd, SOL_SOCKET, SO_RCVTIMEO, &SOCKET_TIMEOUT, sizeof(SOCKET_TIMEOUT)) < 0) ||
187         (setsockopt(connFd, SOL_SOCKET, SO_SNDTIMEO, &SOCKET_TIMEOUT, sizeof(SOCKET_TIMEOUT)) < 0)) {
188         HiLog::Error(LABEL, "Failed to set opt of Connection %d, err %{public}s", connFd, strerror(errno));
189         close(connFd);
190         return (-errno);
191     }
192 
193     return connFd;
194 }
195 
CloseSocket()196 void LmksServer::CloseSocket()
197 {
198     if (socketFd_ >= 0) {
199         HiLog::Debug(LABEL, "Closed socket with fd %d", socketFd_);
200         close(socketFd_);
201         socketFd_ = -1;
202     }
203 }
204 
SendSocketMessage(int connectFd,const void * buf,int len)205 int LmksServer::SendSocketMessage(int connectFd, const void *buf, int len)
206 {
207     if (connectFd < 0 || len <= 0 || buf == nullptr) {
208         HiLog::Error(LABEL, "Invalid args: connect %d, len %d, buf might be nullptr", connectFd, len);
209         return -1;
210     }
211 
212     ssize_t rLen = TEMP_FAILURE_RETRY(send(connectFd, buf, len, 0));
213     if (rLen < 0) {
214         HiLog::Error(LABEL, "Send message from fd %d error %zd: %s", connectFd, rLen, strerror(errno));
215         return (-errno);
216     }
217 
218     return rLen;
219 }
220 
RecvSocketMessage(int connectFd,void * buf,int len)221 int LmksServer::RecvSocketMessage(int connectFd, void *buf, int len)
222 {
223     if (connectFd < 0 || len <= 0 || buf == nullptr) {
224         HiLog::Error(LABEL, "Invalid args: connect %d, len %d, buf might be nullptr", connectFd, len);
225         return -1;
226     }
227 
228     if (memset_s(buf, len, 0, len) != 0) {
229         HiLog::Error(LABEL, "Failed to memset read buf err %{public}s", strerror(errno));
230         return (-errno);
231     }
232 
233     ssize_t rLen = TEMP_FAILURE_RETRY(recv(connectFd, buf, len, 0));
234     if (rLen < 0) {
235         HiLog::Error(LABEL, "Read message from fd %d error %zd: %s", connectFd, rLen, strerror(errno));
236         return (-errno);
237     }
238 
239     return rLen;
240 }
241 
ProcessMessage(int connectFd,LMKS_PACKET cmds,int len)242 void LmksServer::ProcessMessage(int connectFd, LMKS_PACKET cmds, int len)
243 {
244     if (!isStart_ || (lmksUtils_ == nullptr)) {
245         HiLog::Error(
246             LABEL, "Lmks server not start isStart_ %{public}d lmksUtils_%{public}p", isStart_, lmksUtils_.get());
247         close(connectFd);
248         return;
249     }
250 
251     if (connectFd < 0 || len <= 0) {
252         HiLog::Error(LABEL, "Invalid args: len %d, connectFd %d", len, connectFd);
253         close(connectFd);
254         return;
255     }
256 
257     int ret = -1;
258     pid_t pid = 0;
259 
260     switch (cmds[0]) {
261         case LMKS_CMD_TARGET:
262             HiLog::Info(LABEL, "ProcessMessage LMKS_CMD_TARGET ");
263             break;
264         case LMKS_CMD_PROCPRIO:
265             HiLog::Info(LABEL, "ProcessMessage LMKS_CMD_PROCPRIO");
266             break;
267         case LMKS_CMD_PROCREMOVE:
268             HiLog::Info(LABEL, "ProcessMessage LMKS_CMD_PROCREMOVE");
269             pid = cmds[1];
270             ret = lmksUtils_->RemoveProcess(pid);
271             if (SendSocketMessage(connectFd, &ret, sizeof(ret)) <= 0) {
272                 HiLog::Error(LABEL, "Failed to return the result of remove process");
273             }
274             break;
275         case LMKS_CMD_PROCPURGE:
276             HiLog::Info(LABEL, "ProcessMessage LMKS_CMD_PROCPURGE");
277             break;
278         default:
279             HiLog::Error(LABEL, "Wrong cmd %d", cmds[0]);
280             break;
281     }
282 
283     // close connect fd.
284     close(connectFd);
285 }
286 }  // namespace LMKS
287 }  // namespace OHOS
288