lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CAHk-=witf7e1QRp29tAeHLB34HuBSO5G7q82cmd-mAPSt+0JVg@mail.gmail.com>
Date: Thu, 25 Sep 2025 19:36:13 -0700
From: Linus Torvalds <torvalds@...ux-foundation.org>
To: Kees Cook <kees@...nel.org>
Cc: Andrew Morton <akpm@...ux-foundation.org>, Alejandro Colomar <alx@...nel.org>, 
	Linux Kernel Mailing List <linux-kernel@...r.kernel.org>, 
	Christopher Bazley <chris.bazley.wg14@...il.com>, Rasmus Villemoes <linux@...musvillemoes.dk>, 
	Marco Elver <elver@...gle.com>, Michal Hocko <mhocko@...e.com>, Al Viro <viro@...iv.linux.org.uk>, 
	Alexander Potapenko <glider@...gle.com>, Dmitry Vyukov <dvyukov@...gle.com>, Jann Horn <jannh@...gle.com>
Subject: Re: [PATCH v1 0/3] Add ENDOF(), and use it to fix off-by-one bugs

On Thu, 25 Sept 2025 at 18:31, Kees Cook <kees@...nel.org> wrote:
>
> I can have an opinion about the relative safety of holding pointers that
> can't be safely dereferenced, though. :) But yes, I've long since lost
> the argument that C should avoid these kinds of past-the-end tokens.

The thing is, the "start+len" model is actually *safer* than the
"start+len-1" model.

It's safer because it's simpler and doesn't involve the whole
"subtract one" (and then when you have the "past the end" it's also
easy to calculate "how much is left").

So it's simpler, and it's explicitly supported by the standard.

It's also more strictly correct, because "start+len-1" is technically
not a valid pointer at all. The C standard makes the "past the end"
case explicitly valid, but not the "before the beginning".

Now, I'm the last person to say that the C standard is always correct
- there's a lot of garbage in there, but in this case it also happens
to match the notion of "this works".

Because the "pointer to the last byte" model DOES NOT WORK.

In C, NULL is actually a valid pointer for zero-sized elements.

Yes, really.

The C standard says that "malloc(0)" can return NULL, without it being
an error. So the tuple "NULL, 0" is actually a perfectly valid
"pointer and length" pair, and one that you may actually get thanks to
how malloc() works.

Obviously you cannot dereference a zero-sized object, but zero-sized
objects aren't "wrong" per se.

Now, I happen to believe that the "return NULL for zero sized
allocations" it's not a great model (it also makes error checking more
complicated). So the kernel kmalloc() function actually returns a
different pointer that cannot be dereferenced (grep for
ZERO_SIZE_PTR).

But my point is that "ptr+len" actually *works* for that case.

The "ptr+len-1" loop thing you gave as an example not only is invalid
C for zero-sized cases, it simply does not even work at all for the
NULL case.

Your example loop of how things should work IS WRONG.

Yes, it happens to work as long as you never have zero-sized things,
but it really is a bad pattern.

This is not "opinion". This is just a plain fact about how C works.
"start+len" is well-defined. "start+len-1" is NOT.

               Linus

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ