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:
parent
4ed4e3ca36
commit
ac4183e589
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user