mirror of
https://github.com/apache/nuttx.git
synced 2026-05-29 20:56:47 +08:00
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:
+45
-1
@@ -26,8 +26,10 @@
|
|||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include <nuttx/cancelpt.h>
|
#include <nuttx/cancelpt.h>
|
||||||
|
#include <nuttx/kmalloc.h>
|
||||||
#include <nuttx/net/net.h>
|
#include <nuttx/net/net.h>
|
||||||
|
|
||||||
#include "socket/socket.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;
|
FAR struct socket *psock;
|
||||||
ssize_t ret;
|
ssize_t ret;
|
||||||
|
#ifdef CONFIG_BUILD_KERNEL
|
||||||
|
struct sockaddr_storage kaddr;
|
||||||
|
FAR struct sockaddr *ufrom;
|
||||||
|
FAR void *kbuf;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* recvfrom() is a cancellation point */
|
/* recvfrom() is a cancellation point */
|
||||||
|
|
||||||
enter_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 */
|
/* Get the underlying socket structure */
|
||||||
|
|
||||||
ret = sockfd_socket(sockfd, &psock);
|
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);
|
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)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
set_errno(-ret);
|
set_errno(-ret);
|
||||||
ret = ERROR;
|
ret = ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
leave_cancellation_point();
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+38
-1
@@ -27,11 +27,13 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
#include <nuttx/cancelpt.h>
|
#include <nuttx/cancelpt.h>
|
||||||
|
#include <nuttx/kmalloc.h>
|
||||||
#include <nuttx/net/net.h>
|
#include <nuttx/net/net.h>
|
||||||
|
|
||||||
#include "socket/socket.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;
|
FAR struct socket *psock;
|
||||||
ssize_t ret;
|
ssize_t ret;
|
||||||
|
#ifdef CONFIG_BUILD_KERNEL
|
||||||
|
struct sockaddr_storage kaddr;
|
||||||
|
FAR void *kbuf;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* sendto() is a cancellation point */
|
/* sendto() is a cancellation point */
|
||||||
|
|
||||||
enter_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 */
|
/* Get the underlying socket structure */
|
||||||
|
|
||||||
ret = sockfd_socket(sockfd, &psock);
|
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);
|
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)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
set_errno(-ret);
|
set_errno(-ret);
|
||||||
ret = ERROR;
|
ret = ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
leave_cancellation_point();
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user