linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
From: Linus Torvalds <torvalds@linux-foundation.org>
To: Matthew Wilcox <willy@infradead.org>
Cc: Andrew Morton <akpm@linux-foundation.org>,
	Matthew Wilcox <mawilcox@microsoft.com>,
	linux-mm <linux-mm@kvack.org>, Kees Cook <keescook@chromium.org>,
	Linux Kernel Mailing List <linux-kernel@vger.kernel.org>,
	Kernel Hardening <kernel-hardening@lists.openwall.com>
Subject: Re: [PATCH 2/2] mm: Add kvmalloc_ab_c and kvzalloc_struct
Date: Fri, 04 May 2018 15:35:26 +0000	[thread overview]
Message-ID: <CA+55aFy8DSRoUvtiuu5w+XGOK6tYvtJGBH-i8i-y7aiUD2EGLA@mail.gmail.com> (raw)
In-Reply-To: <20180504131441.GA24691@bombadil.infradead.org>

On Fri, May 4, 2018 at 3:14 AM Matthew Wilcox <willy@infradead.org> wrote:

> > In fact, the conversion I saw was buggy. You can *not* convert a
GFP_ATOMIC
> > user of kmalloc() to use kvmalloc.

> Not sure which conversion you're referring to; not one of mine, I hope?

I was thinking of the coccinelle patch in this thread, but just realized
that that actually only did it for GFP_KERNEL, so I guess it would work,
apart from the "oops, now it doesn't enforce the kmalloc limits any more"
issue.

> >   - that divide is really really expensive on many architectures.

> 'c' and 'size' are _supposed_ to be constant and get evaluated at
> compile-time.  ie you should get something like this on x86:

I guess that willalways  be true of the 'kvzalloc_struct() version that
will always use a sizeof(). I was more thinking of any bare kvalloc_ab_c()
cases, but maybe we'd discourage that to ever be used as such?

Because we definitely have things like that, ie a quick grep finds

    f = kmalloc (sizeof (*f) + size*num, GFP_KERNEL);

where 'size' is not obviously a constant. There may be others, but I didn't
really try to grep any further.

Maybe they aren't common, and maybe the occasional divide doesn't matter,
but particularly if we use scripting to then catch and convert users, I
really hate the idea of "let's introduce something that is potentially much
more expensive than it needs to be".

(And the automated coccinelle scripting it's also something where we must
very much avoid then subtly lifting allocation size limits)

> > Something like
> >
> >       if (size > PAGE_SIZE)
> >            return NULL;
> >       if (elem > 65535)
> >            return NULL;
> >       if (offset > PAGE_SIZE)
> >            return NULL;
> >       return kzalloc(size*elem+offset);
> >
> > and now you (a) guarantee it can't overflow and (b) don't make people
use
> > crazy vmalloc() allocations when they damn well shouldn't.

> I find your faith in the size of structs in the kernel touching ;-)

I *really* hope some of those examples of yours aren't allocated with
kmalloc using this pattern..

But yes, I may be naive on the sizes.

> We really have two reasons for using vmalloc -- one is "fragmentation
> currently makes it impossible to allocate enough contiguous memory
> to satisfy your needs" and the other is "this request is for too much
> memory to satisfy through the buddy allocator".  kvmalloc is normally
> (not always; see file descriptor example above) for the first kind of
> problem, but I wonder if kvmalloc() shouldn't have the same limit as
> kmalloc (2048 pages), then add a kvmalloc_large() which will not impose
> that limit check.

That would definitely solve at least one worry.

We do potentially have users which use kmalloc optimistically and do not
want to fall back to vmalloc (they'll fall back to smaller allocations
entirely), but I guess if fwe make sure to not convert any
__GFP_NOWARN/NORETRY users, that should all be ok.

But honestly, I'd rather see just kmalloc users stay as kmalloc users.

If instread of "kzvmalloc_ab_c()" you introduce the "struct size
calculation" part as a "saturating non-overflow calculation", then it
should be fairly easy to just do

   #define kzalloc_struct(p, member, n, gfp) \
      kzalloc(struct_size(p, member, n, gfp)

and you basically *know* that the only thing you changed was purely the
overflow semantics.

That also would take care of my diide worry, because now there  wouldn't be
any ab_c() calculations that might take a non-constant size. The
"struct_size()" thing would always do the sizeof.

So you'd have something like

   /* 'b' and 'c' are always constants */
   static inline sizeof_t __ab_c_saturating(size_t a, size_t b, size_t c)
   {
     if (b && n > (SIZE_MAX -c) / size)
         return SIZE_MAX;
     return a*b+c;
   }
   #define struct_size(p, member, n) \
       __ab_c_saturating(n, \
             sizeof(*(p)->member) + __must_be_array((p)->member), \
             offsetof(typeof(*(p)), member))

and then that kzalloc_struct() wrapper define above should just work.

The above is entirely untested, but it *looks* sane, and avoids all
semantic changes outside of the overflow protection. And nobody would use
that __ab_c_saturating() by mistake, I hope.

No?

               Linus

  reply	other threads:[~2018-05-04 15:35 UTC|newest]

Thread overview: 43+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-02-14 18:26 [PATCH 0/2] Add kvzalloc_struct to complement kvzalloc_array Matthew Wilcox
2018-02-14 18:26 ` [PATCH 1/2] mm: Add kernel-doc for kvfree Matthew Wilcox
2018-02-14 18:26 ` [PATCH 2/2] mm: Add kvmalloc_ab_c and kvzalloc_struct Matthew Wilcox
2018-02-14 19:22   ` Kees Cook
2018-02-14 19:27     ` Julia Lawall
2018-02-14 19:35     ` Matthew Wilcox
2018-03-07 21:18     ` Julia Lawall
2018-03-08  2:58       ` Matthew Wilcox
2018-03-08  6:24         ` Julia Lawall
2018-03-08 23:05           ` Matthew Wilcox
2018-03-09  5:59             ` Julia Lawall
2018-03-13 17:19             ` Julia Lawall
2018-03-13 18:32               ` Matthew Wilcox
2018-03-13 18:35                 ` Julia Lawall
2018-04-29 16:59                 ` Kees Cook
2018-04-29 20:30                   ` Matthew Wilcox
2018-04-30 19:02                     ` Kees Cook
2018-04-30 20:16                       ` Matthew Wilcox
2018-04-30 21:29                         ` Rasmus Villemoes
2018-04-30 22:41                           ` Matthew Wilcox
2018-05-01 17:00                           ` Kees Cook
2018-05-01 17:41                             ` Julia Lawall
2018-05-03 23:00                             ` Rasmus Villemoes
2018-05-04  0:36                               ` Kees Cook
2018-05-04  0:40                                 ` Kees Cook
2018-04-30 22:29                         ` Kees Cook
2018-02-14 19:55   ` Christopher Lameter
2018-02-14 20:14     ` Matthew Wilcox
2018-02-15 15:55       ` Christopher Lameter
2018-02-15 16:23         ` Matthew Wilcox
2018-02-15 17:06           ` Christopher Lameter
2018-02-22  1:28             ` Kees Cook
2018-05-04  7:42   ` Linus Torvalds
2018-05-04 13:14     ` Matthew Wilcox
2018-05-04 15:35       ` Linus Torvalds [this message]
2018-05-04 16:03         ` Kees Cook
2018-02-14 18:47 ` [PATCH 0/2] Add kvzalloc_struct to complement kvzalloc_array Joe Perches
2018-02-14 19:23   ` Kees Cook
2018-02-14 19:32     ` Joe Perches
2018-02-14 19:36       ` Matthew Wilcox
2018-02-14 19:43         ` Joe Perches
2018-02-14 19:56           ` Matthew Wilcox
2018-02-14 20:06             ` Joe Perches

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=CA+55aFy8DSRoUvtiuu5w+XGOK6tYvtJGBH-i8i-y7aiUD2EGLA@mail.gmail.com \
    --to=torvalds@linux-foundation.org \
    --cc=akpm@linux-foundation.org \
    --cc=keescook@chromium.org \
    --cc=kernel-hardening@lists.openwall.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=mawilcox@microsoft.com \
    --cc=willy@infradead.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