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.
This commit is contained in:
Ville Juven 2023-05-24 13:22:08 +03:00 committed by Xiang Xiao
parent 4ed4e3ca36
commit ac4183e589
2 changed files with 83 additions and 2 deletions

View File

@ -26,8 +26,10 @@
#include <assert.h>
#include <errno.h>
#include <string.h>
#include <nuttx/cancelpt.h>
#include <nuttx/kmalloc.h>
#include <nuttx/net/net.h>
#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;
}

View File

@ -27,11 +27,13 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <stdint.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <nuttx/cancelpt.h>
#include <nuttx/kmalloc.h>
#include <nuttx/net/net.h>
#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;
}