Am Freitag, dem 14.06.2024 um 12:17 +0200 schrieb Peter Zijlstra: > On Wed, Jun 12, 2024 at 04:23:31PM -0700, Kees Cook wrote: > > On Thu, Jun 13, 2024 at 12:08:21AM +0200, Peter Zijlstra wrote: > > > On Wed, Jun 12, 2024 at 12:01:19PM -0700, Kees Cook wrote: > > > > I'm happy to take patches. And for this bikeshed, this would be better > > > > named under the size_*() helpers which are trying to keep size_t > > > > calculations from overflowing (by saturating). i.e.: > > > > > > > > size_add_mult(sizeof(*p), sizeof(*p->member), num) > > > > > > Fine I suppose, but what if we want something not size_t? Are we waiting > > > for the type system extension? > > > > Because of C's implicit promotion/truncation, we can't do anything > > sanely with return values of arbitrary type size; we have to capture the > > lvalue type somehow so the checking can happen without C doing silent > > garbage.
What is the specific problem here? > > So sizeof() returns the native (built-in) size_t, right? If that type > the nooverflow qualifier on, then: > > sizeof(*p) + num*sizeof(p->foo[0]) > > should all get the nooverflow semantics right? Because size_t is > effectively 'nooverflow unsigned long' the multiplication should promote > 'num' to some 'long'. > > Now, I've re-read the rules and I don't see qualifiers mentioned, so > can't we state that the overflow/nooverflow qualifiers are to be > preserved on (implicit) promotion and when nooverflow and overflow are > combined the 'safe' nooverflow takes precedence? > > I mean, when we're adding qualifiers we can make up rules about them > too, right? It should probably be a type attribute. > > If 'people' don't want to adorn the built-in size_t, we can always do > something like: > > #define sizeof(x) ((nooverflow unsigned long)(sizeof(x))) > > and 'fix' it ourselves. This is likely a stupid question, but making it signed wouldn't work? Or is a signed size_t too small or some architectures? Or would this change break too much? Martin > > > > But none of that is showing me generated asm for the various cases. As > > > such, I don't consider myself informed enough. > > > > Gotcha. For the compile-time stuff it's all just looking at > > known-at-compile-time sizes. So for something like this, we get a > > __compiletime_warning() emitted: > > > > const char src[] = "Hello there"; > > char dst[10]; > > > > strscpy(dst, src); /* Compiler yells since src is bigger than dst. */ > > > > For run-time checks it's basically just using the regular WARN() > > infrastructure with __builtin_dynamic_object_size(). Here's a simplified > > userspace example with assert(): > > > > https://godbolt.org/z/zMrKnMxn5 > > > > The kernel's FORTIFY_SOURCE is much more complex in how it does the > > checking, how it does the reporting (for helping people figure out what's > > gone weird), etc. > > Thanks, I'll go have a look at that.