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