linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Christian Brauner <christian@brauner.io>
To: Kees Cook <keescook@chromium.org>
Cc: LKML <linux-kernel@vger.kernel.org>,
	"Eric W. Biederman" <ebiederm@xmission.com>,
	"Luis R. Rodriguez" <mcgrof@kernel.org>,
	Andrew Morton <akpm@linux-foundation.org>,
	Joe Lawrence <joe.lawrence@redhat.com>,
	Waiman Long <longman@redhat.com>,
	Dominik Brodowski <linux@dominikbrodowski.net>,
	Al Viro <viro@zeniv.linux.org.uk>
Subject: Re: [PATCH v1 2/2] sysctl: handle overflow for file-max
Date: Tue, 16 Oct 2018 15:16:22 +0200	[thread overview]
Message-ID: <20181016131621.ebtkabyzvfqkh3s6@brauner.io> (raw)
In-Reply-To: <CAGXu5jKSnmcrmOCcuNKX39tx6_p0EY4GBtvpeK=g7PxUg1LJTA@mail.gmail.com>

On Mon, Oct 15, 2018 at 02:20:15PM -0700, Kees Cook wrote:
> On Mon, Oct 15, 2018 at 9:28 AM, Christian Brauner <christian@brauner.io> wrote:
> > On Mon, Oct 15, 2018 at 09:11:51AM -0700, Kees Cook wrote:
> >> On Mon, Oct 15, 2018 at 3:55 AM, Christian Brauner <christian@brauner.io> wrote:
> >> > Currently, when writing
> >> >
> >> > echo 18446744073709551616 > /proc/sys/fs/file-max
> >> >
> >> > /proc/sys/fs/file-max will overflow and be set to 0. That quickly
> >> > crashes the system.
> >> > This commit explicitly caps the value for file-max to ULONG_MAX.
> >> >
> >> > Note, this isn't technically necessary since proc_get_long() will already
> >> > return ULONG_MAX. However, two reason why we still should do this:
> >> > 1. it makes it explicit what the upper bound of file-max is instead of
> >> >    making readers of the code infer it from proc_get_long() themselves
> >> > 2. other tunebles than file-max may want to set a lower max value than
> >> >    ULONG_MAX and we need to enable __do_proc_doulongvec_minmax() to handle
> >> >    such cases too
> >> >
> >> > Cc: Kees Cook <keescook@chromium.org>
> >> > Signed-off-by: Christian Brauner <christian@brauner.io>
> >> > ---
> >> > v0->v1:
> >> > - if max value is < than ULONG_MAX use max as upper bound
> >> > - (Dominik) remove double "the" from commit message
> >> > ---
> >> >  kernel/sysctl.c | 4 ++++
> >> >  1 file changed, 4 insertions(+)
> >> >
> >> > diff --git a/kernel/sysctl.c b/kernel/sysctl.c
> >> > index 97551eb42946..226d4eaf4b0e 100644
> >> > --- a/kernel/sysctl.c
> >> > +++ b/kernel/sysctl.c
> >> > @@ -127,6 +127,7 @@ static int __maybe_unused one = 1;
> >> >  static int __maybe_unused two = 2;
> >> >  static int __maybe_unused four = 4;
> >> >  static unsigned long one_ul = 1;
> >> > +static unsigned long ulong_max = ULONG_MAX;
> >> >  static int one_hundred = 100;
> >> >  static int one_thousand = 1000;
> >> >  #ifdef CONFIG_PRINTK
> >> > @@ -1696,6 +1697,7 @@ static struct ctl_table fs_table[] = {
> >> >                 .maxlen         = sizeof(files_stat.max_files),
> >> >                 .mode           = 0644,
> >> >                 .proc_handler   = proc_doulongvec_minmax,
> >> > +               .extra2         = &ulong_max,
> >>
> >> Don't we want this capped lower? The percpu comparisons, for example,
> >> are all signed long. And there is at least this test, which could
> >> overflow:
> >>
> >>         if (atomic_long_read(&unix_nr_socks) > 2 * get_max_files())
> >>                 goto out;
> >
> > Does that check even make sense?
> > Commit 518de9b39e854542de59bfb8b9f61c8f7ecf808b made get_max_files()
> > return a long to bump the number of allowed files to more than 2^31.
> >
> > But assuming a platform where an unsigned long is 64bit which is what
> > get_max_files() returns and atomic_long_read() is 64bit too this is
> > guaranteed to overflow, no?  So I'm not clear what this is trying to do.
> > Seems this should simply be:
> >
> > if (atomic_long_read(&unix_nr_socks) > get_max_files())
> >         goto out;
> >
> > or am I missing a crucial point?
> >
> >>
> >> Seems like max-files should be  SLONG_MAX / 2 or something instead?
> >
> > Hm. Isn't that a bit low? Iiuc, this would mean cutting the maximum
> > number of open files in half? If at all shouldn't it be LONG_MAX?
> 
> LONG_MAX would align us with the values in the percpu stuff. I'm
> really not sure what's happening in the sock check, but it's prone to
> an unsigned multiplication overflow, if I'm reading it right. Probably
> should just be a separate bug fix:
> 
> -         if (atomic_long_read(&unix_nr_socks) > 2 * get_max_files())
> +         if (atomic_long_read(&unix_nr_socks) / 2 > get_max_files())

Yeah, as I said before this is just waiting for an overflow and it seems
this bug has existed since the switch to git. The intention apparently
was indeed to allow the number of sockets to be double the open file
limit. However, as it is right now this just overflows. I'll send a
separate patch for this but I'd sugest to do something like:


diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index d1edfa3cad61..7e461f4f0466 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -754,9 +754,12 @@ static struct sock *unix_create1(struct net *net, struct socket *sock, int kern)
 {
 	struct sock *sk = NULL;
 	struct unix_sock *u;
+	static atomic_long_t tmp;
 
 	atomic_long_inc(&unix_nr_socks);
-	if (atomic_long_read(&unix_nr_socks) > 2 * get_max_files())
+	tmp = atomic_long_read(&unix_nr_socks);
+	do_div(tmp, 2);
+	if (tmp > get_max_files())
 		goto out;
 
 	sk = sk_alloc(net, PF_UNIX, GFP_KERNEL, &unix_proto, kern);

> 
> -Kees
> 
> >
> >>
> >> >         },
> >> >         {
> >> >                 .procname       = "nr_open",
> >> > @@ -2795,6 +2797,8 @@ static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table, int
> >> >                                 break;
> >> >                         if (neg)
> >> >                                 continue;
> >> > +                       if (max && val > *max)
> >> > +                               val = *max;
> >> >                         val = convmul * val / convdiv;
> >> >                         if ((min && val < *min) || (max && val > *max))
> >> >                                 continue;
> >> > --
> >> > 2.17.1
> >> >
> >>
> >> -Kees
> >>
> >> --
> >> Kees Cook
> >> Pixel Security
> 
> 
> 
> -- 
> Kees Cook
> Pixel Security

  reply	other threads:[~2018-10-16 13:16 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-10-15 10:55 [PATCH v1 0/2] sysctl: cap file-max value at ULONG_MAX Christian Brauner
2018-10-15 10:55 ` [PATCH v1 1/2] sysctl: cap to ULONG_MAX in proc_get_long() Christian Brauner
2018-10-15 16:18   ` Kees Cook
2018-10-15 16:30     ` Christian Brauner
2018-10-15 19:01       ` Christian Brauner
2018-10-15 10:55 ` [PATCH v1 2/2] sysctl: handle overflow for file-max Christian Brauner
2018-10-15 16:11   ` Kees Cook
2018-10-15 16:28     ` Christian Brauner
2018-10-15 21:20       ` Kees Cook
2018-10-16 13:16         ` Christian Brauner [this message]
2018-10-16 14:38           ` Christian Brauner
2018-10-16 15:13   ` Waiman Long
2018-10-16 15:21     ` Christian Brauner
2018-10-16 15:25       ` Waiman Long
2018-10-16 15:29         ` Christian Brauner
2018-10-16 15:33           ` Christian Brauner
2018-10-16 15:34           ` Waiman Long
2018-10-16 15:40             ` Christian Brauner
2018-10-16 15:44               ` Waiman Long
2018-10-16 15:47                 ` Christian Brauner
2018-10-16 15:53                   ` Waiman Long
2018-10-16 15:59                     ` Christian Brauner

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=20181016131621.ebtkabyzvfqkh3s6@brauner.io \
    --to=christian@brauner.io \
    --cc=akpm@linux-foundation.org \
    --cc=ebiederm@xmission.com \
    --cc=joe.lawrence@redhat.com \
    --cc=keescook@chromium.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux@dominikbrodowski.net \
    --cc=longman@redhat.com \
    --cc=mcgrof@kernel.org \
    --cc=viro@zeniv.linux.org.uk \
    /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).