All of lore.kernel.org
 help / color / mirror / Atom feed
From: Philippe Gerum <rpm@xenomai.org>
To: xenomai@xenomai.org
Subject: [PATCH 3/5] net/ipv4: ioctl: remove direct references to user memory
Date: Fri, 22 Mar 2019 10:59:33 +0100	[thread overview]
Message-ID: <20190322095935.8066-4-rpm@xenomai.org> (raw)
In-Reply-To: <20190322095935.8066-1-rpm@xenomai.org>

Signed-off-by: Philippe Gerum <rpm@xenomai.org>
---
 kernel/drivers/net/stack/ipv4/ip_sock.c | 172 +++++++++++++++++-------
 1 file changed, 123 insertions(+), 49 deletions(-)

diff --git a/kernel/drivers/net/stack/ipv4/ip_sock.c b/kernel/drivers/net/stack/ipv4/ip_sock.c
index 96944a891..26bde8658 100644
--- a/kernel/drivers/net/stack/ipv4/ip_sock.c
+++ b/kernel/drivers/net/stack/ipv4/ip_sock.c
@@ -28,9 +28,10 @@
 #include <rtnet_socket.h>
 #include <ipv4/igmp.h>
 
-int rt_ip_setsockopt(struct rtsocket *s, int level, int optname,
-		     const void *optval, socklen_t optlen)
+static int rt_ip_setsockopt(struct rtdm_fd *fd, int level, int optname,
+		     const void __user *u_optval, socklen_t optlen)
 {
+	struct rtsocket *s = rtdm_fd_to_private(fd);
 	int err = 0, in_rt;
 
 	if (level != SOL_IP)
@@ -39,16 +40,24 @@ int rt_ip_setsockopt(struct rtsocket *s, int level, int optname,
 	in_rt = rtdm_in_rt_context();
 
 	switch (optname) {
-	case IP_TOS:
+	case IP_TOS: {
+		unsigned int *tos, _tos;
+
 		if (optlen < sizeof(unsigned int))
 			return -EINVAL;
 
-		s->prot.inet.tos = *(unsigned int *)optval;
+		tos = rtnet_get_arg(fd, &_tos, u_optval, sizeof(_tos));
+		if (IS_ERR(tos))
+			return PTR_ERR(tos);
+
+		s->prot.inet.tos = *tos;
 		break;
+	}
 
 #ifdef CONFIG_XENO_DRIVERS_NET_RTIPV4_IGMP
 	case IP_ADD_MEMBERSHIP: {
-		struct ip_mreq *mreq = (struct ip_mreq *)optval;
+		const struct ip_mreq *mreq;
+		struct ip_mreq _mreq;
 
 		if (optlen < sizeof(*mreq))
 			return -EINVAL;
@@ -56,12 +65,17 @@ int rt_ip_setsockopt(struct rtsocket *s, int level, int optname,
 		if (!in_rt)
 			return -ENOSYS;
 
+		mreq = rtnet_get_arg(fd, &_mreq, u_optval, sizeof(_mreq));
+		if (IS_ERR(mreq))
+			return PTR_ERR(mreq);
+
 		err = rt_ip_mc_join_group(s, mreq);
 		break;
 	}
 
 	case IP_DROP_MEMBERSHIP: {
-		struct ip_mreq *mreq = (struct ip_mreq *)optval;
+		const struct ip_mreq *mreq;
+		struct ip_mreq _mreq;
 
 		if (optlen < sizeof(*mreq))
 			return -EINVAL;
@@ -69,23 +83,35 @@ int rt_ip_setsockopt(struct rtsocket *s, int level, int optname,
 		if (!in_rt)
 			return -ENOSYS;
 
+		mreq = rtnet_get_arg(fd, &_mreq, u_optval, sizeof(_mreq));
+		if (IS_ERR(mreq))
+			return PTR_ERR(mreq);
+
 		err = rt_ip_mc_leave_group(s, mreq);
 		break;
 	}
 
 	case IP_MULTICAST_IF: {
-	    struct ip_mreq mreq;
-
-	    if (optlen < sizeof(struct in_addr))
-		return -EINVAL;
+		if (optlen < sizeof(struct in_addr))
+			return -EINVAL;
 
-	    if (optlen >= sizeof(mreq))
-		memcpy(&mreq, optval, sizeof(mreq));
-	    else
-		memcpy(&mreq.imr_interface, optval, sizeof(mreq.imr_interface));
+		if (optlen >= sizeof(struct ip_mreq)) {
+			const struct ip_mreq *mreq;
+			struct ip_mreq _mreq;
+			mreq = rtnet_get_arg(fd, &_mreq, u_optval, sizeof(_mreq));
+			if (IS_ERR(mreq))
+				return PTR_ERR(mreq);
+			s->prot.inet.mc_if_addr = mreq->imr_interface.s_addr;
+		} else {
+			const struct in_addr *in_addr;
+			struct in_addr _in_addr;
+			in_addr = rtnet_get_arg(fd, &_in_addr, u_optval, sizeof(_in_addr));
+			if (IS_ERR(in_addr))
+				return PTR_ERR(in_addr);
+			s->prot.inet.mc_if_addr = in_addr->s_addr;
+		}
 
-	    s->prot.inet.mc_if_addr = mreq.imr_interface.s_addr;
-	    break;
+		break;
 	}
 #endif
 	default:
@@ -96,18 +122,30 @@ int rt_ip_setsockopt(struct rtsocket *s, int level, int optname,
 	return err;
 }
 
-int rt_ip_getsockopt(struct rtsocket *s, int level, int optname,
-		     void *optval, socklen_t * optlen)
+static int rt_ip_getsockopt(struct rtdm_fd *fd, int level, int optname,
+		     void __user *u_optval, socklen_t __user *u_optlen)
 {
+	struct rtsocket *s = rtdm_fd_to_private(fd);
+	socklen_t *optlen, _optlen;
+	unsigned int tos;
 	int err = 0;
 
-	if (*optlen < sizeof(unsigned int))
-		return -EINVAL;
+	optlen = rtnet_get_arg(fd, &_optlen, u_optlen, sizeof(_optlen));
+	if (IS_ERR(optlen))
+		return PTR_ERR(optlen);
 
 	switch (optname) {
 	case IP_TOS:
-		*(unsigned int *)optval = s->prot.inet.tos;
-		*optlen = sizeof(unsigned int);
+		if (*optlen < sizeof(tos))
+			return -EINVAL;
+		tos = s->prot.inet.tos;
+		err = rtnet_put_arg(fd, u_optval, &tos, sizeof(tos));
+		if (err)
+			return err;
+		*optlen = sizeof(tos);
+		err = rtnet_put_arg(fd, u_optlen, optlen, sizeof(*optlen));
+		if (err)
+			return err;
 		break;
 
 	default:
@@ -118,65 +156,101 @@ int rt_ip_getsockopt(struct rtsocket *s, int level, int optname,
 	return err;
 }
 
-int rt_ip_getsockname(struct rtsocket *s, struct sockaddr *addr,
-		      socklen_t * addrlen)
+static int rt_ip_getsockname(struct rtdm_fd *fd,
+			struct sockaddr __user *u_addr,
+			socklen_t __user *u_addrlen)
 {
-	struct sockaddr_in *usin = (struct sockaddr_in *)addr;
+	struct rtsocket *s = rtdm_fd_to_private(fd);
+	socklen_t *addrlen, _addrlen;
+	struct sockaddr_in in;
+	int err;
+
+	addrlen = rtnet_get_arg(fd, &_addrlen, u_addrlen, sizeof(_addrlen));
+	if (IS_ERR(addrlen))
+		return PTR_ERR(addrlen);
 
 	if (*addrlen < sizeof(struct sockaddr_in))
 		return -EINVAL;
 
-	usin->sin_family = AF_INET;
-	usin->sin_addr.s_addr = s->prot.inet.saddr;
-	usin->sin_port = s->prot.inet.sport;
+	in.sin_family = AF_INET;
+	in.sin_addr.s_addr = s->prot.inet.saddr;
+	in.sin_port = s->prot.inet.sport;
+	memset(in.sin_zero, 0, sizeof(in.sin_zero));
 
-	memset(usin->sin_zero, 0, sizeof(usin->sin_zero));
+	err = rtnet_put_arg(fd, u_addr, &in, sizeof(in));
+	if (err)
+		return err;
 
-	*addrlen = sizeof(struct sockaddr_in);
+	*addrlen = sizeof(in);
 
-	return 0;
+	return rtnet_put_arg(fd, u_addrlen, addrlen, sizeof(*addrlen));
 }
 
-int rt_ip_getpeername(struct rtsocket *s, struct sockaddr *addr,
-		      socklen_t * addrlen)
+static int rt_ip_getpeername(struct rtdm_fd *fd,
+			struct sockaddr __user *u_addr,
+			socklen_t __user *u_addrlen)
 {
-	struct sockaddr_in *usin = (struct sockaddr_in *)addr;
+	struct rtsocket *s = rtdm_fd_to_private(fd);
+	socklen_t *addrlen, _addrlen;
+	struct sockaddr_in in;
+	int err;
+
+	addrlen = rtnet_get_arg(fd, &_addrlen, u_addrlen, sizeof(_addrlen));
+	if (IS_ERR(addrlen))
+		return PTR_ERR(addrlen);
 
 	if (*addrlen < sizeof(struct sockaddr_in))
 		return -EINVAL;
 
-	usin->sin_family = AF_INET;
-	usin->sin_addr.s_addr = s->prot.inet.daddr;
-	usin->sin_port = s->prot.inet.dport;
+	in.sin_family = AF_INET;
+	in.sin_addr.s_addr = s->prot.inet.daddr;
+	in.sin_port = s->prot.inet.dport;
+	memset(in.sin_zero, 0, sizeof(in.sin_zero));
 
-	memset(usin->sin_zero, 0, sizeof(usin->sin_zero));
+	err = rtnet_put_arg(fd, u_addr, &in, sizeof(in));
+	if (err)
+		return err;
 
-	*addrlen = sizeof(struct sockaddr_in);
+	*addrlen = sizeof(in);
 
-	return 0;
+	return rtnet_put_arg(fd, u_addrlen, addrlen, sizeof(*addrlen));
 }
 
-int rt_ip_ioctl(struct rtdm_fd *fd, int request, void *arg)
+int rt_ip_ioctl(struct rtdm_fd *fd, int request, void __user *arg)
 {
-	struct rtsocket *sock = rtdm_fd_to_private(fd);
-	struct _rtdm_getsockaddr_args *getaddr = arg;
-	struct _rtdm_getsockopt_args *getopt = arg;
-	struct _rtdm_setsockopt_args *setopt = arg;
+	const struct _rtdm_getsockopt_args *getopt;
+	struct _rtdm_getsockopt_args _getopt;
+	const struct _rtdm_setsockopt_args *setopt;
+	struct _rtdm_setsockopt_args _setopt;
+	const struct _rtdm_getsockaddr_args *getaddr;
+	struct _rtdm_getsockaddr_args _getaddr;
 
 	switch (request) {
 	case _RTIOC_SETSOCKOPT:
-		return rt_ip_setsockopt(sock, setopt->level, setopt->optname,
+		setopt = rtnet_get_arg(fd, &_setopt, arg, sizeof(_setopt));
+		if (IS_ERR(setopt))
+			return PTR_ERR(setopt);
+		return rt_ip_setsockopt(fd, setopt->level, setopt->optname,
 					setopt->optval, setopt->optlen);
 
 	case _RTIOC_GETSOCKOPT:
-		return rt_ip_getsockopt(sock, getopt->level, getopt->optname,
+		getopt = rtnet_get_arg(fd, &_getopt, arg, sizeof(_getopt));
+		if (IS_ERR(getopt))
+			return PTR_ERR(getopt);
+		return rt_ip_getsockopt(fd, getopt->level, getopt->optname,
 					getopt->optval, getopt->optlen);
 
 	case _RTIOC_GETSOCKNAME:
-		return rt_ip_getsockname(sock, getaddr->addr, getaddr->addrlen);
+		getaddr = rtnet_get_arg(fd, &_getaddr, arg, sizeof(_getaddr));
+		if (IS_ERR(getaddr))
+			return PTR_ERR(getaddr);
+		return rt_ip_getsockname(fd, getaddr->addr, getaddr->addrlen);
 
 	case _RTIOC_GETPEERNAME:
-		return rt_ip_getpeername(sock, getaddr->addr, getaddr->addrlen);
+		getaddr = rtnet_get_arg(fd, &_getaddr, arg, sizeof(_getaddr));
+		if (IS_ERR(getaddr))
+			return PTR_ERR(getaddr);
+		return rt_ip_getpeername(fd, getaddr->addr, getaddr->addrlen);
 
 	default:
 		return rt_socket_if_ioctl(fd, request, arg);
-- 
2.20.1



  parent reply	other threads:[~2019-03-22  9:59 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-03-22  9:59 [PATCH 0/5] More RTnet fixes and updates Philippe Gerum
2019-03-22  9:59 ` [PATCH 1/5] net/stack: increase maximum number of ethernet devices Philippe Gerum
2019-03-22  9:59 ` [PATCH 2/5] net/drivers: e1000e: stop using deprecated pci_enable_msix() Philippe Gerum
2019-03-22  9:59 ` Philippe Gerum [this message]
2019-03-22  9:59 ` [PATCH 4/5] net/drivers: fec: enable multicast Philippe Gerum
2019-03-22  9:59 ` [PATCH 5/5] utils/net: ping: display min and average round-trip time Philippe Gerum

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190322095935.8066-4-rpm@xenomai.org \
    --to=rpm@xenomai.org \
    --cc=xenomai@xenomai.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.