netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Dan Carpenter <dan.carpenter@oracle.com>
To: David Ahern <dsahern@gmail.com>
Cc: kbuild@lists.01.org, Arjun Roy <arjunroy.kdev@gmail.com>,
	davem@davemloft.net, netdev@vger.kernel.org, lkp@intel.com,
	kbuild-all@lists.01.org, arjunroy@google.com,
	edumazet@google.com, soheil@google.com,
	Leon Romanovsky <leon@kernel.org>,
	Jakub Kicinski <kuba@kernel.org>
Subject: Re: [net-next] tcp: Sanitize CMSG flags and reserved args in tcp_zerocopy_receive.
Date: Mon, 15 Feb 2021 19:02:22 +0300	[thread overview]
Message-ID: <20210215160222.GE2222@kadam> (raw)
In-Reply-To: <33d68f94-2d20-fdc4-c572-16138aa6305b@gmail.com>

On Mon, Feb 15, 2021 at 08:04:11AM -0700, David Ahern wrote:
> On 2/15/21 5:03 AM, Dan Carpenter wrote:
> > Hi Arjun,
> > 
> > url:    https://github.com/0day-ci/linux/commits/Arjun-Roy/tcp-Sanitize-CMSG-flags-and-reserved-args-in-tcp_zerocopy_receive/20210212-052537 
> > base:   https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git  e4b62cf7559f2ef9a022de235e5a09a8d7ded520
> > config: x86_64-randconfig-m001-20210209 (attached as .config)
> > compiler: gcc-9 (Debian 9.3.0-15) 9.3.0
> > 
> > If you fix the issue, kindly add following tag as appropriate
> > Reported-by: kernel test robot <lkp@intel.com>
> > Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
> > 
> > smatch warnings:
> > net/ipv4/tcp.c:4158 do_tcp_getsockopt() warn: check for integer overflow 'len'
> > 
> > vim +/len +4158 net/ipv4/tcp.c
> > 
> > 3fdadf7d27e3fb Dmitry Mishin            2006-03-20  3896  static int do_tcp_getsockopt(struct sock *sk, int level,
> > 3fdadf7d27e3fb Dmitry Mishin            2006-03-20  3897  		int optname, char __user *optval, int __user *optlen)
> > ^1da177e4c3f41 Linus Torvalds           2005-04-16  3898  {
> > 295f7324ff8d9e Arnaldo Carvalho de Melo 2005-08-09  3899  	struct inet_connection_sock *icsk = inet_csk(sk);
> > ^1da177e4c3f41 Linus Torvalds           2005-04-16  3900  	struct tcp_sock *tp = tcp_sk(sk);
> > 6fa251663069e0 Nikolay Borisov          2016-02-03  3901  	struct net *net = sock_net(sk);
> > ^1da177e4c3f41 Linus Torvalds           2005-04-16  3902  	int val, len;
> > 
> > "len" is int.
> > 
> > [ snip ]
> > 05255b823a6173 Eric Dumazet             2018-04-27  4146  #ifdef CONFIG_MMU
> > 05255b823a6173 Eric Dumazet             2018-04-27  4147  	case TCP_ZEROCOPY_RECEIVE: {
> > 7eeba1706eba6d Arjun Roy                2021-01-20  4148  		struct scm_timestamping_internal tss;
> > e0fecb289ad3fd Arjun Roy                2020-12-10  4149  		struct tcp_zerocopy_receive zc = {};
> > 05255b823a6173 Eric Dumazet             2018-04-27  4150  		int err;
> > 05255b823a6173 Eric Dumazet             2018-04-27  4151  
> > 05255b823a6173 Eric Dumazet             2018-04-27  4152  		if (get_user(len, optlen))
> > 05255b823a6173 Eric Dumazet             2018-04-27  4153  			return -EFAULT;
> > c8856c05145490 Arjun Roy                2020-02-14  4154  		if (len < offsetofend(struct tcp_zerocopy_receive, length))
> > 05255b823a6173 Eric Dumazet             2018-04-27  4155  			return -EINVAL;
> > 
> > 
> > The problem is that negative values of "len" are type promoted to high
> > positive values.  So the fix is to write this as:
> > 
> > 	if (len < 0 || len < offsetofend(struct tcp_zerocopy_receive, length))
> > 		return -EINVAL;
> > 
> > 110912bdf28392 Arjun Roy                2021-02-11  4156  		if (unlikely(len > sizeof(zc))) {
> > 110912bdf28392 Arjun Roy                2021-02-11  4157  			err = check_zeroed_user(optval + sizeof(zc),
> > 110912bdf28392 Arjun Roy                2021-02-11 @4158  						len - sizeof(zc));
> >                                                                                                         ^^^^^^^^^^^^^^^^
> > Potentially "len - a negative value".
> > 
> > 
> 
> get_user(len, optlen) is called multiple times in that function. len < 0
> was checked after the first one at the top.
> 

What you're describing is a "Double Fetch" bug, where the attack is we
get some data from the user, and we verify it, then we get it from the
user a second time and trust it.  The problem is that the user modifies
it between the first and second get_user() call so it ends up being a
security vulnerability.

But I'm glad you pointed out the first get_user() because it has an
ancient, harmless pre git bug in it.

net/ipv4/tcp.c
  3888  static int do_tcp_getsockopt(struct sock *sk, int level,
  3889                  int optname, char __user *optval, int __user *optlen)
  3890  {
  3891          struct inet_connection_sock *icsk = inet_csk(sk);
  3892          struct tcp_sock *tp = tcp_sk(sk);
  3893          struct net *net = sock_net(sk);
  3894          int val, len;
  3895  
  3896          if (get_user(len, optlen))
  3897                  return -EFAULT;
  3898  
  3899          len = min_t(unsigned int, len, sizeof(int));
  3900  
  3901          if (len < 0)
                    ^^^^^^^
This is impossible.  "len" has to be in the 0-4 range because of the
min_t() assignment.  It's harmless though and the condition should just
be removed.

  3902                  return -EINVAL;
  3903  
  3904          switch (optname) {
  3905          case TCP_MAXSEG:

Anyway, I will create a new Smatch warning for this situation.

> Also, maybe I am missing something here, but offsetofend can not return
> a negative value, so this checks catches len < 0 as well:
> 
> 	if (len < offsetofend(struct tcp_zerocopy_receive, length))
> 		return -EINVAL;
> 

offsetofend is (unsigned long)12.  If we compare a negative integer with
(unsigned long)12 then negative number is type promoted to a high
positive value.

	if (-1 < (usigned long)12)
		printf("dan is wrong\n");

regards,
dan carpenter



  reply	other threads:[~2021-02-15 16:08 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-02-11 21:21 [net-next] tcp: Sanitize CMSG flags and reserved args in tcp_zerocopy_receive Arjun Roy
2021-02-12  2:08 ` Jakub Kicinski
2021-02-12  3:10 ` patchwork-bot+netdevbpf
2021-02-15 12:03 ` Dan Carpenter
2021-02-15 15:04   ` David Ahern
2021-02-15 16:02     ` Dan Carpenter [this message]
2021-02-25 23:00       ` Arjun Roy

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=20210215160222.GE2222@kadam \
    --to=dan.carpenter@oracle.com \
    --cc=arjunroy.kdev@gmail.com \
    --cc=arjunroy@google.com \
    --cc=davem@davemloft.net \
    --cc=dsahern@gmail.com \
    --cc=edumazet@google.com \
    --cc=kbuild-all@lists.01.org \
    --cc=kbuild@lists.01.org \
    --cc=kuba@kernel.org \
    --cc=leon@kernel.org \
    --cc=lkp@intel.com \
    --cc=netdev@vger.kernel.org \
    --cc=soheil@google.com \
    /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).