public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
From: Alejandro Colomar <alx.manpages@gmail.com>
To: Ariadne Conill <ariadne@dereferenced.org>
Cc: "Damien Miller" <djm@mindrot.org>,
	"Theo de Raadt" <deraadt@openbsd.org>,
	libc-alpha@sourceware.org, "Alejandro Colomar" <alx@kernel.org>,
	"Theo de Raadt" <deraadt@theos.com>,
	"Todd C . Miller" <Todd.Miller@sudo.ws>,
	"Jason A. Donenfeld" <Jason@zx2c4.com>,
	"Cristian Rodríguez" <crrodriguez@opensuse.org>,
	"Adhemerval Zanella" <adhemerval.zanella@linaro.org>,
	"Yann Droneaud" <ydroneaud@opteya.com>,
	"Joseph Myers" <joseph@codesourcery.com>,
	otto@cvs.openbsd.org
Subject: Re: [PATCH] Give a useful meaning to arc4random_uniform(0);
Date: Sun, 1 Jan 2023 15:05:55 +0100	[thread overview]
Message-ID: <0882c84d-c451-2e4a-7e33-ad98585a232c@gmail.com> (raw)
In-Reply-To: <77585c7c-b751-d75a-4bb2-fd9b9de399@dereferenced.org>


[-- Attachment #1.1: Type: text/plain, Size: 4270 bytes --]

Hello Ariadne,

On 1/1/23 08:48, Ariadne Conill wrote:
> On Sun, 1 Jan 2023, Alejandro Colomar via Libc-alpha wrote:
>> On 1/1/23 00:07, Damien Miller wrote:
>> Having a random 32-bit number instead is likely to be a pointer addressing an 
>> invalid memory address, and result in a crash.  And crashes are good, right?
> 
> In scenarios where available address space is constrained, the likelihood of a 
> crash verses state corruption elsewhere in a program is reduced considerably.  I 
> think we should avoid defining interfaces based on the assumption that some 
> minimal amount of address space is available.
> 
>> Changing the behavior of arc4random_uniform() wouldn't make this code more 
>> broken, but rather uncover the bug in it.
> 
> The better approach would be for random_elem to check that there is at least one 
> element available.

Agree.

>  Making arc4random_uniform(0) do something unexpected will 
> probably break legitimate code.  I can think of many situations where 
> arc4random_uniform(0) would be legitimately called.

Please show (and/or link to) some examples, if possible.  I'm really curious.

> 
>>> Therefore IMO the only safe return from arc4random_uniform(0) is 0.
>>
>> I'd argue it's the opposite.  0 is the most unsafe value it can return in such 
>> a case, since it's the least likely to result in a crash.  The Undefined 
>> Behavior is invoked, and in a way that is likely to modify memory that is 
>> available to the process.
> 
> If you are using arc4random_uniform to blindly pick elements out of an array 
> without doing the bounds checking yourself, you're already setting yourself up 
> for failure.  In an ideal world, we would add an additional API which is 
> designed for picking elements and which did this type of bounds check and then 
> failed safely.  Something like:
> 
> inline void *
> arc4random_pickelem(void **elems, size_t elemsize, size_t nelems)
> {
>      if (__builtin_object_size(elems, 0) < (nelems * elemsize)) {
>          errno = EINVAL;
>          return NULL;
>      }
> 
>      ptrdiff_t diff = arc4random_uniform(nelems) * elemsize;
>      return (char *)(elems + diff);
> }
> 
> Changing arc4random_uniform(0) to return non-zero will probably break monte 
> carlo simulations and such which reasonably depend on the behavior that 
> arc4random_uniform(0) == 0.

I don't know that code.  Please show it or link to it.

> 
>>
>> 42 would be a better value.
>> An even better value would be UINT32_MAX, which would almost-certainly 
>> guarantee a crash everywhere.
>> However, it makes more sense to just let it be an unbounded random value, 
>> which will likely result in the same crashes as with UINT32_MAX, but would be 
>> more useful for other purposes.
> 
> What purpose do you envision where arc4random_uniform(0) being non-zero would be 
> considered useful?  If you want to safely pick elements from arrays at random, 
> then we should build an interface for doing this safely, rather then changing 
> the behavior of pre-existing ones.

So far, the only code I've touched myself that needed this is the _range() 
variant that I wrote for selecting a value within a [min, max] range.  I don't 
even need to modify arc4random_uniform(3) for this, because it's not implemented 
in terms of arc4random_uniform(3), but rather in terms of 
arc4random(3)/getrandom(2), and I had to implement the _uniform() API myself. 
Since I didn't look at any existing implementation, I wrote the behavior for (0) 
that was most relevant for my use case, which is to allow the _range() function 
to work well for any input.

I will probably rename my _uniform() implementation to _uniform_wrap(), to avoid 
confusing users.

The manual page doesn't help either, since it doesn't document what happens on 
(0).  Maybe that's something you could add to CAVEATS in you manual page.

You can see the code here:
<https://github.com/shadow-maint/shadow/pull/624/files>

Maybe Jason has more examples to show you from Linux internals, since he 
implemented the same behavior for Linux recently.

> 
> Ariadne

Cheers,
Alex

-- 
<http://www.alejandro-colomar.es/>

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

  parent reply	other threads:[~2023-01-01 14:06 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-12-31  2:36 Alejandro Colomar
2022-12-31  2:48 ` Alejandro Colomar
2022-12-31  2:57 ` Jason A. Donenfeld
2022-12-31 13:39   ` Alejandro Colomar
2022-12-31  8:50 ` Theo de Raadt
2022-12-31  8:51   ` Theo de Raadt
2022-12-31 14:56     ` Alejandro Colomar
2022-12-31 15:13       ` Alejandro Colomar
2022-12-31 15:17         ` Alejandro Colomar
2022-12-31 15:59         ` Alejandro Colomar
2022-12-31 16:03           ` Alejandro Colomar
2023-01-01  8:41           ` Theo de Raadt
2022-12-31 23:07   ` Damien Miller
2022-12-31 23:58     ` Alejandro Colomar
2023-01-01  7:48       ` Ariadne Conill
2023-01-01  9:21         ` Otto Moerbeek
2023-01-01 14:05         ` Alejandro Colomar [this message]
2023-01-01  8:34       ` Theo de Raadt
2023-01-01 21:37 ` Arsen Arsenović
2023-01-01 23:50   ` Alejandro Colomar
2023-01-02  0:02     ` Arsen Arsenović
2023-01-02 11:24       ` Alejandro Colomar

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=0882c84d-c451-2e4a-7e33-ad98585a232c@gmail.com \
    --to=alx.manpages@gmail.com \
    --cc=Jason@zx2c4.com \
    --cc=Todd.Miller@sudo.ws \
    --cc=adhemerval.zanella@linaro.org \
    --cc=alx@kernel.org \
    --cc=ariadne@dereferenced.org \
    --cc=crrodriguez@opensuse.org \
    --cc=deraadt@openbsd.org \
    --cc=deraadt@theos.com \
    --cc=djm@mindrot.org \
    --cc=joseph@codesourcery.com \
    --cc=libc-alpha@sourceware.org \
    --cc=otto@cvs.openbsd.org \
    --cc=ydroneaud@opteya.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 read-only IMAP folder(s) and NNTP newsgroup(s).