[SAL] Update SAL,Add socketpair sendmsg recvmsg function (#8293)

This commit is contained in:
rcitachi
2023-11-28 13:56:06 +08:00
committed by GitHub
parent 265b79d953
commit c06f4e98fc
13 changed files with 710 additions and 284 deletions
+223 -2
View File
@@ -3535,6 +3535,150 @@ static int netflags_muslc_2_lwip(int flags)
return flgs;
}
#ifdef ARCH_MM_MMU
static int copy_msghdr_from_user(struct msghdr *kmsg, struct msghdr *umsg,
struct iovec **out_iov, void **out_msg_control)
{
size_t iovs_size;
struct iovec *uiov, *kiov;
size_t iovs_buffer_size = 0;
void *iovs_buffer;
if (!lwp_user_accessable(umsg, sizeof(*umsg)))
{
return -EFAULT;
}
lwp_get_from_user(kmsg, umsg, sizeof(*kmsg));
iovs_size = sizeof(*kmsg->msg_iov) * kmsg->msg_iovlen;
if (!lwp_user_accessable(kmsg->msg_iov, iovs_size))
{
return -EFAULT;
}
/* user and kernel */
kiov = kmem_get(iovs_size * 2);
if (!kiov)
{
return -ENOMEM;
}
uiov = (void *)kiov + iovs_size;
lwp_get_from_user(uiov, kmsg->msg_iov, iovs_size);
if (out_iov)
{
*out_iov = uiov;
}
kmsg->msg_iov = kiov;
for (int i = 0; i < kmsg->msg_iovlen; ++i)
{
/*
* We MUST check we can copy data to user after socket done in uiov
* otherwise we will be lost the messages from the network!
*/
if (!lwp_user_accessable(uiov->iov_base, uiov->iov_len))
{
kmem_put(kmsg->msg_iov);
return -EPERM;
}
iovs_buffer_size += uiov->iov_len;
kiov->iov_len = uiov->iov_len;
++kiov;
++uiov;
}
/* msg_iov and msg_control */
iovs_buffer = kmem_get(iovs_buffer_size + kmsg->msg_controllen);
if (!iovs_buffer)
{
kmem_put(kmsg->msg_iov);
return -ENOMEM;
}
kiov = kmsg->msg_iov;
for (int i = 0; i < kmsg->msg_iovlen; ++i)
{
kiov->iov_base = iovs_buffer;
iovs_buffer += kiov->iov_len;
++kiov;
}
*out_msg_control = kmsg->msg_control;
/* msg_control is the end of the iovs_buffer */
kmsg->msg_control = iovs_buffer;
return 0;
}
#endif /* ARCH_MM_MMU */
sysret_t sys_recvmsg(int socket, struct msghdr *msg, int flags)
{
int flgs, ret = -1;
struct msghdr kmsg;
#ifdef ARCH_MM_MMU
void *msg_control;
struct iovec *uiov, *kiov;
#endif
if (!msg)
{
return -EPERM;
}
flgs = netflags_muslc_2_lwip(flags);
#ifdef ARCH_MM_MMU
ret = copy_msghdr_from_user(&kmsg, msg, &uiov, &msg_control);
if (!ret)
{
ret = recvmsg(socket, &kmsg, flgs);
if (ret < 0)
{
goto _free_res;
}
kiov = kmsg.msg_iov;
for (int i = 0; i < kmsg.msg_iovlen; ++i)
{
lwp_put_to_user(uiov->iov_base, kiov->iov_base, kiov->iov_len);
++kiov;
++uiov;
}
lwp_put_to_user(msg_control, kmsg.msg_control, kmsg.msg_controllen);
lwp_put_to_user(&msg->msg_flags, &kmsg.msg_flags, sizeof(kmsg.msg_flags));
_free_res:
kmem_put(kmsg.msg_iov->iov_base);
kmem_put(kmsg.msg_iov);
}
#else
rt_memcpy(&kmsg, msg, sizeof(kmsg));
ret = recvmsg(socket, &kmsg, flgs);
if (!ret)
{
msg->msg_flags = kmsg.msg_flags;
}
#endif /* ARCH_MM_MMU */
return (ret < 0 ? GET_ERRNO() : ret);
}
sysret_t sys_recvfrom(int socket, void *mem, size_t len, int flags,
struct musl_sockaddr *from, socklen_t *fromlen)
{
@@ -3633,6 +3777,57 @@ sysret_t sys_recv(int socket, void *mem, size_t len, int flags)
return (ret < 0 ? GET_ERRNO() : ret);
}
sysret_t sys_sendmsg(int socket, const struct msghdr *msg, int flags)
{
int flgs, ret = -1;
struct msghdr kmsg;
#ifdef ARCH_MM_MMU
void *msg_control;
struct iovec *uiov, *kiov;
#endif
if (!msg)
{
return -EPERM;
}
flgs = netflags_muslc_2_lwip(flags);
#ifdef ARCH_MM_MMU
ret = copy_msghdr_from_user(&kmsg, (struct msghdr *)msg, &uiov, &msg_control);
if (!ret)
{
kiov = kmsg.msg_iov;
for (int i = 0; i < kmsg.msg_iovlen; ++i)
{
lwp_get_from_user(kiov->iov_base, uiov->iov_base, kiov->iov_len);
++kiov;
++uiov;
}
lwp_get_from_user(kmsg.msg_control, msg_control, kmsg.msg_controllen);
ret = sendmsg(socket, &kmsg, flgs);
kmem_put(kmsg.msg_iov->iov_base);
kmem_put(kmsg.msg_iov);
}
#else
rt_memcpy(&kmsg, msg, sizeof(kmsg));
ret = sendmsg(socket, &kmsg, flgs);
if (!ret)
{
msg->msg_flags = kmsg.msg_flags;
}
#endif /* ARCH_MM_MMU */
return (ret < 0 ? GET_ERRNO() : ret);
}
sysret_t sys_sendto(int socket, const void *dataptr, size_t size, int flags,
const struct musl_sockaddr *to, socklen_t tolen)
{
@@ -3757,6 +3952,30 @@ out:
return (fd < 0 ? GET_ERRNO() : fd);
}
sysret_t sys_socketpair(int domain, int type, int protocol, int fd[2])
{
#ifdef RT_USING_SAL
int ret = 0;
int k_fd[2];
if (!lwp_user_accessable((void *)fd, sizeof(int [2])))
{
return -EFAULT;
}
ret = socketpair(domain, type, protocol, k_fd);
if (ret == 0)
{
lwp_put_to_user(fd, k_fd, sizeof(int [2]));
}
return ret;
#else
return -ELIBACC;
#endif
}
sysret_t sys_closesocket(int socket)
{
return closesocket(socket);
@@ -6688,8 +6907,8 @@ const static struct rt_syscall_def func_table[] =
SYSCALL_NET(SYSCALL_SIGN(sys_getaddrinfo)),
SYSCALL_NET(SYSCALL_SIGN(sys_gethostbyname2_r)), /* 85 */
SYSCALL_SIGN(sys_notimpl), //network,
SYSCALL_SIGN(sys_notimpl), //network,
SYSCALL_NET(SYSCALL_SIGN(sys_sendmsg)),
SYSCALL_NET(SYSCALL_SIGN(sys_recvmsg)),
SYSCALL_SIGN(sys_notimpl), //network,
SYSCALL_SIGN(sys_notimpl), //network,
SYSCALL_SIGN(sys_notimpl), //network, /* 90 */
@@ -6826,6 +7045,8 @@ const static struct rt_syscall_def func_table[] =
SYSCALL_SIGN(sys_ftruncate),
SYSCALL_SIGN(sys_setitimer),
SYSCALL_SIGN(sys_utimensat),
SYSCALL_SIGN(sys_notimpl),
SYSCALL_SIGN(sys_socketpair), /* 205 */
};
const void *lwp_get_sys_api(rt_uint32_t number)