Module: xenomai-3 Branch: wip/rtnet-fixes Commit: e9bedb0cdab8321457c82e91ffdff92cfc7ceb40 URL: http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=e9bedb0cdab8321457c82e91ffdff92cfc7ceb40
Author: Philippe Gerum <r...@xenomai.org> Date: Sun Jan 7 18:23:57 2018 +0100 net/udp: recvmsg, ioctl: remove direct references to user memory (2) --- kernel/drivers/net/stack/ipv4/udp/udp.c | 137 ++++++++++++++++++------------- 1 file changed, 78 insertions(+), 59 deletions(-) diff --git a/kernel/drivers/net/stack/ipv4/udp/udp.c b/kernel/drivers/net/stack/ipv4/udp/udp.c index 4368303..8e80d3e 100644 --- a/kernel/drivers/net/stack/ipv4/udp/udp.c +++ b/kernel/drivers/net/stack/ipv4/udp/udp.c @@ -154,18 +154,24 @@ static inline struct rtsocket *rt_udp_v4_lookup(u32 daddr, u16 dport) * @s: socket * @addr: local address */ -int rt_udp_bind(struct rtsocket *sock, const struct sockaddr *addr, - socklen_t addrlen) +int rt_udp_bind(struct rtdm_fd *fd, struct rtsocket *sock, + const struct sockaddr __user *addr, socklen_t addrlen) { - struct sockaddr_in *usin = (struct sockaddr_in *)addr; + struct sockaddr_in _sin, *sin; rtdm_lockctx_t context; int index; int err = 0; - if ((addrlen < (int)sizeof(struct sockaddr_in)) || - ((usin->sin_port & auto_port_mask) == auto_port_start)) - return -EINVAL; + if (addrlen < sizeof(struct sockaddr_in)) + return -EINVAL; + + sin = rtnet_get_arg(fd, &_sin, addr, sizeof(_sin)); + if (IS_ERR(sin)) + return PTR_ERR(sin); + + if ((sin->sin_port & auto_port_mask) == auto_port_start) + return -EINVAL; rtdm_lock_get_irqsave(&udp_socket_base_lock, context); @@ -181,8 +187,8 @@ int rt_udp_bind(struct rtsocket *sock, const struct sockaddr *addr, port_hash_del(&port_registry[index]); if (port_hash_insert(&port_registry[index], - usin->sin_addr.s_addr, - usin->sin_port ?: index + auto_port_start)) { + sin->sin_addr.s_addr, + sin->sin_port ?: index + auto_port_start)) { port_hash_insert(&port_registry[index], port_registry[index].saddr, port_registry[index].sport); @@ -207,51 +213,64 @@ int rt_udp_bind(struct rtsocket *sock, const struct sockaddr *addr, /*** * rt_udp_connect */ -int rt_udp_connect(struct rtsocket *sock, const struct sockaddr *serv_addr, - socklen_t addrlen) +int rt_udp_connect(struct rtdm_fd *fd, struct rtsocket *sock, + const struct sockaddr __user *serv_addr, socklen_t addrlen) { - struct sockaddr_in *usin = (struct sockaddr_in *) serv_addr; - rtdm_lockctx_t context; - int index; - - - if (usin->sin_family == AF_UNSPEC) { - if ((index = sock->prot.inet.reg_index) < 0) - /* socket is being closed */ - return -EBADF; - - rtdm_lock_get_irqsave(&udp_socket_base_lock, context); - - sock->prot.inet.saddr = INADDR_ANY; - /* Note: The following line differs from standard stacks, and we also - don't remove the socket from the port list. Might get fixed in - the future... */ - sock->prot.inet.sport = index + auto_port_start; - sock->prot.inet.daddr = INADDR_ANY; - sock->prot.inet.dport = 0; - sock->prot.inet.state = TCP_CLOSE; - - rtdm_lock_put_irqrestore(&udp_socket_base_lock, context); - } else { - if ((addrlen < (int)sizeof(struct sockaddr_in)) || - (usin->sin_family != AF_INET)) - return -EINVAL; - - rtdm_lock_get_irqsave(&udp_socket_base_lock, context); - - if (sock->prot.inet.state != TCP_CLOSE) { - rtdm_lock_put_irqrestore(&udp_socket_base_lock, context); - return -EINVAL; - } - - sock->prot.inet.state = TCP_ESTABLISHED; - sock->prot.inet.daddr = usin->sin_addr.s_addr; - sock->prot.inet.dport = usin->sin_port; - - rtdm_lock_put_irqrestore(&udp_socket_base_lock, context); - } + struct sockaddr _sa, *sa; + struct sockaddr_in _sin, *sin; + rtdm_lockctx_t context; + int index; + + if (addrlen < sizeof(struct sockaddr)) + return -EINVAL; + + sa = rtnet_get_arg(fd, &_sa, serv_addr, sizeof(_sa)); + if (IS_ERR(sa)) + return PTR_ERR(sa); + + if (sa->sa_family == AF_UNSPEC) { + if ((index = sock->prot.inet.reg_index) < 0) + /* socket is being closed */ + return -EBADF; + + rtdm_lock_get_irqsave(&udp_socket_base_lock, context); + + sock->prot.inet.saddr = INADDR_ANY; + /* Note: The following line differs from standard + stacks, and we also don't remove the socket from + the port list. Might get fixed in the future... */ + sock->prot.inet.sport = index + auto_port_start; + sock->prot.inet.daddr = INADDR_ANY; + sock->prot.inet.dport = 0; + sock->prot.inet.state = TCP_CLOSE; + + rtdm_lock_put_irqrestore(&udp_socket_base_lock, context); + } else { + if (addrlen < sizeof(struct sockaddr_in)) + return -EINVAL; + + sin = rtnet_get_arg(fd, &_sin, serv_addr, sizeof(_sin)); + if (IS_ERR(sin)) + return PTR_ERR(sin); + + if (sin->sin_family != AF_INET) + return -EINVAL; + + rtdm_lock_get_irqsave(&udp_socket_base_lock, context); + + if (sock->prot.inet.state != TCP_CLOSE) { + rtdm_lock_put_irqrestore(&udp_socket_base_lock, context); + return -EINVAL; + } + + sock->prot.inet.state = TCP_ESTABLISHED; + sock->prot.inet.daddr = sin->sin_addr.s_addr; + sock->prot.inet.dport = sin->sin_port; + + rtdm_lock_put_irqrestore(&udp_socket_base_lock, context); + } - return 0; + return 0; } @@ -363,9 +382,9 @@ int rt_udp_ioctl(struct rtdm_fd *fd, unsigned int request, void __user *arg) if (IS_ERR(setaddr)) return PTR_ERR(setaddr); if (request == _RTIOC_BIND) - return rt_udp_bind(sock, setaddr->addr, setaddr->addrlen); + return rt_udp_bind(fd, sock, setaddr->addr, setaddr->addrlen); - return rt_udp_connect(sock, setaddr->addr, setaddr->addrlen); + return rt_udp_connect(fd, sock, setaddr->addr, setaddr->addrlen); default: return rt_ip_ioctl(fd, request, arg); @@ -380,7 +399,7 @@ int rt_udp_ioctl(struct rtdm_fd *fd, unsigned int request, void __user *arg) /*** * rt_udp_recvmsg */ -ssize_t rt_udp_recvmsg(struct rtdm_fd *fd, struct user_msghdr *msg, int msg_flags) +ssize_t rt_udp_recvmsg(struct rtdm_fd *fd, struct user_msghdr *u_msg, int msg_flags) { struct rtsocket *sock = rtdm_fd_to_private(fd); size_t len; @@ -393,11 +412,11 @@ ssize_t rt_udp_recvmsg(struct rtdm_fd *fd, struct user_msghdr *msg, int msg_flag struct sockaddr_in sin; nanosecs_rel_t timeout = sock->timeout; int ret, flags; - struct user_msghdr _msg; + struct user_msghdr _msg, *msg; socklen_t namelen; struct iovec iov_fast[RTDM_IOV_FASTMAX], *iov; - msg = rtnet_get_arg(fd, &_msg, msg, sizeof(*msg)); + msg = rtnet_get_arg(fd, &_msg, u_msg, sizeof(_msg)); if (IS_ERR(msg)) return PTR_ERR(msg); @@ -438,12 +457,12 @@ ssize_t rt_udp_recvmsg(struct rtdm_fd *fd, struct user_msghdr *msg, int msg_flag sin.sin_family = AF_INET; sin.sin_port = uh->source; sin.sin_addr.s_addr = skb->nh.iph->saddr; - ret = rtnet_put_arg(fd, &msg->msg_name, &sin, sizeof(sin)); + ret = rtnet_put_arg(fd, msg->msg_name, &sin, sizeof(sin)); if (ret) goto fail; namelen = sizeof(sin); - ret = rtnet_put_arg(fd, &msg->msg_namelen, &namelen, sizeof(namelen)); + ret = rtnet_put_arg(fd, &u_msg->msg_namelen, &namelen, sizeof(namelen)); if (ret) goto fail; } @@ -485,7 +504,7 @@ ssize_t rt_udp_recvmsg(struct rtdm_fd *fd, struct user_msghdr *msg, int msg_flag flags |= MSG_TRUNC; if (flags != msg->msg_flags) { - ret = rtnet_put_arg(fd, &msg->msg_flags, &flags, sizeof(flags)); + ret = rtnet_put_arg(fd, &u_msg->msg_flags, &flags, sizeof(flags)); if (ret) goto fail; } _______________________________________________ Xenomai-git mailing list Xenomai-git@xenomai.org https://xenomai.org/mailman/listinfo/xenomai-git