mailing list of musl libc
 help / color / mirror / code / Atom feed
* getrandom syscall
@ 2015-01-27 22:12 Daniel Cegiełka
  2015-01-28  9:02 ` Szabolcs Nagy
  2015-01-28 14:54 ` Rich Felker
  0 siblings, 2 replies; 25+ messages in thread
From: Daniel Cegiełka @ 2015-01-27 22:12 UTC (permalink / raw)
  To: musl

[-- Attachment #1: Type: text/plain, Size: 21 bytes --]

best regards,
Daniel

[-- Attachment #2: getrandom.c --]
[-- Type: text/x-csrc, Size: 333 bytes --]

#include <stddef.h>
#include <errno.h>
#include "syscall.h"

int getrandom(void *buf, size_t len)
{
	int ret, pre_errno = errno;

	if (len > 256) {
		errno = EIO;
		return -1;
	}
	do {
		ret = syscall(SYS_getrandom, buf, len, 0);
	} while (ret == -1 && errno == EINTR);
	if (ret != len)
		return -1;
	errno = pre_errno;
	return 0;
}

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: getrandom syscall
  2015-01-27 22:12 getrandom syscall Daniel Cegiełka
@ 2015-01-28  9:02 ` Szabolcs Nagy
  2015-01-28  9:10   ` Daniel Cegiełka
  2015-01-28 14:54 ` Rich Felker
  1 sibling, 1 reply; 25+ messages in thread
From: Szabolcs Nagy @ 2015-01-28  9:02 UTC (permalink / raw)
  To: musl

* Daniel Cegie??ka <daniel.cegielka@gmail.com> [2015-01-27 23:12:46 +0100]:
> #include <stddef.h>
> #include <errno.h>
> #include "syscall.h"
> 

#ifdef SYS_getrandom

> int getrandom(void *buf, size_t len)
> {
> 	int ret, pre_errno = errno;
> 
> 	if (len > 256) {
> 		errno = EIO;
> 		return -1;
> 	}
> 	do {
> 		ret = syscall(SYS_getrandom, buf, len, 0);
> 	} while (ret == -1 && errno == EINTR);
> 	if (ret != len)
> 		return -1;
> 	errno = pre_errno;
> 	return 0;
> }

#endif

eg sh does not have the syscall (linux is not consistent with
syscalls for whatever reason)


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: getrandom syscall
  2015-01-28  9:02 ` Szabolcs Nagy
@ 2015-01-28  9:10   ` Daniel Cegiełka
  2015-01-28 12:26     ` Szabolcs Nagy
  0 siblings, 1 reply; 25+ messages in thread
From: Daniel Cegiełka @ 2015-01-28  9:10 UTC (permalink / raw)
  To: musl

2015-01-28 10:02 GMT+01:00 Szabolcs Nagy <nsz@port70.net>:
> * Daniel Cegie??ka <daniel.cegielka@gmail.com> [2015-01-27 23:12:46 +0100]:
>> #include <stddef.h>
>> #include <errno.h>
>> #include "syscall.h"
>>
>
> #ifdef SYS_getrandom
>
>> int getrandom(void *buf, size_t len)
>> {
>>       int ret, pre_errno = errno;
>>
>>       if (len > 256) {
>>               errno = EIO;
>>               return -1;
>>       }
>>       do {
>>               ret = syscall(SYS_getrandom, buf, len, 0);
>>       } while (ret == -1 && errno == EINTR);
>>       if (ret != len)
>>               return -1;
>>       errno = pre_errno;
>>       return 0;
>> }
>
> #endif
>
> eg sh does not have the syscall (linux is not consistent with
> syscalls for whatever reason)

SYS_getrandom is defined on musl, so #ifdef SYS_getrandom is not a
good solution:

http://git.musl-libc.org/cgit/musl/tree/arch/x86_64/bits/syscall.h#n657

It's better to return an error.

Daniel


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: getrandom syscall
  2015-01-28  9:10   ` Daniel Cegiełka
@ 2015-01-28 12:26     ` Szabolcs Nagy
  2015-01-28 12:42       ` Daniel Cegiełka
  0 siblings, 1 reply; 25+ messages in thread
From: Szabolcs Nagy @ 2015-01-28 12:26 UTC (permalink / raw)
  To: musl

* Daniel Cegie??ka <daniel.cegielka@gmail.com> [2015-01-28 10:10:53 +0100]:
> 2015-01-28 10:02 GMT+01:00 Szabolcs Nagy <nsz@port70.net>:
> >
> > #ifdef SYS_getrandom
...
> > #endif
> >
> > eg sh does not have the syscall (linux is not consistent with
> > syscalls for whatever reason)
> 
> SYS_getrandom is defined on musl, so #ifdef SYS_getrandom is not a
> good solution:
> 
> http://git.musl-libc.org/cgit/musl/tree/arch/x86_64/bits/syscall.h#n657
> 
> It's better to return an error.

no

you should return runtime error if the syscall fails
(eg you are on old kernel that does not support the syscall)

but you cannot use this code if SYS_getrandom is not
defined (eg. sh arch) because it will be a musl
compile time failure (sadly linux does not allocate
syscall numbers on all archs so musl cannot define
all SYS_ macros consistently on all archs either)


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: getrandom syscall
  2015-01-28 12:26     ` Szabolcs Nagy
@ 2015-01-28 12:42       ` Daniel Cegiełka
  2015-01-28 14:49         ` Rich Felker
  0 siblings, 1 reply; 25+ messages in thread
From: Daniel Cegiełka @ 2015-01-28 12:42 UTC (permalink / raw)
  To: musl

2015-01-28 13:26 GMT+01:00 Szabolcs Nagy <nsz@port70.net>:
> * Daniel Cegie??ka <daniel.cegielka@gmail.com> [2015-01-28 10:10:53 +0100]:
>> 2015-01-28 10:02 GMT+01:00 Szabolcs Nagy <nsz@port70.net>:
>> >
>> > #ifdef SYS_getrandom
> ...
>> > #endif
>> >
>> > eg sh does not have the syscall (linux is not consistent with
>> > syscalls for whatever reason)
>>
>> SYS_getrandom is defined on musl, so #ifdef SYS_getrandom is not a
>> good solution:
>>
>> http://git.musl-libc.org/cgit/musl/tree/arch/x86_64/bits/syscall.h#n657
>>
>> It's better to return an error.
>
> no
>
> you should return runtime error if the syscall fails
> (eg you are on old kernel that does not support the syscall)
>
> but you cannot use this code if SYS_getrandom is not
> defined (eg. sh arch) because it will be a musl
> compile time failure (sadly linux does not allocate
> syscall numbers on all archs so musl cannot define
> all SYS_ macros consistently on all archs either)

Indeed. I considered the kernel version check, but it is ugly
approach. #ifdef SYS_getrandom we should add also add to the header
file (stdlib.h?). Is this code will be approved for musl?

Daniel


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: getrandom syscall
  2015-01-28 12:42       ` Daniel Cegiełka
@ 2015-01-28 14:49         ` Rich Felker
  0 siblings, 0 replies; 25+ messages in thread
From: Rich Felker @ 2015-01-28 14:49 UTC (permalink / raw)
  To: musl

On Wed, Jan 28, 2015 at 01:42:23PM +0100, Daniel Cegiełka wrote:
> 2015-01-28 13:26 GMT+01:00 Szabolcs Nagy <nsz@port70.net>:
> > * Daniel Cegie??ka <daniel.cegielka@gmail.com> [2015-01-28 10:10:53 +0100]:
> >> 2015-01-28 10:02 GMT+01:00 Szabolcs Nagy <nsz@port70.net>:
> >> >
> >> > #ifdef SYS_getrandom
> > ...
> >> > #endif
> >> >
> >> > eg sh does not have the syscall (linux is not consistent with
> >> > syscalls for whatever reason)
> >>
> >> SYS_getrandom is defined on musl, so #ifdef SYS_getrandom is not a
> >> good solution:
> >>
> >> http://git.musl-libc.org/cgit/musl/tree/arch/x86_64/bits/syscall.h#n657
> >>
> >> It's better to return an error.
> >
> > no
> >
> > you should return runtime error if the syscall fails
> > (eg you are on old kernel that does not support the syscall)
> >
> > but you cannot use this code if SYS_getrandom is not
> > defined (eg. sh arch) because it will be a musl
> > compile time failure (sadly linux does not allocate
> > syscall numbers on all archs so musl cannot define
> > all SYS_ macros consistently on all archs either)
> 
> Indeed. I considered the kernel version check, but it is ugly
> approach. #ifdef SYS_getrandom we should add also add to the header
> file (stdlib.h?). Is this code will be approved for musl?

No, the header can't see the syscalls list. You can prototype the
function even if it's not defined; it won't hurt. But rather than
leaving it undefined, I think it should just return an error of ENOSYS
if the SYS_getrandom macro is not defined.

Rich


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: getrandom syscall
  2015-01-27 22:12 getrandom syscall Daniel Cegiełka
  2015-01-28  9:02 ` Szabolcs Nagy
@ 2015-01-28 14:54 ` Rich Felker
  2015-01-28 15:41   ` Szabolcs Nagy
  2015-01-28 15:41   ` Daniel Cegiełka
  1 sibling, 2 replies; 25+ messages in thread
From: Rich Felker @ 2015-01-28 14:54 UTC (permalink / raw)
  To: musl

On Tue, Jan 27, 2015 at 11:12:46PM +0100, Daniel Cegiełka wrote:
> best regards,
> Daniel

Thanks. I've been wanting to get this added as well as a getentropy
function (the other API for the same thing).

> #include <stddef.h>
> #include <errno.h>
> #include "syscall.h"
> 
> int getrandom(void *buf, size_t len)
> {
> 	int ret, pre_errno = errno;

There's no need to save/restore errno here. errno is only meaningful
after a function returns an error code. On success it should not be
inspected and could contain junk.

> 	if (len > 256) {
> 		errno = EIO;
> 		return -1;
> 	}

Could you explain the motivation for this part?

> 	do {
> 		ret = syscall(SYS_getrandom, buf, len, 0);
> 	} while (ret == -1 && errno == EINTR);

This would be more efficient (and avoid your errno issue entirely) if
you use __syscall which returns -errcode rather than storing errcode
in errno. It allows the whole loop to be inlined with no function
call. Something like:

	while ((ret = __syscall(SYS_getrandom, buf, len, 0)) == -EINTR);

Of course there's the question of whether it should loop on EINTR
anyway; I don't know. Also if this can block there's the question of
whether it should be cancellable, but that can be decided later.

Finally, I wonder if it would make sense to use other fallbacks in the
case where the syscall is not supported -- perhaps the aux vector
AT_RANDOM or even /dev/urandom? (But I'd rather avoid doing anything
that depends on fds, which would make a function that appears to
always-work but actually fails on resource exhaustion.)

Rich


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: getrandom syscall
  2015-01-28 14:54 ` Rich Felker
@ 2015-01-28 15:41   ` Szabolcs Nagy
  2015-01-28 15:50     ` Daniel Cegiełka
  2015-01-28 16:01     ` Daniel Cegiełka
  2015-01-28 15:41   ` Daniel Cegiełka
  1 sibling, 2 replies; 25+ messages in thread
From: Szabolcs Nagy @ 2015-01-28 15:41 UTC (permalink / raw)
  To: musl

* Rich Felker <dalias@libc.org> [2015-01-28 09:54:10 -0500]:
> On Tue, Jan 27, 2015 at 11:12:46PM +0100, Daniel Cegie??ka wrote:
> > 
> > int getrandom(void *buf, size_t len)

i just noticed the signature

where did this signature come from?
glibc does not have it and bsds have getentropy

the linux syscall is

int getrandom(void *buf, size_t buflen, unsigned int flags);

although it's not yet documented as far as i can see:

http://man7.org/linux/man-pages/man2/syscalls.2.html


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: getrandom syscall
  2015-01-28 14:54 ` Rich Felker
  2015-01-28 15:41   ` Szabolcs Nagy
@ 2015-01-28 15:41   ` Daniel Cegiełka
  1 sibling, 0 replies; 25+ messages in thread
From: Daniel Cegiełka @ 2015-01-28 15:41 UTC (permalink / raw)
  To: musl

2015-01-28 15:54 GMT+01:00 Rich Felker <dalias@libc.org>:
> On Tue, Jan 27, 2015 at 11:12:46PM +0100, Daniel Cegiełka wrote:
>> best regards,
>> Daniel
>
> Thanks. I've been wanting to get this added as well as a getentropy
> function (the other API for the same thing).

Here is a Theodore Tso version:

https://lkml.org/lkml/2014/7/17/474

+wrapper for getentropy():

https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=c6e9d6f38894798696f23c8084ca7edbf16ee895

>
>> #include <stddef.h>
>> #include <errno.h>
>> #include "syscall.h"
>>
>> int getrandom(void *buf, size_t len)
>> {
>>       int ret, pre_errno = errno;
>
> There's no need to save/restore errno here. errno is only meaningful
> after a function returns an error code. On success it should not be
> inspected and could contain junk.
>
>>       if (len > 256) {
>>               errno = EIO;
>>               return -1;
>>       }
>
> Could you explain the motivation for this part?

If you request a large number of bytes you’re going to wait while they
are being computed. It make no sense, so getrandom returns an error if
the requested is over 256 bytes (__it's worth it thoroughly
investigate__).

https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=c6e9d6f38894798696f23c8084ca7edbf16ee895

"""
Theodore Tso 2014-07-23 15:11:06 UTC

The bug should be fixed if you cherry-pick commit
79a8468747c5f95ed3d5ce8376a3e82e0c5857fc into 3.15.4+.   Please let me
know if it doesn't.

Why on *earth* are you using /dev/urandom in this way?   The nbytes
restriction is to prevent an accounting failure since we are now
tracking entropy in fractional bits, so when we convert bytes
requested into fractional bits, we overflow if someone tries to
request more than 32MB.  Given that no sane use of /dev/urandom needs
more than 256 bytes, this was considered acceptable.
"""

https://bugzilla.kernel.org/show_bug.cgi?id=80981

but I don't have certainty about this.


>>       do {
>>               ret = syscall(SYS_getrandom, buf, len, 0);
>>       } while (ret == -1 && errno == EINTR);
>
> This would be more efficient (and avoid your errno issue entirely) if
> you use __syscall which returns -errcode rather than storing errcode
> in errno. It allows the whole loop to be inlined with no function
> call. Something like:
>
>         while ((ret = __syscall(SYS_getrandom, buf, len, 0)) == -EINTR);
>
> Of course there's the question of whether it should loop on EINTR
> anyway; I don't know. Also if this can block there's the question of
> whether it should be cancellable, but that can be decided later.
>
> Finally, I wonder if it would make sense to use other fallbacks in the
> case where the syscall is not supported -- perhaps the aux vector
> AT_RANDOM or even /dev/urandom? (But I'd rather avoid doing anything
> that depends on fds, which would make a function that appears to
> always-work but actually fails on resource exhaustion.)

Thanks,
Daniel


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: getrandom syscall
  2015-01-28 15:41   ` Szabolcs Nagy
@ 2015-01-28 15:50     ` Daniel Cegiełka
  2015-01-28 16:03       ` Szabolcs Nagy
  2015-01-28 16:01     ` Daniel Cegiełka
  1 sibling, 1 reply; 25+ messages in thread
From: Daniel Cegiełka @ 2015-01-28 15:50 UTC (permalink / raw)
  To: musl

2015-01-28 16:41 GMT+01:00 Szabolcs Nagy <nsz@port70.net>:
> * Rich Felker <dalias@libc.org> [2015-01-28 09:54:10 -0500]:
>> On Tue, Jan 27, 2015 at 11:12:46PM +0100, Daniel Cegie??ka wrote:
>> >
>> > int getrandom(void *buf, size_t len)
>
> i just noticed the signature
>
> where did this signature come from?
> glibc does not have it and bsds have getentropy
>
> the linux syscall is
>
> int getrandom(void *buf, size_t buflen, unsigned int flags);
>
> although it's not yet documented as far as i can see:
>
> http://man7.org/linux/man-pages/man2/syscalls.2.html

https://sourceware.org/bugzilla/show_bug.cgi?id=17252

Daniel


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: getrandom syscall
  2015-01-28 15:41   ` Szabolcs Nagy
  2015-01-28 15:50     ` Daniel Cegiełka
@ 2015-01-28 16:01     ` Daniel Cegiełka
  1 sibling, 0 replies; 25+ messages in thread
From: Daniel Cegiełka @ 2015-01-28 16:01 UTC (permalink / raw)
  To: musl

2015-01-28 16:41 GMT+01:00 Szabolcs Nagy <nsz@port70.net>:
> * Rich Felker <dalias@libc.org> [2015-01-28 09:54:10 -0500]:
>> On Tue, Jan 27, 2015 at 11:12:46PM +0100, Daniel Cegie??ka wrote:
>> >
>> > int getrandom(void *buf, size_t len)
>
> i just noticed the signature
>
> where did this signature come from?
> glibc does not have it and bsds have getentropy
>
> the linux syscall is
>
> int getrandom(void *buf, size_t buflen, unsigned int flags);

Sorry! My mistake. Needed are two different versions (getrandom and
getentropy). I hurried too much...


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: getrandom syscall
  2015-01-28 15:50     ` Daniel Cegiełka
@ 2015-01-28 16:03       ` Szabolcs Nagy
  2015-01-28 16:12         ` Daniel Cegiełka
  2015-01-28 16:25         ` Daniel Cegiełka
  0 siblings, 2 replies; 25+ messages in thread
From: Szabolcs Nagy @ 2015-01-28 16:03 UTC (permalink / raw)
  To: musl

* Daniel Cegie??ka <daniel.cegielka@gmail.com> [2015-01-28 16:50:04 +0100]:
> 2015-01-28 16:41 GMT+01:00 Szabolcs Nagy <nsz@port70.net>:
...
> >> > int getrandom(void *buf, size_t len)
> >
> > where did this signature come from?
...
> https://sourceware.org/bugzilla/show_bug.cgi?id=17252
> 

i dont see any function prototype discussed there

exposing this syscall without the flags makes no sense to me


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: getrandom syscall
  2015-01-28 16:03       ` Szabolcs Nagy
@ 2015-01-28 16:12         ` Daniel Cegiełka
  2015-01-28 16:21           ` Rich Felker
  2015-01-28 16:25         ` Daniel Cegiełka
  1 sibling, 1 reply; 25+ messages in thread
From: Daniel Cegiełka @ 2015-01-28 16:12 UTC (permalink / raw)
  To: musl

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



[-- Attachment #2: getentropy.c --]
[-- Type: text/x-csrc, Size: 220 bytes --]

int getentropy(void *buf, size_t buflen)
{
	int ret;

	if (buflen > 256)
		goto failure;
	ret = getrandom(buf, buflen, 0);
	if (ret < 0)
		return ret;
	if (ret == buflen)
		return 0;
failure:
	errno = EIO;
	return -1;
}

[-- Attachment #3: getrandom.c --]
[-- Type: text/x-csrc, Size: 138 bytes --]

#include "syscall.h"

int getrandom(void *buf, size_t buflen, unsigned int flags)
{
	return syscall(SYS_getrandom, buf, buflen, flags);
}

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: getrandom syscall
  2015-01-28 16:12         ` Daniel Cegiełka
@ 2015-01-28 16:21           ` Rich Felker
  2015-01-28 17:02             ` Daniel Cegiełka
  0 siblings, 1 reply; 25+ messages in thread
From: Rich Felker @ 2015-01-28 16:21 UTC (permalink / raw)
  To: musl

On Wed, Jan 28, 2015 at 05:12:31PM +0100, Daniel Cegiełka wrote:
> 
> int getentropy(void *buf, size_t buflen)
> {
> 	int ret;
> 
> 	if (buflen > 256)
> 		goto failure;
> 	ret = getrandom(buf, buflen, 0);
> 	if (ret < 0)
> 		return ret;
> 	if (ret == buflen)
> 		return 0;
> failure:
> 	errno = EIO;
> 	return -1;
> }

Is it intentional to fall through to failure when ret is positive but
less than buflen? Can this happen?

> #include "syscall.h"
> 
> int getrandom(void *buf, size_t buflen, unsigned int flags)
> {
> 	return syscall(SYS_getrandom, buf, buflen, flags);
> }

If I read the documentation correctly, the removed EINTR handling is
irrelevant since the kernel guarantees not to EINTR for <=256 bytes
with the default flags, right?

Rich


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: getrandom syscall
  2015-01-28 16:03       ` Szabolcs Nagy
  2015-01-28 16:12         ` Daniel Cegiełka
@ 2015-01-28 16:25         ` Daniel Cegiełka
  1 sibling, 0 replies; 25+ messages in thread
From: Daniel Cegiełka @ 2015-01-28 16:25 UTC (permalink / raw)
  To: musl

2015-01-28 17:03 GMT+01:00 Szabolcs Nagy <nsz@port70.net>:

>
> i dont see any function prototype discussed there
>
> exposing this syscall without the flags makes no sense to me

Yes, that was my mistake. I had read about long time block above 256
bytes, and by mistake I did not pay attention to what actually I sent.
syscall is now clean and safe version is getentropy. Sorry for that.


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: getrandom syscall
  2015-01-28 16:21           ` Rich Felker
@ 2015-01-28 17:02             ` Daniel Cegiełka
  2015-01-28 17:09               ` Daniel Cegiełka
  0 siblings, 1 reply; 25+ messages in thread
From: Daniel Cegiełka @ 2015-01-28 17:02 UTC (permalink / raw)
  To: musl

[-- Attachment #1: Type: text/plain, Size: 1077 bytes --]

2015-01-28 17:21 GMT+01:00 Rich Felker <dalias@libc.org>:
> On Wed, Jan 28, 2015 at 05:12:31PM +0100, Daniel Cegiełka wrote:
>>
>> int getentropy(void *buf, size_t buflen)
>> {
>>       int ret;
>>
>>       if (buflen > 256)
>>               goto failure;
>>       ret = getrandom(buf, buflen, 0);
>>       if (ret < 0)
>>               return ret;
>>       if (ret == buflen)
>>               return 0;
>> failure:
>>       errno = EIO;
>>       return -1;
>> }
>
> Is it intentional to fall through to failure when ret is positive but
> less than buflen? Can this happen?

This is a Theodore Tso version...


>
>> #include "syscall.h"
>>
>> int getrandom(void *buf, size_t buflen, unsigned int flags)
>> {
>>       return syscall(SYS_getrandom, buf, buflen, flags);
>> }
>
> If I read the documentation correctly, the removed EINTR handling is
> irrelevant since the kernel guarantees not to EINTR for <=256 bytes
> with the default flags, right?

yes, and if it is above 256, it can be blocked and there is no guarantee.



> Rich

[-- Attachment #2: getentropy.c --]
[-- Type: text/x-csrc, Size: 248 bytes --]

int getentropy(void *buf, size_t len)
{
	int ret, pre_errno = errno;

	if (len > 256) {
		errno = EIO;
		return -1;
	}
	while ((ret = __syscall(SYS_getrandom, buf, len, 0)) == -EINTR);
	if (ret != len)
		return -1;
	errno = pre_errno;
	return 0;
}

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: getrandom syscall
  2015-01-28 17:02             ` Daniel Cegiełka
@ 2015-01-28 17:09               ` Daniel Cegiełka
  2015-01-28 17:43                 ` Brent Cook
  0 siblings, 1 reply; 25+ messages in thread
From: Daniel Cegiełka @ 2015-01-28 17:09 UTC (permalink / raw)
  To: musl

An interesting description of the topic:

http://rg3.name/201410191206.html

Daniel


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: getrandom syscall
  2015-01-28 17:09               ` Daniel Cegiełka
@ 2015-01-28 17:43                 ` Brent Cook
  2015-01-28 18:12                   ` Daniel Cegiełka
  2015-01-28 19:17                   ` Rich Felker
  0 siblings, 2 replies; 25+ messages in thread
From: Brent Cook @ 2015-01-28 17:43 UTC (permalink / raw)
  To: musl

Here is the wrapper in LibreSSL for getrandom, to hopefully lend to
the discussion:

https://github.com/libressl-portable/openbsd/blob/master/src/lib/libcrypto/crypto/getentropy_linux.c#L194

It tries to avoid a couple of possible issues. FIrst, while <= 256
byte getrandom should not interrupt, it appears that if the kernel
entropy pool has not been initialized yet, it would still return EINTR
if called early enough in the boot process. How likely this is in
practice, I don't know.

Then, to avoid modifying errno even though there was an actual
success, the wrapper restores the previous errno value when it
succeeds.

I just realized that the length check in getentropy_getrandom() is
redundant, since it is checked earlier in getentropy() as well, but
hopefully this is helpful.

If a getentropy() were added to musl libc, but in such a way that it
might fail on older kernels, that would cause some problems with
LibreSSL, and now OpenNTPD. They will both try to use getentropy()
with arc4random() if it is found in a system, and arc4random() will
treat a getentropy() failure as fatal.

Thanks, and good discussion.


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: getrandom syscall
  2015-01-28 17:43                 ` Brent Cook
@ 2015-01-28 18:12                   ` Daniel Cegiełka
  2015-01-28 19:17                   ` Rich Felker
  1 sibling, 0 replies; 25+ messages in thread
From: Daniel Cegiełka @ 2015-01-28 18:12 UTC (permalink / raw)
  To: musl

2015-01-28 18:43 GMT+01:00 Brent Cook <busterb@gmail.com>:
> Here is the wrapper in LibreSSL for getrandom, to hopefully lend to
> the discussion:
>
> https://github.com/libressl-portable/openbsd/blob/master/src/lib/libcrypto/crypto/getentropy_linux.c#L194
>
> It tries to avoid a couple of possible issues. FIrst, while <= 256
> byte getrandom should not interrupt, it appears that if the kernel
> entropy pool has not been initialized yet, it would still return EINTR
> if called early enough in the boot process. How likely this is in
> practice, I don't know.
>
> Then, to avoid modifying errno even though there was an actual
> success, the wrapper restores the previous errno value when it
> succeeds.
>
> I just realized that the length check in getentropy_getrandom() is
> redundant, since it is checked earlier in getentropy() as well, but
> hopefully this is helpful.
>
> If a getentropy() were added to musl libc, but in such a way that it
> might fail on older kernels, that would cause some problems with
> LibreSSL, and now OpenNTPD. They will both try to use getentropy()
> with arc4random() if it is found in a system, and arc4random() will
> treat a getentropy() failure as fatal.

Thank you for your feedback. That's right, arc4random() sometimes
ended with an abort() and this is a huge problem. I used  /dev/urandom
as a source of entropy for arc4random(), but it can fail (eg. in a
chroot), so if arc4random() calls abort(), then the whole process
ends.

btw. thanks for your work on OpenNTPD. I was planning to send an
adjtimex() patch, but I see that you already did:

https://github.com/openntpd-portable/openntpd-portable/commit/eeb97529cd5a332a69a312687e41939eb17f7a81

Daniel

> Thanks, and good discussion.


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: getrandom syscall
  2015-01-28 17:43                 ` Brent Cook
  2015-01-28 18:12                   ` Daniel Cegiełka
@ 2015-01-28 19:17                   ` Rich Felker
  2015-01-28 19:33                     ` Daniel Cegiełka
  2015-01-28 20:20                     ` Brent Cook
  1 sibling, 2 replies; 25+ messages in thread
From: Rich Felker @ 2015-01-28 19:17 UTC (permalink / raw)
  To: musl

On Wed, Jan 28, 2015 at 11:43:17AM -0600, Brent Cook wrote:
> Here is the wrapper in LibreSSL for getrandom, to hopefully lend to
> the discussion:
> 
> https://github.com/libressl-portable/openbsd/blob/master/src/lib/libcrypto/crypto/getentropy_linux.c#L194

This version is failing to set errno when rejecting len>256, which
looks bad.

> It tries to avoid a couple of possible issues. FIrst, while <= 256
> byte getrandom should not interrupt, it appears that if the kernel
> entropy pool has not been initialized yet, it would still return EINTR
> if called early enough in the boot process. How likely this is in
> practice, I don't know.

You mean it would block and be subject to EINTR if a signal occurs? In
this case I would think you'd probably _want_ the EINTR to cause it to
fail. I can imagine an early-boot program using SIGALRM to prevent
waiting too-long/forever for entropy that's not going to arrive.

> Then, to avoid modifying errno even though there was an actual
> success, the wrapper restores the previous errno value when it
> succeeds.

Avoiding modification of errno when the call succeeds is not necessary
or desirable. Callers should not be assuming errno is untouched after
success.

> I just realized that the length check in getentropy_getrandom() is
> redundant, since it is checked earlier in getentropy() as well, but
> hopefully this is helpful.

Indeed, that masks the issue I mentioned above.

So, their version of getentropy is aiming to provide a meaningful
result even on systems that don't have SYS_getrandom. Should we be
doing the same?

> If a getentropy() were added to musl libc, but in such a way that it
> might fail on older kernels, that would cause some problems with
> LibreSSL, and now OpenNTPD. They will both try to use getentropy()
> with arc4random() if it is found in a system, and arc4random() will
> treat a getentropy() failure as fatal.

Yes, this sounds bad. So what fallbacks should we implement? Do we
need a strong CSPRNG on top of AT_RANDOM?

Rich


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: getrandom syscall
  2015-01-28 19:17                   ` Rich Felker
@ 2015-01-28 19:33                     ` Daniel Cegiełka
  2015-01-28 20:20                     ` Brent Cook
  1 sibling, 0 replies; 25+ messages in thread
From: Daniel Cegiełka @ 2015-01-28 19:33 UTC (permalink / raw)
  To: musl

2015-01-28 20:17 GMT+01:00 Rich Felker <dalias@libc.org>:
> On Wed, Jan 28, 2015 at 11:43:17AM -0600, Brent Cook wrote:
>> Here is the wrapper in LibreSSL for getrandom, to hopefully lend to
>> the discussion:
>>
>> https://github.com/libressl-portable/openbsd/blob/master/src/lib/libcrypto/crypto/getentropy_linux.c#L194
>
> This version is failing to set errno when rejecting len>256, which
> looks bad.

http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man2/getentropy.2?query=getentropy&sec=2

linux getrandom() is not limited to 256 bytes, but len>256 bytes is problematic.

Very similar and so different :)

Daniel

> Rich


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: getrandom syscall
  2015-01-28 19:17                   ` Rich Felker
  2015-01-28 19:33                     ` Daniel Cegiełka
@ 2015-01-28 20:20                     ` Brent Cook
  2015-01-28 22:02                       ` Rich Felker
  1 sibling, 1 reply; 25+ messages in thread
From: Brent Cook @ 2015-01-28 20:20 UTC (permalink / raw)
  To: musl


> On Jan 28, 2015, at 1:17 PM, Rich Felker <dalias@libc.org> wrote:
> 
> On Wed, Jan 28, 2015 at 11:43:17AM -0600, Brent Cook wrote:
>> Here is the wrapper in LibreSSL for getrandom, to hopefully lend to
>> the discussion:
>> 
>> https://github.com/libressl-portable/openbsd/blob/master/src/lib/libcrypto/crypto/getentropy_linux.c#L194
> 
> This version is failing to set errno when rejecting len>256, which
> looks bad.

Right, it's not actually a problem in context of the whole file.
This is just the first of several fallbacks called by getentropy.

I think that was there originally just to remind what the limit is
before it changes blocking behavior. In this context, it can also fail
with ENOSYS too, so this on function is not a standalone gententropy
emulation.

>> It tries to avoid a couple of possible issues. FIrst, while <= 256
>> byte getrandom should not interrupt, it appears that if the kernel
>> entropy pool has not been initialized yet, it would still return EINTR
>> if called early enough in the boot process. How likely this is in
>> practice, I don't know.
> 
> You mean it would block and be subject to EINTR if a signal occurs? In
> this case I would think you'd probably _want_ the EINTR to cause it to
> fail. I can imagine an early-boot program using SIGALRM to prevent
> waiting too-long/forever for entropy that's not going to arrive.

Yes, that is a better description. Failing when receiving EINTR to avoid
an infinite loop is an interesting idea, but getentropy is documented
as only failing under a very narrow range of conditions:

http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man2/getentropy.2

>> Then, to avoid modifying errno even though there was an actual
>> success, the wrapper restores the previous errno value when it
>> succeeds.
> 
> Avoiding modification of errno when the call succeeds is not necessary
> or desirable. Callers should not be assuming errno is untouched after
> success.

I think the difference here was that this is attempting to emulate a
syscall, rather than a library function, so its trying to only set
errno on failure. This was suggested to me by Theo de Raadt.

But, you're right, callers shouldn't expect either anyway.

>> I just realized that the length check in getentropy_getrandom() is
>> redundant, since it is checked earlier in getentropy() as well, but
>> hopefully this is helpful.
> 
> Indeed, that masks the issue I mentioned above.

Right, this is just one of several entropy methods that it calls in
order to perform the emulation. The outer getentropy() function is the
one that matters.

> So, their version of getentropy is aiming to provide a meaningful
> result even on systems that don't have SYS_getrandom. Should we be
> doing the same?
> 
>> If a getentropy() were added to musl libc, but in such a way that it
>> might fail on older kernels, that would cause some problems with
>> LibreSSL, and now OpenNTPD. They will both try to use getentropy()
>> with arc4random() if it is found in a system, and arc4random() will
>> treat a getentropy() failure as fatal.
> 
> Yes, this sounds bad. So what fallbacks should we implement? Do we
> need a strong CSPRNG on top of AT_RANDOM?

You can see a variety of fallbacks there, and AT_RANDOM is included,
though that is not available on every kernel either. If you're going to
implement such a CSPRNG, the C library seems the place to do it though.

  - Brent



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: getrandom syscall
  2015-01-28 20:20                     ` Brent Cook
@ 2015-01-28 22:02                       ` Rich Felker
  2015-01-28 22:59                         ` Josiah Worcester
  2015-02-09 20:37                         ` Andy Lutomirski
  0 siblings, 2 replies; 25+ messages in thread
From: Rich Felker @ 2015-01-28 22:02 UTC (permalink / raw)
  To: musl

On Wed, Jan 28, 2015 at 02:20:16PM -0600, Brent Cook wrote:
> >> It tries to avoid a couple of possible issues. FIrst, while <= 256
> >> byte getrandom should not interrupt, it appears that if the kernel
> >> entropy pool has not been initialized yet, it would still return EINTR
> >> if called early enough in the boot process. How likely this is in
> >> practice, I don't know.
> > 
> > You mean it would block and be subject to EINTR if a signal occurs? In
> > this case I would think you'd probably _want_ the EINTR to cause it to
> > fail. I can imagine an early-boot program using SIGALRM to prevent
> > waiting too-long/forever for entropy that's not going to arrive.
> 
> Yes, that is a better description. Failing when receiving EINTR to avoid
> an infinite loop is an interesting idea, but getentropy is documented
> as only failing under a very narrow range of conditions:
> 
> http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man2/getentropy.2

OK. The conditions for EIO are left sort of open-ended, but it seems
the intent is that this function not fail with valid inputs. I think
we should follow that intent if we provide the function, which means
both ignoring EINTR and providing a fallback for ENOSYS.

> > So, their version of getentropy is aiming to provide a meaningful
> > result even on systems that don't have SYS_getrandom. Should we be
> > doing the same?
> > 
> >> If a getentropy() were added to musl libc, but in such a way that it
> >> might fail on older kernels, that would cause some problems with
> >> LibreSSL, and now OpenNTPD. They will both try to use getentropy()
> >> with arc4random() if it is found in a system, and arc4random() will
> >> treat a getentropy() failure as fatal.
> > 
> > Yes, this sounds bad. So what fallbacks should we implement? Do we
> > need a strong CSPRNG on top of AT_RANDOM?
> 
> You can see a variety of fallbacks there, and AT_RANDOM is included,
> though that is not available on every kernel either. If you're going to
> implement such a CSPRNG, the C library seems the place to do it though.

At this point I think what's clear is that we should provide the
syscall wrapper for getrandom. What to do with getentropy is less
clear, and it looks to be a fair bit of work/code-size to get a robust
getentropy suitable for application usage.

I don't want to copy the idiotic stuff libressl is doing, but I think
the following fallback sequence would be reasonable:

1. Try SYS_getrandom. Fails on even mildly-old kernels.

2. Try opening /dev/urandom. Fails under fd pressure or broken
   chroots/containers/lsms/etc.

3. Try AT_RANDOM+CSPRNG. Fails on ancient (what version?) kernels.

I don't know what to after that, but I suspect/hope that any kernel
too old to have AT_RANDOM is full of so many gaping security holes
that lack of working entropy source is the least of anyone's problems.

As for CSPRNG, what would be acceptably small and secure? CTR mode
using a block cipher and AT_RANDOM as the key? Could we reuse crypto
code out of crypt/*.c? Or just call crypt_r directly?

Rich


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: getrandom syscall
  2015-01-28 22:02                       ` Rich Felker
@ 2015-01-28 22:59                         ` Josiah Worcester
  2015-02-09 20:37                         ` Andy Lutomirski
  1 sibling, 0 replies; 25+ messages in thread
From: Josiah Worcester @ 2015-01-28 22:59 UTC (permalink / raw)
  To: musl

On Wed, Jan 28, 2015 at 4:02 PM, Rich Felker <dalias@libc.org> wrote:
>
> At this point I think what's clear is that we should provide the
> syscall wrapper for getrandom. What to do with getentropy is less
> clear, and it looks to be a fair bit of work/code-size to get a robust
> getentropy suitable for application usage.
>
> I don't want to copy the idiotic stuff libressl is doing, but I think
> the following fallback sequence would be reasonable:


For what it's worth the libressl stuff is nowhere near as idiotic as
what was there previously (though is still a bunch of stuff that is at
least theoretically determinable)

> 1. Try SYS_getrandom. Fails on even mildly-old kernels.
>
> 2. Try opening /dev/urandom. Fails under fd pressure or broken
>    chroots/containers/lsms/etc.
>
> 3. Try AT_RANDOM+CSPRNG. Fails on ancient (what version?) kernels.

2.6.29+ have AT_RANDOM.

> I don't know what to after that, but I suspect/hope that any kernel
> too old to have AT_RANDOM is full of so many gaping security holes
> that lack of working entropy source is the least of anyone's problems.

2.6.12 and possibly earlier appears to have the RANDOM_UUID sysctl, if
you wish to use that.

> As for CSPRNG, what would be acceptably small and secure? CTR mode
> using a block cipher and AT_RANDOM as the key? Could we reuse crypto
> code out of crypt/*.c? Or just call crypt_r directly?
>
> Rich


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: getrandom syscall
  2015-01-28 22:02                       ` Rich Felker
  2015-01-28 22:59                         ` Josiah Worcester
@ 2015-02-09 20:37                         ` Andy Lutomirski
  1 sibling, 0 replies; 25+ messages in thread
From: Andy Lutomirski @ 2015-02-09 20:37 UTC (permalink / raw)
  To: musl

On 01/28/2015 02:02 PM, Rich Felker wrote:
> On Wed, Jan 28, 2015 at 02:20:16PM -0600, Brent Cook wrote:
>>>> It tries to avoid a couple of possible issues. FIrst, while <= 256
>>>> byte getrandom should not interrupt, it appears that if the kernel
>>>> entropy pool has not been initialized yet, it would still return EINTR
>>>> if called early enough in the boot process. How likely this is in
>>>> practice, I don't know.
>>>
>>> You mean it would block and be subject to EINTR if a signal occurs? In
>>> this case I would think you'd probably _want_ the EINTR to cause it to
>>> fail. I can imagine an early-boot program using SIGALRM to prevent
>>> waiting too-long/forever for entropy that's not going to arrive.
>>
>> Yes, that is a better description. Failing when receiving EINTR to avoid
>> an infinite loop is an interesting idea, but getentropy is documented
>> as only failing under a very narrow range of conditions:
>>
>> http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man2/getentropy.2
>
> OK. The conditions for EIO are left sort of open-ended, but it seems
> the intent is that this function not fail with valid inputs. I think
> we should follow that intent if we provide the function, which means
> both ignoring EINTR and providing a fallback for ENOSYS.
>
>>> So, their version of getentropy is aiming to provide a meaningful
>>> result even on systems that don't have SYS_getrandom. Should we be
>>> doing the same?
>>>
>>>> If a getentropy() were added to musl libc, but in such a way that it
>>>> might fail on older kernels, that would cause some problems with
>>>> LibreSSL, and now OpenNTPD. They will both try to use getentropy()
>>>> with arc4random() if it is found in a system, and arc4random() will
>>>> treat a getentropy() failure as fatal.
>>>
>>> Yes, this sounds bad. So what fallbacks should we implement? Do we
>>> need a strong CSPRNG on top of AT_RANDOM?
>>
>> You can see a variety of fallbacks there, and AT_RANDOM is included,
>> though that is not available on every kernel either. If you're going to
>> implement such a CSPRNG, the C library seems the place to do it though.
>
> At this point I think what's clear is that we should provide the
> syscall wrapper for getrandom. What to do with getentropy is less
> clear, and it looks to be a fair bit of work/code-size to get a robust
> getentropy suitable for application usage.
>
> I don't want to copy the idiotic stuff libressl is doing, but I think
> the following fallback sequence would be reasonable:
>
> 1. Try SYS_getrandom. Fails on even mildly-old kernels.
>
> 2. Try opening /dev/urandom. Fails under fd pressure or broken
>     chroots/containers/lsms/etc.
>
> 3. Try AT_RANDOM+CSPRNG. Fails on ancient (what version?) kernels.
>
> I don't know what to after that, but I suspect/hope that any kernel
> too old to have AT_RANDOM is full of so many gaping security holes
> that lack of working entropy source is the least of anyone's problems.
>
> As for CSPRNG, what would be acceptably small and secure? CTR mode
> using a block cipher and AT_RANDOM as the key? Could we reuse crypto
> code out of crypt/*.c? Or just call crypt_r directly?

Something backword secret (maybe the wrong term) would be nice, e.g., 
new_state, output = PRF(old_state).  This has the property that a leak 
of memory contents heartbleed-style doesn't leak *prior* CSPRNG outputs.

Defining PRF(x) = SHA256(x) with x being 128 bits is probably fine. 
That is, new_state is the first 128 bits of SHA256(old_state) and the 
output is the next 128 bits.  The quantum cryptographer in me would 
prefer 256-bit state, though, but I'm not sure that makes any sense in 
practice with AT_RANDOM.

I am not a serious cryptographer, so this should be taken with a small 
grain of salt.  If you wanted to depend on having an implementation of 
the Keccak sponge around, then there are very simple and much cleaner 
CSPRNGs in the literature that I could point you to, but they have the 
disadvantage of using larger internal states and therefore more memory. 
  Using a 128-bit state has the benefit that it could reuse the memory 
already allocated to AT_RANDOM.

--Andy



^ permalink raw reply	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2015-02-09 20:37 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-01-27 22:12 getrandom syscall Daniel Cegiełka
2015-01-28  9:02 ` Szabolcs Nagy
2015-01-28  9:10   ` Daniel Cegiełka
2015-01-28 12:26     ` Szabolcs Nagy
2015-01-28 12:42       ` Daniel Cegiełka
2015-01-28 14:49         ` Rich Felker
2015-01-28 14:54 ` Rich Felker
2015-01-28 15:41   ` Szabolcs Nagy
2015-01-28 15:50     ` Daniel Cegiełka
2015-01-28 16:03       ` Szabolcs Nagy
2015-01-28 16:12         ` Daniel Cegiełka
2015-01-28 16:21           ` Rich Felker
2015-01-28 17:02             ` Daniel Cegiełka
2015-01-28 17:09               ` Daniel Cegiełka
2015-01-28 17:43                 ` Brent Cook
2015-01-28 18:12                   ` Daniel Cegiełka
2015-01-28 19:17                   ` Rich Felker
2015-01-28 19:33                     ` Daniel Cegiełka
2015-01-28 20:20                     ` Brent Cook
2015-01-28 22:02                       ` Rich Felker
2015-01-28 22:59                         ` Josiah Worcester
2015-02-09 20:37                         ` Andy Lutomirski
2015-01-28 16:25         ` Daniel Cegiełka
2015-01-28 16:01     ` Daniel Cegiełka
2015-01-28 15:41   ` Daniel Cegiełka

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/musl/

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).