From: François LEGAL <[email protected]> Add copy_from_user call on struct user_msghdr in case fd is a user fd.
Signed-off-by: François LEGAL <[email protected]> --- kernel/drivers/can/rtcan_raw.c | 37 +++++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/kernel/drivers/can/rtcan_raw.c b/kernel/drivers/can/rtcan_raw.c index 693b927..ef05ae2 100644 --- a/kernel/drivers/can/rtcan_raw.c +++ b/kernel/drivers/can/rtcan_raw.c @@ -527,12 +527,12 @@ do { \ } while (0) ssize_t rtcan_raw_recvmsg(struct rtdm_fd *fd, - struct user_msghdr *msg, int flags) + struct user_msghdr *u_msg, int flags) { struct rtcan_socket *sock = rtdm_fd_to_private(fd); struct sockaddr_can scan; nanosecs_rel_t timeout; - struct iovec *iov = (struct iovec *)msg->msg_iov; + struct iovec *iov; struct iovec iov_buf; can_frame_t frame; nanosecs_abs_t timestamp = 0; @@ -543,8 +543,17 @@ ssize_t rtcan_raw_recvmsg(struct rtdm_fd *fd, size_t first_part_size; size_t payload_size; rtdm_lockctx_t lock_ctx; + struct user_msghdr _msg, *msg; int ret; + if (rtdm_fd_is_user(fd)) { + if ((ret = rtdm_copy_from_user(fd, & _msg, u_msg, sizeof (struct user_msghdr))) != 0) + return -ret; + else + msg = & _msg; + } else + msg = u_msg; + /* Clear frame memory location */ memset(&frame, 0, sizeof(can_frame_t)); @@ -582,7 +591,8 @@ ssize_t rtcan_raw_recvmsg(struct rtdm_fd *fd, return -EFAULT; iov = &iov_buf; - } + } else + iov = (struct iovec *)msg->msg_iov; /* Check size of buffer */ if (iov->iov_len < sizeof(can_frame_t)) @@ -763,12 +773,12 @@ ssize_t rtcan_raw_recvmsg(struct rtdm_fd *fd, ssize_t rtcan_raw_sendmsg(struct rtdm_fd *fd, - const struct user_msghdr *msg, int flags) + const struct user_msghdr *u_msg, int flags) { struct rtcan_socket *sock = rtdm_fd_to_private(fd); - struct sockaddr_can *scan = (struct sockaddr_can *)msg->msg_name; + struct sockaddr_can *scan; struct sockaddr_can scan_buf; - struct iovec *iov = (struct iovec *)msg->msg_iov; + struct iovec *iov; struct iovec iov_buf; can_frame_t *frame; can_frame_t frame_buf; @@ -776,10 +786,19 @@ ssize_t rtcan_raw_sendmsg(struct rtdm_fd *fd, nanosecs_rel_t timeout = 0; struct tx_wait_queue tx_wait; struct rtcan_device *dev; + struct user_msghdr _msg; + const struct user_msghdr *msg; int ifindex = 0; int ret = 0; spl_t s; + if (rtdm_fd_is_user(fd)) { + if ((ret = rtdm_copy_from_user(fd, & _msg, u_msg, sizeof (struct user_msghdr))) != 0) + return -ret; + else + msg = & _msg; + } else + msg = u_msg; if (flags & MSG_OOB) /* Mirror BSD error message compatibility */ return -EOPNOTSUPP; @@ -821,7 +840,8 @@ ssize_t rtcan_raw_sendmsg(struct rtdm_fd *fd, return -EFAULT; scan = &scan_buf; - } + } else + scan = (struct sockaddr_can *)msg->msg_name; /* Check address family */ if (scan->can_family != AF_CAN) @@ -839,7 +859,8 @@ ssize_t rtcan_raw_sendmsg(struct rtdm_fd *fd, return -EFAULT; iov = &iov_buf; - } + } else + iov = (struct iovec *)msg->msg_iov; /* Check size of buffer */ if (iov->iov_len != sizeof(can_frame_t))
