1 /*
2 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this list of
9 * conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12 * of conditions and the following disclaimer in the documentation and/or other materials
13 * provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16 * to endorse or promote products derived from this software without specific prior written
17 * permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include "syscall_pub.h"
33 #include "stdlib.h"
34 #include "fs/file.h"
35 #include "los_process_pri.h"
36 #include "los_signal.h"
37 #include "los_syscall.h"
38 #include "los_vm_map.h"
39 #include "user_copy.h"
40
41 #ifdef LOSCFG_NET_LWIP_SACK
42 #include "lwip/sockets.h"
43
44 #define SOCKET_U2K(s) \
45 do { \
46 s = GetAssociatedSystemFd(s); \
47 if (s == VFS_ERROR) { \
48 set_errno(EBADF); \
49 return -get_errno(); \
50 } \
51 } while (0)
52
53 #define SOCKET_K2U(s) \
54 do { \
55 int fd = AllocAndAssocProcessFd(s, MIN_START_FD); \
56 if (fd == -1) { \
57 closesocket(s); \
58 set_errno(EMFILE); \
59 s = -EMFILE; \
60 } else { \
61 s = fd; \
62 } \
63 } while (0)
64
SysSocket(int domain,int type,int protocol)65 int SysSocket(int domain, int type, int protocol)
66 {
67 int ret;
68
69 ret = socket(domain, type, protocol);
70 if (ret == -1) {
71 return -get_errno();
72 }
73
74 SOCKET_K2U(ret);
75 return ret;
76 }
77
SysBind(int s,const struct sockaddr * name,socklen_t namelen)78 int SysBind(int s, const struct sockaddr *name, socklen_t namelen)
79 {
80 int ret;
81
82 SOCKET_U2K(s);
83 CHECK_ASPACE(name, namelen);
84
85 DUP_FROM_USER(name, namelen);
86
87 if (name == NULL) {
88 set_errno(EFAULT);
89 ret = -1;
90 } else {
91 ret = bind(s, name, namelen);
92 }
93 FREE_DUP(name);
94 if (ret == -1) {
95 return -get_errno();
96 }
97
98 return ret;
99 }
100
SysConnect(int s,const struct sockaddr * name,socklen_t namelen)101 int SysConnect(int s, const struct sockaddr *name, socklen_t namelen)
102 {
103 int ret;
104
105 SOCKET_U2K(s);
106 CHECK_ASPACE(name, namelen);
107
108 DUP_FROM_USER(name, namelen);
109
110 if (name == NULL) {
111 set_errno(EFAULT);
112 ret = -1;
113 } else {
114 ret = connect(s, name, namelen);
115 }
116 FREE_DUP(name);
117 if (ret == -1) {
118 return -get_errno();
119 }
120
121 return ret;
122 }
123
SysListen(int sockfd,int backlog)124 int SysListen(int sockfd, int backlog)
125 {
126 int ret;
127
128 SOCKET_U2K(sockfd);
129 ret = listen(sockfd, backlog);
130 if (ret == -1) {
131 return -get_errno();
132 }
133
134 return ret;
135 }
136
SysAccept(int socket,struct sockaddr * address,socklen_t * addressLen)137 int SysAccept(int socket, struct sockaddr *address,
138 socklen_t *addressLen)
139 {
140 int ret;
141
142 SOCKET_U2K(socket);
143
144 CHECK_ASPACE(addressLen, sizeof(socklen_t));
145 CPY_FROM_USER(addressLen);
146
147 CHECK_ASPACE(address, LEN(addressLen));
148 DUP_FROM_USER_NOCOPY(address, LEN(addressLen));
149
150 ret = accept(socket, address, addressLen);
151 if (ret == -1) {
152 FREE_DUP(address);
153 return -get_errno();
154 }
155
156 CPY_TO_USER(addressLen, close(ret); FREE_DUP(address));
157 DUP_TO_USER(address, LEN(addressLen), close(ret); FREE_DUP(address));
158 FREE_DUP(address);
159
160 SOCKET_K2U(ret);
161 return ret;
162 }
163
SysGetSockName(int s,struct sockaddr * name,socklen_t * namelen)164 int SysGetSockName(int s, struct sockaddr *name, socklen_t *namelen)
165 {
166 int ret;
167
168 SOCKET_U2K(s);
169
170 CHECK_ASPACE(namelen, sizeof(socklen_t));
171 CPY_FROM_USER(namelen);
172
173 CHECK_ASPACE(name, LEN(namelen));
174 DUP_FROM_USER_NOCOPY(name, LEN(namelen));
175
176 if (name == NULL || namelen == NULL) {
177 set_errno(EFAULT);
178 ret = -1;
179 } else {
180 ret = getsockname(s, name, namelen);
181 }
182 if (ret == -1) {
183 FREE_DUP(name);
184 return -get_errno();
185 }
186
187 CPY_TO_USER(namelen, FREE_DUP(name));
188 DUP_TO_USER(name, LEN(namelen), FREE_DUP(name));
189 FREE_DUP(name);
190 return ret;
191 }
192
SysGetPeerName(int s,struct sockaddr * name,socklen_t * namelen)193 int SysGetPeerName(int s, struct sockaddr *name, socklen_t *namelen)
194 {
195 int ret;
196
197 SOCKET_U2K(s);
198
199 CHECK_ASPACE(namelen, sizeof(socklen_t));
200 CPY_FROM_USER(namelen);
201
202 CHECK_ASPACE(name, LEN(namelen));
203 DUP_FROM_USER_NOCOPY(name, LEN(namelen));
204
205 if (name == NULL || namelen == NULL) {
206 set_errno(EFAULT);
207 ret = -1;
208 } else {
209 ret = getpeername(s, name, namelen);
210 }
211 if (ret == -1) {
212 FREE_DUP(name);
213 return -get_errno();
214 }
215
216 CPY_TO_USER(namelen, FREE_DUP(name));
217 DUP_TO_USER(name, LEN(namelen), FREE_DUP(name));
218 FREE_DUP(name);
219 return ret;
220 }
221
SysSend(int s,const void * dataptr,size_t size,int flags)222 ssize_t SysSend(int s, const void *dataptr, size_t size, int flags)
223 {
224 int ret;
225
226 SOCKET_U2K(s);
227 CHECK_ASPACE(dataptr, size);
228
229 DUP_FROM_USER(dataptr, size);
230
231 if (dataptr == NULL) {
232 set_errno(EFAULT);
233 ret = -1;
234 } else {
235 ret = send(s, dataptr, size, flags);
236 }
237 FREE_DUP(dataptr);
238 if (ret == -1) {
239 return -get_errno();
240 }
241
242 return ret;
243 }
244
SysSendTo(int s,const void * dataptr,size_t size,int flags,const struct sockaddr * to,socklen_t tolen)245 ssize_t SysSendTo(int s, const void *dataptr, size_t size, int flags,
246 const struct sockaddr *to, socklen_t tolen)
247 {
248 int ret;
249
250 SOCKET_U2K(s);
251 CHECK_ASPACE(dataptr, size);
252 CHECK_ASPACE(to, tolen);
253
254 DUP_FROM_USER(dataptr, size);
255 DUP_FROM_USER(to, tolen, FREE_DUP(dataptr));
256
257 if (dataptr == NULL) {
258 set_errno(EFAULT);
259 ret = -1;
260 } else {
261 ret = sendto(s, dataptr, size, flags, to, tolen);
262 }
263 FREE_DUP(dataptr);
264 FREE_DUP(to);
265 if (ret == -1) {
266 return -get_errno();
267 }
268
269 return ret;
270 }
271
SysRecv(int socket,void * buffer,size_t length,int flags)272 ssize_t SysRecv(int socket, void *buffer, size_t length, int flags)
273 {
274 int ret;
275
276 SOCKET_U2K(socket);
277 CHECK_ASPACE(buffer, length);
278
279 DUP_FROM_USER_NOCOPY(buffer, length);
280
281 if (buffer == NULL) {
282 set_errno(EFAULT);
283 ret = -1;
284 } else {
285 ret = recv(socket, buffer, length, flags);
286 }
287 if (ret == -1) {
288 FREE_DUP(buffer);
289 return -get_errno();
290 }
291
292 DUP_TO_USER(buffer, ret, FREE_DUP(buffer));
293 FREE_DUP(buffer);
294 return ret;
295 }
296
SysRecvFrom(int socket,void * buffer,size_t length,int flags,struct sockaddr * address,socklen_t * addressLen)297 ssize_t SysRecvFrom(int socket, void *buffer, size_t length,
298 int flags, struct sockaddr *address,
299 socklen_t *addressLen)
300 {
301 int ret;
302
303 SOCKET_U2K(socket);
304 CHECK_ASPACE(buffer, length);
305
306 CHECK_ASPACE(addressLen, sizeof(socklen_t));
307 CPY_FROM_USER(addressLen);
308
309 CHECK_ASPACE(address, LEN(addressLen));
310 DUP_FROM_USER_NOCOPY(address, LEN(addressLen));
311
312 DUP_FROM_USER_NOCOPY(buffer, length, FREE_DUP(address));
313
314 if (buffer == NULL || (address != NULL && addressLen == NULL)) {
315 set_errno(EFAULT);
316 ret = -1;
317 } else {
318 ret = recvfrom(socket, buffer, length, flags, address, addressLen);
319 }
320 if (ret == -1) {
321 FREE_DUP(address);
322 FREE_DUP(buffer);
323 return -get_errno();
324 }
325
326 CPY_TO_USER(addressLen, FREE_DUP(address); FREE_DUP(buffer));
327 DUP_TO_USER(address, LEN(addressLen), FREE_DUP(address); FREE_DUP(buffer));
328 DUP_TO_USER(buffer, ret, FREE_DUP(address); FREE_DUP(buffer));
329 FREE_DUP(address);
330 FREE_DUP(buffer);
331 return ret;
332 }
333
SysShutdown(int socket,int how)334 int SysShutdown(int socket, int how)
335 {
336 int ret;
337
338 SOCKET_U2K(socket);
339 ret = shutdown(socket, how);
340 if (ret == -1) {
341 return -get_errno();
342 }
343
344 return ret;
345 }
346
SysSetSockOpt(int socket,int level,int optName,const void * optValue,socklen_t optLen)347 int SysSetSockOpt(int socket, int level, int optName,
348 const void *optValue, socklen_t optLen)
349 {
350 int ret;
351
352 SOCKET_U2K(socket);
353 CHECK_ASPACE(optValue, optLen);
354
355 DUP_FROM_USER(optValue, optLen);
356 ret = setsockopt(socket, level, optName, optValue, optLen);
357 FREE_DUP(optValue);
358 if (ret == -1) {
359 return -get_errno();
360 }
361
362 return ret;
363 }
364
SysGetSockOpt(int sockfd,int level,int optName,void * optValue,socklen_t * optLen)365 int SysGetSockOpt(int sockfd, int level, int optName,
366 void *optValue, socklen_t *optLen)
367 {
368 int ret;
369
370 SOCKET_U2K(sockfd);
371
372 CHECK_ASPACE(optLen, sizeof(socklen_t));
373 CPY_FROM_USER(optLen);
374
375 CHECK_ASPACE(optValue, LEN(optLen));
376 DUP_FROM_USER_NOCOPY(optValue, LEN(optLen));
377
378 if (optLen == NULL) {
379 set_errno(EFAULT);
380 ret = -1;
381 } else {
382 ret = getsockopt(sockfd, level, optName, optValue, optLen);
383 }
384 if (ret == -1) {
385 FREE_DUP(optValue);
386 return -get_errno();
387 }
388
389 CPY_TO_USER(optLen, FREE_DUP(optValue));
390 DUP_TO_USER(optValue, LEN(optLen), FREE_DUP(optValue));
391 FREE_DUP(optValue);
392 return ret;
393 }
394
SysSendMsg(int s,const struct msghdr * message,int flags)395 ssize_t SysSendMsg(int s, const struct msghdr *message, int flags)
396 {
397 int ret;
398
399 SOCKET_U2K(s);
400
401 CHECK_ASPACE(message, sizeof(struct msghdr));
402 CPY_FROM_CONST_USER(struct msghdr, message);
403
404 if (message && message->msg_iovlen > IOV_MAX) {
405 set_errno(EMSGSIZE);
406 return -get_errno();
407 }
408
409 CHECK_FIELD_ASPACE(message, msg_name, message->msg_namelen);
410 CHECK_FIELD_ASPACE(message, msg_iov, message->msg_iovlen * sizeof(struct iovec));
411 CHECK_FIELD_ASPACE(message, msg_control, message->msg_controllen);
412
413 DUP_FIELD_FROM_USER(message, msg_iov, message->msg_iovlen * sizeof(struct iovec));
414 CHECK_ARRAY_FIELD_ASPACE(message, msg_iov, message->msg_iovlen, iov_base, iov_len,
415 FREE_DUP_FIELD(message, msg_iov));
416 DUP_FIELD_FROM_USER(message, msg_name, message->msg_namelen,
417 FREE_DUP_FIELD(message, msg_iov));
418 DUP_FIELD_FROM_USER(message, msg_control, message->msg_controllen,
419 FREE_DUP_FIELD(message, msg_iov);
420 FREE_DUP_FIELD(message, msg_name));
421 DUP_ARRAY_FIELD_FROM_USER(message, msg_iov, message->msg_iovlen, iov_base, iov_len,
422 FREE_DUP_FIELD(message, msg_control);
423 FREE_DUP_FIELD(message, msg_iov);
424 FREE_DUP_FIELD(message, msg_name));
425
426 if (message == NULL) {
427 set_errno(EFAULT);
428 ret = -1;
429 } else {
430 ret = sendmsg(s, message, flags);
431 }
432 FREE_DUP_ARRAY_FIELD(message, msg_iov, message->msg_iovlen, iov_base);
433 FREE_DUP_FIELD(message, msg_control);
434 FREE_DUP_FIELD(message, msg_iov);
435 FREE_DUP_FIELD(message, msg_name);
436 if (ret == -1) {
437 return -get_errno();
438 }
439
440 return ret;
441 }
442
SysRecvMsg(int s,struct msghdr * message,int flags)443 ssize_t SysRecvMsg(int s, struct msghdr *message, int flags)
444 {
445 int ret;
446
447 SOCKET_U2K(s);
448
449 CHECK_ASPACE(message, sizeof(struct msghdr));
450 CPY_FROM_NONCONST_USER(message);
451
452 if (message && message->msg_iovlen > IOV_MAX) {
453 set_errno(EMSGSIZE);
454 return -get_errno();
455 }
456
457 CHECK_FIELD_ASPACE(message, msg_name, message->msg_namelen);
458 CHECK_FIELD_ASPACE(message, msg_iov, message->msg_iovlen * sizeof(struct iovec));
459 CHECK_FIELD_ASPACE(message, msg_control, message->msg_controllen);
460
461 DUP_FIELD_FROM_USER(message, msg_iov, message->msg_iovlen * sizeof(struct iovec));
462 CHECK_ARRAY_FIELD_ASPACE(message, msg_iov, message->msg_iovlen, iov_base, iov_len,
463 FREE_DUP_FIELD(message, msg_iov));
464 DUP_FIELD_FROM_USER_NOCOPY(message, msg_name, message->msg_namelen,
465 FREE_DUP_FIELD(message, msg_iov));
466 DUP_FIELD_FROM_USER_NOCOPY(message, msg_control, message->msg_controllen,
467 FREE_DUP_FIELD(message, msg_iov);
468 FREE_DUP_FIELD(message, msg_name));
469 DUP_ARRAY_FIELD_FROM_USER_NOCOPY(message, msg_iov, message->msg_iovlen, iov_base, iov_len,
470 FREE_DUP_FIELD(message, msg_control);
471 FREE_DUP_FIELD(message, msg_iov);
472 FREE_DUP_FIELD(message, msg_name));
473
474 if (message == NULL) {
475 set_errno(EFAULT);
476 ret = -1;
477 } else {
478 ret = recvmsg(s, message, flags);
479 }
480 if (ret == -1) {
481 goto OUT;
482 }
483
484 CPY_TO_USER(message, ret = -1; goto OUT);
485 DUP_FIELD_TO_USER(message, msg_control, message->msg_controllen, ret = -1; goto OUT);
486 DUP_FIELD_TO_USER(message, msg_iov, message->msg_iovlen * sizeof(struct iovec), ret = -1; goto OUT);
487 DUP_FIELD_TO_USER(message, msg_name, message->msg_namelen, ret = -1; goto OUT);
488 DUP_ARRAY_FIELD_TO_USER(message, msg_iov, message->msg_iovlen, iov_base, iov_len, ret = -1; goto OUT);
489 OUT:
490 FREE_DUP_ARRAY_FIELD(message, msg_iov, message->msg_iovlen, iov_base);
491 FREE_DUP_FIELD(message, msg_control);
492 FREE_DUP_FIELD(message, msg_iov);
493 FREE_DUP_FIELD(message, msg_name);
494 return (ret == -1) ? -get_errno() : ret;
495 }
496
497 #endif
498