linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Herbert Xu <herbert@gondor.apana.org.au>
To: David Miller <davem@davemloft.net>,
	viro@ZenIV.linux.org.uk, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org, bcrl@kvack.org,
	YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>,
	nakam@linux-ipv6.org
Subject: [PATCH 2/2] ipv4: Avoid reading user iov twice after raw_probe_proto_opt
Date: Fri, 07 Nov 2014 21:27:09 +0800	[thread overview]
Message-ID: <E1XmjZF-0005Gp-MX@gondolin.me.apana.org.au> (raw)
In-Reply-To: 20141107132553.GA20190@gondor.apana.org.au

Ever since raw_probe_proto_opt was added it had the problem of
causing the user iov to be read twice, once during the probe for
the protocol header and once again in ip_append_data.

This is a potential security problem since it means that whatever
we're probing may be invalid.  This patch plugs the hole by
firstly advancing the iov so we don't read the same spot again,
and secondly saving what we read the first time around for use
by ip_append_data.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---

 net/ipv4/raw.c |   62 +++++++++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 54 insertions(+), 8 deletions(-)

diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index 9be9050..43385a9 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -79,6 +79,16 @@
 #include <linux/netfilter.h>
 #include <linux/netfilter_ipv4.h>
 #include <linux/compat.h>
+#include <linux/uio.h>
+
+struct raw_frag_vec {
+	struct iovec *iov;
+	union {
+		struct icmphdr icmph;
+		char c[1];
+	} hdr;
+	int hlen;
+};
 
 static struct raw_hashinfo raw_v4_hashinfo = {
 	.lock = __RW_LOCK_UNLOCKED(raw_v4_hashinfo.lock),
@@ -420,25 +430,57 @@ error:
 	return err;
 }
 
-static int raw_probe_proto_opt(struct flowi4 *fl4, struct msghdr *msg)
+static int raw_probe_proto_opt(struct raw_frag_vec *rfv, struct flowi4 *fl4)
 {
-	struct icmphdr icmph;
 	int err;
 
 	if (fl4->flowi4_proto != IPPROTO_ICMP)
 		return 0;
 
 	/* We only need the first two bytes. */
-	err = memcpy_fromiovecend((void *)&icmph, msg->msg_iov, 0, 2);
+	rfv->hlen = 2;
+
+	err = memcpy_fromiovec(rfv->hdr.c, rfv->iov, rfv->hlen);
 	if (err)
 		return err;
 
-	fl4->fl4_icmp_type = icmph.type;
-	fl4->fl4_icmp_code = icmph.code;
+	fl4->fl4_icmp_type = rfv->hdr.icmph.type;
+	fl4->fl4_icmp_code = rfv->hdr.icmph.code;
 
 	return 0;
 }
 
+static int raw_getfrag(void *from, char *to, int offset, int len, int odd,
+		       struct sk_buff *skb)
+{
+	struct raw_frag_vec *rfv = from;
+
+	if (offset < rfv->hlen) {
+		int copy = min(rfv->hlen - offset, len);
+
+		if (skb->ip_summed == CHECKSUM_PARTIAL)
+			memcpy(to, rfv->hdr.c + offset, copy);
+		else
+			skb->csum = csum_block_add(
+				skb->csum,
+				csum_partial_copy_nocheck(rfv->hdr.c + offset,
+							  to, copy, 0),
+				odd);
+
+		odd = 0;
+		offset += copy;
+		to += copy;
+		len -= copy;
+
+		if (!len)
+			return 0;
+	}
+
+	offset -= rfv->hlen;
+
+	return ip_generic_getfrag(rfv->iov, to, offset, len, odd, skb);
+}
+
 static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 		       size_t len)
 {
@@ -452,6 +494,7 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 	u8  tos;
 	int err;
 	struct ip_options_data opt_copy;
+	struct raw_frag_vec rfv;
 
 	err = -EMSGSIZE;
 	if (len > 0xFFFF)
@@ -557,7 +600,10 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 			   daddr, saddr, 0, 0);
 
 	if (!inet->hdrincl) {
-		err = raw_probe_proto_opt(&fl4, msg);
+		rfv.iov = msg->msg_iov;
+		rfv.hlen = 0;
+
+		err = raw_probe_proto_opt(&rfv, &fl4);
 		if (err)
 			goto done;
 	}
@@ -588,8 +634,8 @@ back_from_confirm:
 		if (!ipc.addr)
 			ipc.addr = fl4.daddr;
 		lock_sock(sk);
-		err = ip_append_data(sk, &fl4, ip_generic_getfrag,
-				     msg->msg_iov, len, 0,
+		err = ip_append_data(sk, &fl4, raw_getfrag,
+				     &rfv, len, 0,
 				     &ipc, &rt, msg->msg_flags);
 		if (err)
 			ip_flush_pending_frames(sk);

  parent reply	other threads:[~2014-11-07 13:27 UTC|newest]

Thread overview: 82+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-11-02 23:05 fs: Use non-const iov in aio_read/aio_write Herbert Xu
2014-11-03  0:16 ` Al Viro
2014-11-03  0:21   ` Al Viro
2014-11-03  0:22   ` Herbert Xu
2014-11-03  0:45     ` Al Viro
2014-11-03  5:37       ` [0/3] net: Kill skb_copy_datagram_const_iovec Herbert Xu
2014-11-03  5:44         ` [PATCH 1/3] tun: Modify const aio_read iovec per do_sock_read Herbert Xu
2014-11-03  5:44         ` [PATCH 3/3] net: Kill skb_copy_datagram_const_iovec Herbert Xu
2014-11-03  5:44         ` [PATCH 2/3] macvtap: Modify const aio_read iovec per do_sock_read Herbert Xu
2014-11-03 20:05         ` [0/3] net: Kill skb_copy_datagram_const_iovec David Miller
2014-11-04  3:38           ` Herbert Xu
2014-11-04  8:31             ` [PATCH 1/4] inet: Add skb_copy_datagram_iter Herbert Xu
2014-11-04 14:32               ` Al Viro
2014-11-04 14:35                 ` Al Viro
2014-11-04 14:44                   ` Herbert Xu
2014-11-04 14:52                     ` Al Viro
2014-11-04 14:55                       ` Herbert Xu
2014-11-04 14:42                 ` Herbert Xu
2014-11-04 15:13                   ` Al Viro
2014-11-05  2:22                     ` Herbert Xu
2014-11-05  3:27                       ` David Miller
2014-11-05  3:55                         ` Al Viro
2014-11-05  4:12                           ` Al Viro
2014-11-05 20:51                             ` David Miller
2014-11-05 20:50                           ` David Miller
2014-11-05 21:07                             ` Al Viro
2014-11-05 21:57                               ` David Miller
2014-11-06  3:25                                 ` Al Viro
2014-11-06  5:50                                   ` ipv4: Use standard iovec primitive in raw_probe_proto_opt Herbert Xu
2014-11-06  6:43                                     ` Al Viro
2014-11-06  6:46                                       ` Herbert Xu
2014-11-06  7:11                                         ` Al Viro
2014-11-06  9:55                                           ` Jon Maloy
2014-11-06 22:16                                             ` Al Viro
2014-11-28  5:14                                               ` Al Viro
2014-11-06 21:28                                         ` David Miller
2014-11-07  2:00                                           ` Herbert Xu
2014-11-07 13:25                                             ` [PATCH 0/2] ipv4: Simplify raw_probe_proto_opt and avoid reading user iov twice Herbert Xu
2014-11-07 13:27                                               ` [PATCH 1/2] ipv4: Use standard iovec primitive in raw_probe_proto_opt Herbert Xu
2014-11-07 13:27                                               ` Herbert Xu [this message]
2014-11-10 19:26                                               ` [PATCH 0/2] ipv4: Simplify raw_probe_proto_opt and avoid reading user iov twice David Miller
2014-11-06  9:50                                   ` [PATCH 1/4] inet: Add skb_copy_datagram_iter Jon Maloy
2014-11-07 21:48                                   ` David Miller
2014-11-07 22:11                                     ` Al Viro
2014-11-07 22:31                                       ` Al Viro
2014-11-07 22:35                                         ` Al Viro
2014-11-07 23:42                                       ` Al Viro
2014-11-08  2:21                                         ` Herbert Xu
2014-11-09 21:19                                         ` Al Viro
2014-11-10  5:20                                           ` David Miller
2014-11-10  6:58                                             ` Al Viro
2014-11-10  7:30                                               ` David Miller
2014-11-10  9:09                                                 ` Al Viro
2014-11-10 16:18                                                   ` David Miller
2014-11-10 10:14                                           ` Michael S. Tsirkin
2014-11-07 21:52                                   ` David Miller
2014-11-05 20:24               ` David Miller
2014-11-06  8:23                 ` Herbert Xu
2014-11-06 17:25                   ` David Miller
2014-11-07  1:59                     ` Herbert Xu
2014-11-07  3:13                       ` David Miller
2014-11-07 13:21                         ` [PATCH 0/4] Replace skb_copy_datagram_const_iovec with iterator version Herbert Xu
2014-11-07 13:22                           ` [PATCH 1/4] inet: Add skb_copy_datagram_iter Herbert Xu
2014-11-07 13:22                           ` [PATCH 2/4] tun: Use iovec iterators Herbert Xu
2014-11-07 13:22                           ` [PATCH 3/4] macvtap: " Herbert Xu
2014-11-07 13:22                           ` [PATCH 4/4] net: Kill skb_copy_datagram_const_iovec Herbert Xu
2014-11-06  8:27                 ` [PATCH 0/4] Replace skb_copy_datagram_const_iovec with iterator version Herbert Xu
2014-11-06  8:28                   ` [PATCH 1/4] inet: Add skb_copy_datagram_iter Herbert Xu
2014-11-06 17:30                     ` Al Viro
2014-11-07  1:58                       ` Herbert Xu
2014-11-06  8:28                   ` [PATCH 2/4] tun: Use iovec iterators Herbert Xu
2014-11-06  8:28                   ` [PATCH 3/4] macvtap: " Herbert Xu
2014-11-06 17:33                     ` Al Viro
2014-11-06  8:28                   ` [PATCH 4/4] net: Kill skb_copy_datagram_const_iovec Herbert Xu
2014-11-04  8:31             ` [PATCH 2/4] tun: Use iovec iterators Herbert Xu
2014-11-04  8:37               ` Herbert Xu
2014-11-05  2:49                 ` YOSHIFUJI Hideaki
2014-11-05  3:41                   ` Herbert Xu
2014-11-04  8:31             ` [PATCH 3/4] macvtap: " Herbert Xu
2014-11-04  8:31             ` [PATCH 4/4] net: Kill skb_copy_datagram_const_iovec Herbert Xu
2014-11-04  5:45           ` [0/3] " Al Viro
2014-11-05  1:53             ` Al Viro

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=E1XmjZF-0005Gp-MX@gondolin.me.apana.org.au \
    --to=herbert@gondor.apana.org.au \
    --cc=bcrl@kvack.org \
    --cc=davem@davemloft.net \
    --cc=linux-kernel@vger.kernel.org \
    --cc=nakam@linux-ipv6.org \
    --cc=netdev@vger.kernel.org \
    --cc=viro@ZenIV.linux.org.uk \
    --cc=yoshfuji@linux-ipv6.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).