From ac4183e589eb68ac51a6d222a3113d76141f111b Mon Sep 17 00:00:00 2001 From: Ville Juven Date: Wed, 24 May 2023 13:22:08 +0300 Subject: [PATCH] socket/send/recv: Copy user parameters to kernel memory (BUILD_KERNEL) Need to copy the user pointers into kernel memory before calling send/recv, because devif_poll() and others will fail at once due to wrong mappings. --- net/socket/recvfrom.c | 46 ++++++++++++++++++++++++++++++++++++++++++- net/socket/sendto.c | 39 +++++++++++++++++++++++++++++++++++- 2 files changed, 83 insertions(+), 2 deletions(-) diff --git a/net/socket/recvfrom.c b/net/socket/recvfrom.c index 5d03866943..5473c28031 100644 --- a/net/socket/recvfrom.c +++ b/net/socket/recvfrom.c @@ -26,8 +26,10 @@ #include #include +#include #include +#include #include #include "socket/socket.h" @@ -152,11 +154,39 @@ ssize_t recvfrom(int sockfd, FAR void *buf, size_t len, int flags, { FAR struct socket *psock; ssize_t ret; +#ifdef CONFIG_BUILD_KERNEL + struct sockaddr_storage kaddr; + FAR struct sockaddr *ufrom; + FAR void *kbuf; +#endif /* recvfrom() is a cancellation point */ enter_cancellation_point(); +#ifdef CONFIG_BUILD_KERNEL + /* Allocate memory and copy user buffer to kernel */ + + kbuf = kmm_malloc(len); + if (!kbuf) + { + /* Out of memory */ + + ret = -ENOMEM; + goto errout_with_cancelpt; + } + + memcpy(kbuf, buf, len); + buf = kbuf; + + /* Copy the address data to kernel, store the original user pointer */ + + if ((ufrom = from) != NULL) + { + from = (FAR struct sockaddr *)&kaddr; + } +#endif + /* Get the underlying socket structure */ ret = sockfd_socket(sockfd, &psock); @@ -168,13 +198,27 @@ ssize_t recvfrom(int sockfd, FAR void *buf, size_t len, int flags, ret = psock_recvfrom(psock, buf, len, flags, from, fromlen); } +#ifdef CONFIG_BUILD_KERNEL + kmm_free(kbuf); + + /* Copy the address back to user */ + + if (ufrom) + { + memcpy(ufrom, &kaddr, *fromlen); + } + +errout_with_cancelpt: +#endif + + leave_cancellation_point(); + if (ret < 0) { set_errno(-ret); ret = ERROR; } - leave_cancellation_point(); return ret; } diff --git a/net/socket/sendto.c b/net/socket/sendto.c index 8c36ee2ef8..c19dd25921 100644 --- a/net/socket/sendto.c +++ b/net/socket/sendto.c @@ -27,11 +27,13 @@ #include #include #include +#include #include #include #include #include +#include #include #include "socket/socket.h" @@ -198,11 +200,39 @@ ssize_t sendto(int sockfd, FAR const void *buf, size_t len, int flags, { FAR struct socket *psock; ssize_t ret; +#ifdef CONFIG_BUILD_KERNEL + struct sockaddr_storage kaddr; + FAR void *kbuf; +#endif /* sendto() is a cancellation point */ enter_cancellation_point(); +#ifdef CONFIG_BUILD_KERNEL + /* Allocate memory and copy user buffer to kernel */ + + kbuf = kmm_malloc(len); + if (!kbuf) + { + /* Out of memory */ + + ret = -ENOMEM; + goto errout_with_cancelpt; + } + + memcpy(kbuf, buf, len); + buf = kbuf; + + /* Copy the address data to kernel */ + + if (to) + { + memcpy(&kaddr, to, tolen); + to = (FAR const struct sockaddr *)&kaddr; + } +#endif + /* Get the underlying socket structure */ ret = sockfd_socket(sockfd, &psock); @@ -214,12 +244,19 @@ ssize_t sendto(int sockfd, FAR const void *buf, size_t len, int flags, ret = psock_sendto(psock, buf, len, flags, to, tolen); } +#ifdef CONFIG_BUILD_KERNEL + kmm_free(kbuf); + +errout_with_cancelpt: +#endif + + leave_cancellation_point(); + if (ret < 0) { set_errno(-ret); ret = ERROR; } - leave_cancellation_point(); return ret; }