Обсуждение: Support getrandom() for pg_strong_random() source

Поиск
Список
Период
Сортировка

Support getrandom() for pg_strong_random() source

От
Masahiko Sawada
Дата:
Hi all,

Currently we have three options for pg_strong_random() sources:

1. OpenSSL's RAND_bytes()
2. Windows' CryptGenRandom() function
3. /dev/urandom

The patch supports the getrandom() function as a new source of
pg_strong_random(). The getrandom() function uses the same source as
the /dev/urandom device but it seems much faster than opening,
reading, and closing /dev/urandom. Here is the execution time of
generating 1 million UUIDv4 data measured on my environment:

HEAD(/dev/urandom): 1863.064 ms
Patched(getrandom()): 516.627 ms

I guess that while OpenSSL's RAND_bytes() should still be prioritized
where available it might be a good idea to support getrandom() for
builds where RAND_bytes() is not available.

Feedback is very welcome.

Regards,

-- 
Masahiko Sawada
Amazon Web Services: https://aws.amazon.com

Вложения

Re: Support getrandom() for pg_strong_random() source

От
Michael Paquier
Дата:
On Mon, Jul 21, 2025 at 11:43:35PM -0700, Masahiko Sawada wrote:
> The patch supports the getrandom() function as a new source of
> pg_strong_random(). The getrandom() function uses the same source as
> the /dev/urandom device but it seems much faster than opening,
> reading, and closing /dev/urandom. Here is the execution time of
> generating 1 million UUIDv4 data measured on my environment:
>
> HEAD(/dev/urandom): 1863.064 ms
> Patched(getrandom()): 516.627 ms

Interesting.  Are there platforms where this is not available?  I'd be
pretty sure that some animals in the buildfarm would not like this
suggestion but I'm saying it anyway.  Perhaps we could even drop
/dev/urandom?

> I guess that while OpenSSL's RAND_bytes() should still be prioritized
> where available it might be a good idea to support getrandom() for
> builds where RAND_bytes() is not available.
>
> Feedback is very welcome.

I am wondering how much non-OpenSSL builds matter these days, TBH, so
I am not sure that this is worth the addition of an extra
configure/meson check and this stuff has its cost just for such
builds.  I am not saying that we should make OpenSSL mandatory, of
course not, but all production instances of Postgres have likely
OpenSSL enabled anyway.  Perhaps some embedded deployments like
--without-openssl, who knows..
--
Michael

Вложения

Re: Support getrandom() for pg_strong_random() source

От
Masahiko Sawada
Дата:
On Tue, Jul 22, 2025 at 12:13 AM Michael Paquier <michael@paquier.xyz> wrote:
>
> On Mon, Jul 21, 2025 at 11:43:35PM -0700, Masahiko Sawada wrote:
> > The patch supports the getrandom() function as a new source of
> > pg_strong_random(). The getrandom() function uses the same source as
> > the /dev/urandom device but it seems much faster than opening,
> > reading, and closing /dev/urandom. Here is the execution time of
> > generating 1 million UUIDv4 data measured on my environment:
> >
> > HEAD(/dev/urandom): 1863.064 ms
> > Patched(getrandom()): 516.627 ms
>
> Interesting.  Are there platforms where this is not available?  I'd be
> pretty sure that some animals in the buildfarm would not like this
> suggestion but I'm saying it anyway.  Perhaps we could even drop
> /dev/urandom?

As far as I know macOS doesn't support getrandom() but supports
getentropy() instead. And an older glibc version might not support it.
It's supported since Linux 3.17 and glibc 2.25.

> > I guess that while OpenSSL's RAND_bytes() should still be prioritized
> > where available it might be a good idea to support getrandom() for
> > builds where RAND_bytes() is not available.
> >
> > Feedback is very welcome.
>
> I am wondering how much non-OpenSSL builds matter these days, TBH, so
> I am not sure that this is worth the addition of an extra
> configure/meson check and this stuff has its cost just for such
> builds.  I am not saying that we should make OpenSSL mandatory, of
> course not, but all production instances of Postgres have likely
> OpenSSL enabled anyway.  Perhaps some embedded deployments like
> --without-openssl, who knows..

Fair point. In fact, I was not using OpenSSL and just realized
generating UUID by PostgreSQL's uuidv4() and uuidv7() was much slower
than generating it by Rust's UUID crate. On my environment,
getrandom() is faster than RAND_bytes() so I thought there are some
cases where users want to use the getrandom() source rather than
RAND_bytes(), but I'm not sure since there is also a difference in the
secureness.

Regards,

--
Masahiko Sawada
Amazon Web Services: https://aws.amazon.com



Re: Support getrandom() for pg_strong_random() source

От
Dagfinn Ilmari Mannsåker
Дата:
Masahiko Sawada <sawada.mshk@gmail.com> writes:

> On Tue, Jul 22, 2025 at 12:13 AM Michael Paquier <michael@paquier.xyz> wrote:
>>
>> On Mon, Jul 21, 2025 at 11:43:35PM -0700, Masahiko Sawada wrote:
>> > The patch supports the getrandom() function as a new source of
>> > pg_strong_random(). The getrandom() function uses the same source as
>> > the /dev/urandom device but it seems much faster than opening,
>> > reading, and closing /dev/urandom. Here is the execution time of
>> > generating 1 million UUIDv4 data measured on my environment:
>> >
>> > HEAD(/dev/urandom): 1863.064 ms
>> > Patched(getrandom()): 516.627 ms
>>
>> Interesting.  Are there platforms where this is not available?  I'd be
>> pretty sure that some animals in the buildfarm would not like this
>> suggestion but I'm saying it anyway.  Perhaps we could even drop
>> /dev/urandom?
>
> As far as I know macOS doesn't support getrandom() but supports
> getentropy() instead. And an older glibc version might not support it.
> It's supported since Linux 3.17 and glibc 2.25.

getrandom() is Linux-specific, while getentropy() is specified by POSIX
(since 2024).  It was originally introduced by OpenBSD 5.6 in 2014, and
was added to macOS 10.12 in 2016, glibc 2.25 (same as getrandom()) in
2017, musl 1.1.20 and FreeBSD 12.0 in 2018, and NetBSD 10.0 in 2024

Sources: 

https://pubs.opengroup.org/onlinepubs/9799919799/functions/getentropy.html
https://dotat.at/@/2024-10-01-getentropy.html

So I think it's more worthwhile to add support for getentropy() than
getrandom().

- ilmari



Re: Support getrandom() for pg_strong_random() source

От
Masahiko Sawada
Дата:
On Tue, Jul 22, 2025 at 4:12 AM Dagfinn Ilmari Mannsåker
<ilmari@ilmari.org> wrote:
>
> Masahiko Sawada <sawada.mshk@gmail.com> writes:
>
> > On Tue, Jul 22, 2025 at 12:13 AM Michael Paquier <michael@paquier.xyz> wrote:
> >>
> >> On Mon, Jul 21, 2025 at 11:43:35PM -0700, Masahiko Sawada wrote:
> >> > The patch supports the getrandom() function as a new source of
> >> > pg_strong_random(). The getrandom() function uses the same source as
> >> > the /dev/urandom device but it seems much faster than opening,
> >> > reading, and closing /dev/urandom. Here is the execution time of
> >> > generating 1 million UUIDv4 data measured on my environment:
> >> >
> >> > HEAD(/dev/urandom): 1863.064 ms
> >> > Patched(getrandom()): 516.627 ms
> >>
> >> Interesting.  Are there platforms where this is not available?  I'd be
> >> pretty sure that some animals in the buildfarm would not like this
> >> suggestion but I'm saying it anyway.  Perhaps we could even drop
> >> /dev/urandom?
> >
> > As far as I know macOS doesn't support getrandom() but supports
> > getentropy() instead. And an older glibc version might not support it.
> > It's supported since Linux 3.17 and glibc 2.25.
>
> getrandom() is Linux-specific, while getentropy() is specified by POSIX
> (since 2024).  It was originally introduced by OpenBSD 5.6 in 2014, and
> was added to macOS 10.12 in 2016, glibc 2.25 (same as getrandom()) in
> 2017, musl 1.1.20 and FreeBSD 12.0 in 2018, and NetBSD 10.0 in 2024
>
> Sources:
>
> https://pubs.opengroup.org/onlinepubs/9799919799/functions/getentropy.html
> https://dotat.at/@/2024-10-01-getentropy.html
>
> So I think it's more worthwhile to add support for getentropy() than
> getrandom().

While getentropy() has better portability, according to the
getentropy() manual, the maximum length is limited to 256 bytes. It
works in some cases such as generating UUID data but seems not
appropriate for our general pg_strong_random() use cases.

Regards,

--
Masahiko Sawada
Amazon Web Services: https://aws.amazon.com



Re: Support getrandom() for pg_strong_random() source

От
Jacob Champion
Дата:
On Tue, Jul 22, 2025 at 11:32 AM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
> While getentropy() has better portability, according to the
> getentropy() manual, the maximum length is limited to 256 bytes. It
> works in some cases such as generating UUID data but seems not
> appropriate for our general pg_strong_random() use cases.

I imagine that the code would look very similar to your patch, though
(loop, in chunks of size GETENTROPY_MAX, until the required length is
met). Without looking too deeply, I have to say that implementing a
newer POSIX API as opposed to a Linux-specific one does seem like a
better cost-benefit tradeoff, if we decide to do this.

Can you talk more about this part:

> On my environment,
> getrandom() is faster than RAND_bytes() so I thought there are some
> cases where users want to use the getrandom() source rather than
> RAND_bytes(), but I'm not sure since there is also a difference in the
> secureness.

That is _really_ surprising to me at first glance. I thought
RAND_bytes() was supposed to be a userspace PRNG, which I would
naively expect to take much less time than pulling data from Linux.
(Once the OpenSSL PRNG has been seeded, that is.) Are there any other
details about your environment (or the test itself) that are unusual?

Thanks,
--Jacob



Re: Support getrandom() for pg_strong_random() source

От
"DINESH NAIR"
Дата:
Hi , 


            On Tue, Jul 22, 2025 at 4:12 AM Dagfinn Ilmari Mannsåker
<ilmari@ilmari.org> wrote:
>
> Masahiko Sawada <sawada.mshk@gmail.com> writes:
>
> > On Tue, Jul 22, 2025 at 12:13 AM Michael Paquier <michael@paquier.xyz> wrote:
> >>
> >> On Mon, Jul 21, 2025 at 11:43:35PM -0700, Masahiko Sawada wrote:
> >> > The patch supports the getrandom() function as a new source of
> >> > pg_strong_random(). The getrandom() function uses the same source as
> >> > the /dev/urandom device but it seems much faster than opening,
> >> > reading, and closing /dev/urandom. Here is the execution time of
> >> > generating 1 million UUIDv4 data measured on my environment:
> >> >
> >> > HEAD(/dev/urandom): 1863.064 ms
> >> > Patched(getrandom()): 516.627 ms
> >>
> >> Interesting.  Are there platforms where this is not available?  I'd be
> >> pretty sure that some animals in the buildfarm would not like this
> >> suggestion but I'm saying it anyway.  Perhaps we could even drop
> >> /dev/urandom?
> >
> > As far as I know macOS doesn't support getrandom() but supports
> > getentropy() instead. And an older glibc version might not support it.
> > It's supported since Linux 3.17 and glibc 2.25.
>
> getrandom() is Linux-specific, while getentropy() is specified by POSIX
> (since 2024).  It was originally introduced by OpenBSD 5.6 in 2014, and
> was added to macOS 10.12 in 2016, glibc 2.25 (same as getrandom()) in
> 2017, musl 1.1.20 and FreeBSD 12.0 in 2018, and NetBSD 10.0 in 2024
>
> Sources:
>While getentropy() has better portability, according to the
>getentropy() manual, the maximum length is limited to 256 bytes. It
>works in some cases such as generating UUID data but seems not
> appropriate for our general pg_strong_random() use cases.


The getentropy() function has a limitation of generating a maximum of 256 bytes of entropy per call and is not supported on Windows platforms. For cryptographic operations that require large buffers of high-quality randomness efficiently, it's not  recommended to use getentropy().
In Postgres it’s common to see the SQL random() function used to generate a random number, but it’s a pseudo-random number generator, and not suitable for cases where real randomness is required critical. Postgres also provides a way of getting secure random numbers as well, but only through the use of the pgcrypto extension, which makes gen_random_bytes available. Pulling pgcrypto into ...
brandur.org


Thanks 


Regards

Dinesh Nair



From: Masahiko Sawada <sawada.mshk@gmail.com>
Sent: Wednesday, July 23, 2025 12:02 AM
To: Dagfinn Ilmari Mannsåker <ilmari@ilmari.org>
Cc: Michael Paquier <michael@paquier.xyz>; PostgreSQL Hackers <pgsql-hackers@lists.postgresql.org>
Subject: Re: Support getrandom() for pg_strong_random() source
 
Caution: This email was sent from an external source. Please verify the sender’s identity before clicking links or opening attachments.

On Tue, Jul 22, 2025 at 4:12 AM Dagfinn Ilmari Mannsåker
<ilmari@ilmari.org> wrote:
>
> Masahiko Sawada <sawada.mshk@gmail.com> writes:
>
> > On Tue, Jul 22, 2025 at 12:13 AM Michael Paquier <michael@paquier.xyz> wrote:
> >>
> >> On Mon, Jul 21, 2025 at 11:43:35PM -0700, Masahiko Sawada wrote:
> >> > The patch supports the getrandom() function as a new source of
> >> > pg_strong_random(). The getrandom() function uses the same source as
> >> > the /dev/urandom device but it seems much faster than opening,
> >> > reading, and closing /dev/urandom. Here is the execution time of
> >> > generating 1 million UUIDv4 data measured on my environment:
> >> >
> >> > HEAD(/dev/urandom): 1863.064 ms
> >> > Patched(getrandom()): 516.627 ms
> >>
> >> Interesting.  Are there platforms where this is not available?  I'd be
> >> pretty sure that some animals in the buildfarm would not like this
> >> suggestion but I'm saying it anyway.  Perhaps we could even drop
> >> /dev/urandom?
> >
> > As far as I know macOS doesn't support getrandom() but supports
> > getentropy() instead. And an older glibc version might not support it.
> > It's supported since Linux 3.17 and glibc 2.25.
>
> getrandom() is Linux-specific, while getentropy() is specified by POSIX
> (since 2024).  It was originally introduced by OpenBSD 5.6 in 2014, and
> was added to macOS 10.12 in 2016, glibc 2.25 (same as getrandom()) in
> 2017, musl 1.1.20 and FreeBSD 12.0 in 2018, and NetBSD 10.0 in 2024
>
> Sources:
>
> https://ind01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpubs.opengroup.org%2Fonlinepubs%2F9799919799%2Ffunctions%2Fgetentropy.html&data=05%7C02%7Cdinesh_nair%40iitmpravartak.net%7C6063a2ac8d4f45e1a74808ddc94e2e4e%7C3e964837c2384683915549f4ec04f8e9%7C0%7C0%7C638888059824005298%7CUnknown%7CTWFpbGZsb3d8eyJFbXB0eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOIjoiTWFpbCIsIldUIjoyfQ%3D%3D%7C0%7C%7C%7C&sdata=C5abb70MrRMb8YrRpFZreelrwfXgKtxWYNWvEc3oPFg%3D&reserved=0
> https://ind01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdotat.at%2F%40%2F2024-10-01-getentropy.html&data=05%7C02%7Cdinesh_nair%40iitmpravartak.net%7C6063a2ac8d4f45e1a74808ddc94e2e4e%7C3e964837c2384683915549f4ec04f8e9%7C0%7C0%7C638888059824035506%7CUnknown%7CTWFpbGZsb3d8eyJFbXB0eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOIjoiTWFpbCIsIldUIjoyfQ%3D%3D%7C0%7C%7C%7C&sdata=RwqnnTVGURh7kw31OLW0kRUu%2BCUVVRlt%2Fx9FDDesb58%3D&reserved=0
>
> So I think it's more worthwhile to add support for getentropy() than
> getrandom().

While getentropy() has better portability, according to the
getentropy() manual, the maximum length is limited to 256 bytes. It
works in some cases such as generating UUID data but seems not
appropriate for our general pg_strong_random() use cases.

Regards,

--
Masahiko Sawada
Amazon Web Services: https://ind01.safelinks.protection.outlook.com/?url=https%3A%2F%2Faws.amazon.com%2F&data=05%7C02%7Cdinesh_nair%40iitmpravartak.net%7C6063a2ac8d4f45e1a74808ddc94e2e4e%7C3e964837c2384683915549f4ec04f8e9%7C0%7C0%7C638888059824052980%7CUnknown%7CTWFpbGZsb3d8eyJFbXB0eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOIjoiTWFpbCIsIldUIjoyfQ%3D%3D%7C0%7C%7C%7C&sdata=NNEQNe%2Fibr6VRZAmBPWTy6r5J4pH2yza4PVGA4E9LO4%3D&reserved=0


Re: Support getrandom() for pg_strong_random() source

От
Masahiko Sawada
Дата:
On Tue, Jul 22, 2025 at 11:46 AM Jacob Champion
<jacob.champion@enterprisedb.com> wrote:
>
> On Tue, Jul 22, 2025 at 11:32 AM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
> > While getentropy() has better portability, according to the
> > getentropy() manual, the maximum length is limited to 256 bytes. It
> > works in some cases such as generating UUID data but seems not
> > appropriate for our general pg_strong_random() use cases.
>
> I imagine that the code would look very similar to your patch, though
> (loop, in chunks of size GETENTROPY_MAX, until the required length is
> met). Without looking too deeply, I have to say that implementing a
> newer POSIX API as opposed to a Linux-specific one does seem like a
> better cost-benefit tradeoff, if we decide to do this.
>
> Can you talk more about this part:
>
> > On my environment,
> > getrandom() is faster than RAND_bytes() so I thought there are some
> > cases where users want to use the getrandom() source rather than
> > RAND_bytes(), but I'm not sure since there is also a difference in the
> > secureness.
>
> That is _really_ surprising to me at first glance. I thought
> RAND_bytes() was supposed to be a userspace PRNG, which I would
> naively expect to take much less time than pulling data from Linux.
> (Once the OpenSSL PRNG has been seeded, that is.) Are there any other
> details about your environment (or the test itself) that are unusual?

Yes, it surprised me too. The environment I used for this benchmark was:

% cat /etc/redhat-release
Red Hat Enterprise Linux release 8.10 (Ootpa)
% uname -r
4.18.0-553.22.1.el8_10.x86_64
% rpm -qa | grep openssl
openssl-libs-1.1.1k-14.el8_6.x86_64
openssl-debugsource-1.1.1k-14.el8_6.x86_64
rubygem-openssl-2.1.2-114.module+el8.10.0+23088+750dc6ca.x86_64
openssl-devel-1.1.1k-14.el8_6.x86_64
openssl-pkcs11-0.4.10-3.el8.x86_64
openssl-1.1.1k-14.el8_6.x86_64
openssl-debuginfo-1.1.1k-14.el8_6.x86_64
% openssl version
OpenSSL 1.1.1k  FIPS 25 Mar 2021

and I measured the execution time of the following query:

explain analyze select uuidv4() from generate_series(1, 1_000_000);

The result is:

getrandom: 517.120ms
RAND_bytes: 1150.051 ms
/dev/urandom: 1862.483 ms

Since on the above environment I used an old Linux kernel and openssl
version, I've does the same benchmark on another environment:

$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 24.04.2 LTS
Release:        24.04
Codename:       noble
$ apt list --installed | grep ssl
libssl-dev/noble-updates,noble-security,now 3.0.13-0ubuntu3.5 amd64 [installed]
libssl3t64/noble-updates,noble-security,now 3.0.13-0ubuntu3.5 amd64
[installed,automatic]
libxmlsec1t64-openssl/noble,now 1.2.39-5build2 amd64 [installed,automatic]
openssl/noble-updates,noble-security,now 3.0.13-0ubuntu3.5 amd64
[installed,automatic]
python3-openssl/noble,now 23.2.0-1 all [installed,automatic]
ssl-cert/noble,now 1.1.2ubuntu1 all [installed,automatic]

The trend of the results were similar:

getrandom: 497.061 ms
RAND_bytes: 1152.260 ms ms
/dev/urandom: 1696.065 ms

Please let me know if I'm missing configurations or settings to
measure this workload properly.

Regards,

--
Masahiko Sawada
Amazon Web Services: https://aws.amazon.com



Re: Support getrandom() for pg_strong_random() source

От
Jacob Champion
Дата:
On Tue, Jul 22, 2025 at 4:23 PM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
> The trend of the results were similar:
>
> getrandom: 497.061 ms
> RAND_bytes: 1152.260 ms ms
> /dev/urandom: 1696.065 ms
>
> Please let me know if I'm missing configurations or settings to
> measure this workload properly.

I don't think you're missing anything, or else I'm missing something
too. If I modify pg_strong_random() to call getentropy() in addition
to the existing RAND_bytes() code, `perf` shows RAND_bytes() taking up
2.4x the samples that getentropy() does. That's very similar to your
results.

> On Tue, Jul 22, 2025 at 11:46 AM Jacob Champion
> <jacob.champion@enterprisedb.com> wrote:
> > That is _really_ surprising to me at first glance. I thought
> > RAND_bytes() was supposed to be a userspace PRNG, which I would
> > naively expect to take much less time than pulling data from Linux.

So my expectation was naive for sure. This has sent me down a bit of a
rabbit hole, starting with Adam Langley's BoringSSL post [1] which led
to a post/rant on urandom [2]. I don't think an API that advertises
"strong randomness" should ever prioritize performance over strength.
But maybe the pendulum has swung far enough that we can expect any
kernel supporting getentropy() to be able to do the job just as well
as OpenSSL does in userspace, except also faster? I think it might be
worth a discussion.

Thanks,
--Jacob

[1] https://www.imperialviolet.org/2015/10/17/boringssl.html
[2] https://sockpuppet.org/blog/2014/02/25/safely-generate-random-numbers/



Re: Support getrandom() for pg_strong_random() source

От
Daniel Gustafsson
Дата:
> On 23 Jul 2025, at 19:11, Jacob Champion <jacob.champion@enterprisedb.com> wrote:

> .. maybe the pendulum has swung far enough that we can expect any
> kernel supporting getentropy() to be able to do the job just as well
> as OpenSSL does in userspace, except also faster? I think it might be
> worth a discussion.

There has in the past been discussions (at least off-list in hallway tracks)
about allowing randomness to be chosen separately from underlying factors such
as OpenSSL support, at the time it didn't seem worth the trouble but that may
well have changed.

With OpenSSL 1.1.1 being the baseline we can also make use of the _priv_bytes
functions to get increased isolation.

--
Daniel Gustafsson




Re: Support getrandom() for pg_strong_random() source

От
Jacob Champion
Дата:
On Mon, Jul 28, 2025 at 4:36 AM Daniel Gustafsson <daniel@yesql.se> wrote:
> There has in the past been discussions (at least off-list in hallway tracks)
> about allowing randomness to be chosen separately from underlying factors such
> as OpenSSL support, at the time it didn't seem worth the trouble but that may
> well have changed.

Yeah, especially if other options with similar strength could be much
faster. But the comparison is really going to be OS-dependent [1, 2].

> With OpenSSL 1.1.1 being the baseline we can also make use of the _priv_bytes
> functions to get increased isolation.

Hmm, that's an interesting idea too.

To move this forward a tiny bit: I would be okay with maintaining a
new getentropy() case. (I'm less excited about getrandom() because of
its reduced reach.) And maybe down the line we should discuss choosing
an option at configure time?

--Jacob

[1] https://lwn.net/Articles/983186/
[2] https://dotat.at/@/2024-10-01-getentropy.html



Re: Support getrandom() for pg_strong_random() source

От
Daniel Gustafsson
Дата:
> On 28 Jul 2025, at 17:29, Jacob Champion <jacob.champion@enterprisedb.com> wrote:

> To move this forward a tiny bit: I would be okay with maintaining a
> new getentropy() case. (I'm less excited about getrandom() because of
> its reduced reach.) And maybe down the line we should discuss choosing
> an option at configure time?

I would not be opposed to starting there.

--
Daniel Gustafsson




Re: Support getrandom() for pg_strong_random() source

От
Michael Paquier
Дата:
On Mon, Jul 28, 2025 at 06:14:20PM +0200, Daniel Gustafsson wrote:
> On 28 Jul 2025, at 17:29, Jacob Champion <jacob.champion@enterprisedb.com> wrote:
>> To move this forward a tiny bit: I would be okay with maintaining a
>> new getentropy() case. (I'm less excited about getrandom() because of
>> its reduced reach.) And maybe down the line we should discuss choosing
>> an option at configure time?
>
> I would not be opposed to starting there.

Both of you know the options of these areas of the code more than the
average committer, I think, so if you think that getentropy() could be
a good choice, while making the choice configurable to give the
possibility to be outside of OpenSSL, why not.

My understanding of the problem is that it is a choice of efficiency
vs entropy, and that it's not really possible to have both parts of
the cake.  If we make that configurable, documentation sounds like the
key point to me, to explain which one has more benefits over the
other.

Could getentropy() be more efficient at the end on most platforms,
meaning that this could limit the meaning of having a GUC switch?
Having it in POSIX is appealing with the long-term picture in mind..
--
Michael

Вложения

Re: Support getrandom() for pg_strong_random() source

От
Jacob Champion
Дата:
On Mon, Jul 28, 2025 at 6:30 PM Michael Paquier <michael@paquier.xyz> wrote:
> My understanding of the problem is that it is a choice of efficiency
> vs entropy, and that it's not really possible to have both parts of
> the cake.

That was my understanding too, but then [1] called that into question.
If -- and I don't really have enough expertise to verify that "if" --
the reason OpenSSL is slower isn't because of "entropy", but because
of operations and safety checks that it has to ask the kernel to make
for it, then it stands to reason that the kernel could do that a lot
faster.

If it turns out that's not the case (the post at [1] is ten years old;
things change, or Adam could have been wrong, or...), I think that
getentropy() is still a straight upgrade from /dev/urandom, due to its
increased safety guarantees at startup.

> If we make that configurable, documentation sounds like the
> key point to me, to explain which one has more benefits over the
> other.

Agreed.

> Could getentropy() be more efficient at the end on most platforms,
> meaning that this could limit the meaning of having a GUC switch?

I don't know. [2] implies that the performance comparison depends on
several factors, and falls in favor of OpenSSL when the number of
bytes per call is large -- but our use of pg_strong_random() is
generally on small buffers. We would need to do a _lot_ more research
before, say, switching any defaults.

Thanks,
--Jacob

[1] https://www.imperialviolet.org/2015/10/17/boringssl.html
[2] https://dotat.at/@/2024-10-01-getentropy.html



Re: Support getrandom() for pg_strong_random() source

От
Dagfinn Ilmari Mannsåker
Дата:
Jacob Champion <jacob.champion@enterprisedb.com> writes:

> On Mon, Jul 28, 2025 at 6:30 PM Michael Paquier <michael@paquier.xyz> wrote:
>
>> Could getentropy() be more efficient at the end on most platforms,
>> meaning that this could limit the meaning of having a GUC switch?
>
> I don't know. [2] implies that the performance comparison depends on
> several factors, and falls in favor of OpenSSL when the number of
> bytes per call is large
[...]
> [2] https://dotat.at/@/2024-10-01-getentropy.html

Note that that test was done on an older Linux kernel without the vDSO
implementation of getentropy(), so on newer kernel (>=6.11) and glibc
(>= 2.41) versions the difference might be smaller or the other way
around.


- ilmari



Re: Support getrandom() for pg_strong_random() source

От
Masahiko Sawada
Дата:
On Tue, Jul 29, 2025 at 8:55 AM Jacob Champion
<jacob.champion@enterprisedb.com> wrote:
>
> On Mon, Jul 28, 2025 at 6:30 PM Michael Paquier <michael@paquier.xyz> wrote:
> > My understanding of the problem is that it is a choice of efficiency
> > vs entropy, and that it's not really possible to have both parts of
> > the cake.

Agreed. I think the optimal choice would depend on the specific use
case. For instance, since UUIDs are not intended for security
purposes, they don't require particularly high entropy. In UUID
generation, the efficiency of random data generation tends to be
prioritized over the quality of randomness.

>
> > Could getentropy() be more efficient at the end on most platforms,
> > meaning that this could limit the meaning of having a GUC switch?
>
> I don't know. [2] implies that the performance comparison depends on
> several factors, and falls in favor of OpenSSL when the number of
> bytes per call is large -- but our use of pg_strong_random() is
> generally on small buffers. We would need to do a _lot_ more research
> before, say, switching any defaults.

The performance issue with getentropy, particularly when len=1024,
likely stems from the need for multiple getentropy() calls due to its
256-byte length restriction.

Analysis of RAND_bytes() through strace reveals that it internally
makes calls to getrandom() with a fixed length of 32 bytes. While I'm
uncertain of the exact purpose, it's logical that a single
getentropy() call would be more efficient than RAND_bytes(), which
involves additional overhead beyond just calling getrandom(),
especially when dealing with smaller byte sizes.

I've updated the patch to support getentropy() instead of getrandom().

Regards,

--
Masahiko Sawada
Amazon Web Services: https://aws.amazon.com

Вложения

Re: Support getrandom() for pg_strong_random() source

От
Peter Eisentraut
Дата:
On 22.07.25 13:11, Dagfinn Ilmari Mannsåker wrote:
> getrandom() is Linux-specific, while getentropy() is specified by POSIX
> (since 2024).  It was originally introduced by OpenBSD 5.6 in 2014, and
> was added to macOS 10.12 in 2016, glibc 2.25 (same as getrandom()) in
> 2017, musl 1.1.20 and FreeBSD 12.0 in 2018, and NetBSD 10.0 in 2024
> 
> Sources:
> 
> https://pubs.opengroup.org/onlinepubs/9799919799/functions/getentropy.html
> https://dotat.at/@/2024-10-01-getentropy.html
> 
> So I think it's more worthwhile to add support for getentropy() than
> getrandom().

The POSIX description of getentropy() says:

"The intended use of this function is to create a seed for other 
pseudo-random number generators."

So using getentropy() for generating the random numbers that are passed 
back to the application code would appear to be the wrong use.



Re: Support getrandom() for pg_strong_random() source

От
Peter Eisentraut
Дата:
On 30.07.25 08:59, Masahiko Sawada wrote:
> I've updated the patch to support getentropy() instead of getrandom().

The point still stands that the number of installations without OpenSSL 
support is approximately zero, so what is the purpose of this patch if 
approximately no one will be able to use it?




Re: Support getrandom() for pg_strong_random() source

От
Dagfinn Ilmari Mannsåker
Дата:
Masahiko Sawada <sawada.mshk@gmail.com> writes:

> On Tue, Jul 29, 2025 at 8:55 AM Jacob Champion
> <jacob.champion@enterprisedb.com> wrote:
>>
>> On Mon, Jul 28, 2025 at 6:30 PM Michael Paquier <michael@paquier.xyz> wrote:
>> > My understanding of the problem is that it is a choice of efficiency
>> > vs entropy, and that it's not really possible to have both parts of
>> > the cake.
>
> Agreed. I think the optimal choice would depend on the specific use
> case. For instance, since UUIDs are not intended for security
> purposes, they don't require particularly high entropy. In UUID
> generation, the efficiency of random data generation tends to be
> prioritized over the quality of randomness.
>
>>
>> > Could getentropy() be more efficient at the end on most platforms,
>> > meaning that this could limit the meaning of having a GUC switch?
>>
>> I don't know. [2] implies that the performance comparison depends on
>> several factors, and falls in favor of OpenSSL when the number of
>> bytes per call is large -- but our use of pg_strong_random() is
>> generally on small buffers. We would need to do a _lot_ more research
>> before, say, switching any defaults.
>
> The performance issue with getentropy, particularly when len=1024,
> likely stems from the need for multiple getentropy() calls due to its
> 256-byte length restriction.
>
> Analysis of RAND_bytes() through strace reveals that it internally
> makes calls to getrandom() with a fixed length of 32 bytes. While I'm
> uncertain of the exact purpose, it's logical that a single
> getentropy() call would be more efficient than RAND_bytes(), which
> involves additional overhead beyond just calling getrandom(),
> especially when dealing with smaller byte sizes.
>
> I've updated the patch to support getentropy() instead of getrandom().

Thanks, just a few comments:

The blog post at
https://dotat.at/@/2024-10-01-getentropy.html#portability-of-getentropy-
points out a couple of caveats:

 * Originally getentropy() was declared in <sys/random.h> but POSIX
   declares it in <unistd.h>. You need to include both headers to be
   sure.

So the probes need to include both <sys/random.h> (if avaliable) and
<unistd.h>, and in the code <sys/random.h> should only be included if
available.

 * POSIX specifies a GETENTROPY_MAX macro in <limits.h> for the largest
   buffer getentropy() will fill. Most systems don’t yet have this
   macro; if it isn’t defined the limit is 256 bytes.

And this means we should include <limits.h> and only define
GETENTROPY_MAX to 256 if it's not already defined.

> +bool
> +pg_strong_random(void *buf, size_t len)
> +{
> +    char       *p = buf;
> +    ssize_t        res;
> +
> +    while (len)
> +    {
> +        size_t        l = Min(len, GETENTROPY_MAX_LEN);
> +
> +        res = getentropy(buf, l);

This should be getentropy(p, l), otherwise it will will just fill the
first GETENTROPY_MAX_LEN bytes of buf repeatedly.  On my machine I got a
warning about that:

../postgresql/src/port/pg_strong_random.c:159:11: warning: variable 'p' set but not used [-Wunused-but-set-variable]
  159 |         char       *p = buf;
      |                     ^

Do we not have any tests for pg_strong_random that make sure it fills
the entire bufffer for various sizes?

I've attached an updated patch for the above, except I don't know enough
autoconf/m4 to make it include <unistd.h> and optionally <sys/random.h>
in the check there.

- ilmari

From 05a53fe6ab33cfa9d6673ee8b868ce66b349e35b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Dagfinn=20Ilmari=20Manns=C3=A5ker?= <ilmari@ilmari.org>
Date: Wed, 30 Jul 2025 12:36:46 +0100
Subject: [PATCH v3] Support getentropy() as source of pg_strong_random() where
 available

---
 configure                   | 24 ++++++++++++++++++-
 configure.ac                |  8 ++++++-
 meson.build                 |  9 ++++++++
 src/include/pg_config.h.in  |  6 +++++
 src/port/pg_strong_random.c | 46 ++++++++++++++++++++++++++++++++++---
 5 files changed, 88 insertions(+), 5 deletions(-)

diff --git a/configure b/configure
index 507a2437c33..f11cd4265bf 100755
--- a/configure
+++ b/configure
@@ -16243,6 +16243,25 @@ cat >>confdefs.h <<_ACEOF
 _ACEOF
 
 
+ac_fn_c_check_header_mongrel "$LINENO" "sys/random.h" "ac_cv_header_sys_random_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_random_h" = xyes; then :
+  for ac_func in getentropy
+do :
+  ac_fn_c_check_func "$LINENO" "getentropy" "ac_cv_func_getentropy"
+if test "x$ac_cv_func_getentropy" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_GETENTROPY 1
+_ACEOF
+
+$as_echo "#define HAVE_GETENTROPY 1" >>confdefs.h
+
+fi
+done
+
+fi
+
+
+
 ac_fn_c_check_func "$LINENO" "explicit_bzero" "ac_cv_func_explicit_bzero"
 if test "x$ac_cv_func_explicit_bzero" = xyes; then :
   $as_echo "#define HAVE_EXPLICIT_BZERO 1" >>confdefs.h
@@ -18479,6 +18498,9 @@ $as_echo "Windows native" >&6; }
 elif test x"$cross_compiling" = x"yes"; then
   { $as_echo "$as_me:${as_lineno-$LINENO}: result: assuming /dev/urandom" >&5
 $as_echo "assuming /dev/urandom" >&6; }
+elif test x"$ac_cv_func_getentropy" = x"yes"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: getentropy" >&5
+$as_echo "getentropy" >&6; }
 else
   { $as_echo "$as_me:${as_lineno-$LINENO}: result: /dev/urandom" >&5
 $as_echo "/dev/urandom" >&6; }
@@ -18505,7 +18527,7 @@ fi
   if test x"$ac_cv_file__dev_urandom" = x"no" ; then
     as_fn_error $? "
 no source of strong random numbers was found
-PostgreSQL can use OpenSSL, native Windows API or /dev/urandom as a source of random numbers." "$LINENO" 5
+PostgreSQL can use OpenSSL, native Windows API, getentropy function, or /dev/urandom as a source of random numbers."
"$LINENO"5
 
   fi
 fi
 
diff --git a/configure.ac b/configure.ac
index 5f4548adc5c..9cf453fcd23 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1850,6 +1850,10 @@ AC_CHECK_DECLS([memset_s], [], [], [#define __STDC_WANT_LIB_EXT1__ 1
 # This is probably only present on macOS, but may as well check always
 AC_CHECK_DECLS(F_FULLFSYNC, [], [], [#include <fcntl.h>])
 
+AC_CHECK_HEADER([sys/random.h],
+ [AC_CHECK_FUNCS([getentropy],
+  [AC_DEFINE(HAVE_GETENTROPY, 1, [Define to 1 if you have getentropy])])])
+
 AC_REPLACE_FUNCS(m4_normalize([
     explicit_bzero
     getopt
@@ -2314,6 +2318,8 @@ elif test x"$PORTNAME" = x"win32" ; then
   AC_MSG_RESULT([Windows native])
 elif test x"$cross_compiling" = x"yes"; then
   AC_MSG_RESULT([assuming /dev/urandom])
+elif test x"$ac_cv_func_getentropy" = x"yes"; then
+  AC_MSG_RESULT(getentropy)
 else
   AC_MSG_RESULT([/dev/urandom])
   AC_CHECK_FILE([/dev/urandom], [], [])
@@ -2321,7 +2327,7 @@ else
   if test x"$ac_cv_file__dev_urandom" = x"no" ; then
     AC_MSG_ERROR([
 no source of strong random numbers was found
-PostgreSQL can use OpenSSL, native Windows API or /dev/urandom as a source of random numbers.])
+PostgreSQL can use OpenSSL, native Windows API, getentropy function, or /dev/urandom as a source of random numbers.])
   fi
 fi
 
diff --git a/meson.build b/meson.build
index ca423dc8e12..b422b623db1 100644
--- a/meson.build
+++ b/meson.build
@@ -2627,6 +2627,7 @@ header_checks = [
   'sys/personality.h',
   'sys/prctl.h',
   'sys/procctl.h',
+  'sys/random.h',
   'sys/signalfd.h',
   'sys/ucred.h',
   'termios.h',
@@ -2705,6 +2706,14 @@ return 0;
    don't.'''.format(func))
 endforeach
 
+if cc.has_function('getentropy',
+    args: test_c_args,
+    prefix: '''
+#include <unistd.h>
+@0@
+'''.format(cdata.get('HAVE_SYS_RANDOM_H') == 1 ? '#include <sys/random.h>' : ''))
+  cdata.set('HAVE_GETENTROPY', 1)
+endif
 
 if cc.has_type('struct option',
     args: test_c_args, include_directories: postgres_inc,
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index c4dc5d72bdb..147ab293518 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -172,6 +172,9 @@
 /* Define to 1 if you have the `getauxval' function. */
 #undef HAVE_GETAUXVAL
 
+/* Define to 1 if you have getentropy */
+#undef HAVE_GETENTROPY
+
 /* Define to 1 if you have the `getifaddrs' function. */
 #undef HAVE_GETIFADDRS
 
@@ -448,6 +451,9 @@
 /* Define to 1 if you have the <sys/procctl.h> header file. */
 #undef HAVE_SYS_PROCCTL_H
 
+/* Define to 1 if you have the <sys/random.h> header file. */
+#undef HAVE_SYS_RANDOM_H
+
 /* Define to 1 if you have the <sys/signalfd.h> header file. */
 #undef HAVE_SYS_SIGNALFD_H
 
diff --git a/src/port/pg_strong_random.c b/src/port/pg_strong_random.c
index ea6780dcc9f..da482e96ae7 100644
--- a/src/port/pg_strong_random.c
+++ b/src/port/pg_strong_random.c
@@ -40,7 +40,8 @@
  *
  * 1. OpenSSL's RAND_bytes()
  * 2. Windows' CryptGenRandom() function
- * 3. /dev/urandom
+ * 3. getentropy() function
+ * 4. /dev/urandom
  *
  * Returns true on success, and false if none of the sources
  * were available. NB: It is important to check the return value!
@@ -134,10 +135,49 @@ pg_strong_random(void *buf, size_t len)
     return false;
 }
 
-#else                            /* not USE_OPENSSL or WIN32 */
+#elif HAVE_GETENTROPY
+
+#include <limits.h>
+
+#ifdef HAVE_SYS_RANDOM_H
+#include <sys/random.h>
+#endif
+
+#ifndef GETENTROPY_MAX
+#define GETENTROPY_MAX    256
+#endif
+
+void
+pg_strong_random_init(void)
+{
+    /* No initialization needed */
+}
+
+bool
+pg_strong_random(void *buf, size_t len)
+{
+    char       *p = buf;
+    ssize_t        res;
+
+    while (len)
+    {
+        size_t        l = Min(len, GETENTROPY_MAX);
+
+        res = getentropy(p, l);
+        if (res < 0)
+            return false;
+
+        p += l;
+        len -= l;
+    }
+
+    return true;
+}
+
+#else                            /* not USE_OPENSSL, WIN32, or HAVE_GETENTROPY */
 
 /*
- * Without OpenSSL or Win32 support, just read /dev/urandom ourselves.
+ * Without OpenSSL, Win32, or getentropy() support, just read /dev/urandom ourselves.
  */
 
 void
-- 
2.50.1


Re: Support getrandom() for pg_strong_random() source

От
Daniel Gustafsson
Дата:
> On 30 Jul 2025, at 13:10, Peter Eisentraut <peter@eisentraut.org> wrote:
>
> On 30.07.25 08:59, Masahiko Sawada wrote:
>> I've updated the patch to support getentropy() instead of getrandom().
>
> The point still stands that the number of installations without OpenSSL support is approximately zero, so what is the
purposeof this patch if approximately no one will be able to use it? 

The main usecase I've heard discussed (mostly in hallway tracks IIRC) is to
allow multiple PRNG's so that codepaths which favor performance over
cryptographic properties can choose, this would not be that but a small step on
that path (whether or not that's the appropriate step is debatable).

For installations without OpenSSL, getrandom() as an API over /dev/urandom
still works when /dev is chrooted away.  That subset might be too small to
spend code on though.

--
Daniel Gustafsson




Re: Support getrandom() for pg_strong_random() source

От
Dagfinn Ilmari Mannsåker
Дата:
Dagfinn Ilmari Mannsåker <ilmari@ilmari.org> writes:

> Masahiko Sawada <sawada.mshk@gmail.com> writes:
>
>> On Tue, Jul 29, 2025 at 8:55 AM Jacob Champion
>> <jacob.champion@enterprisedb.com> wrote:
>>>
>>> On Mon, Jul 28, 2025 at 6:30 PM Michael Paquier <michael@paquier.xyz> wrote:
>>> > My understanding of the problem is that it is a choice of efficiency
>>> > vs entropy, and that it's not really possible to have both parts of
>>> > the cake.
>>
>> Agreed. I think the optimal choice would depend on the specific use
>> case. For instance, since UUIDs are not intended for security
>> purposes, they don't require particularly high entropy. In UUID
>> generation, the efficiency of random data generation tends to be
>> prioritized over the quality of randomness.
>>
>>>
>>> > Could getentropy() be more efficient at the end on most platforms,
>>> > meaning that this could limit the meaning of having a GUC switch?
>>>
>>> I don't know. [2] implies that the performance comparison depends on
>>> several factors, and falls in favor of OpenSSL when the number of
>>> bytes per call is large -- but our use of pg_strong_random() is
>>> generally on small buffers. We would need to do a _lot_ more research
>>> before, say, switching any defaults.
>>
>> The performance issue with getentropy, particularly when len=1024,
>> likely stems from the need for multiple getentropy() calls due to its
>> 256-byte length restriction.
>>
>> Analysis of RAND_bytes() through strace reveals that it internally
>> makes calls to getrandom() with a fixed length of 32 bytes. While I'm
>> uncertain of the exact purpose, it's logical that a single
>> getentropy() call would be more efficient than RAND_bytes(), which
>> involves additional overhead beyond just calling getrandom(),
>> especially when dealing with smaller byte sizes.
>>
>> I've updated the patch to support getentropy() instead of getrandom().
>
> Thanks, just a few comments:
>
> The blog post at
> https://dotat.at/@/2024-10-01-getentropy.html#portability-of-getentropy-
> points out a couple of caveats:
>
>  * Originally getentropy() was declared in <sys/random.h> but POSIX
>    declares it in <unistd.h>. You need to include both headers to be
>    sure.
>
> So the probes need to include both <sys/random.h> (if avaliable) and
> <unistd.h>,

I realised I got the conditional for this wrong, since
cdata.get('HAVE_SYS_RANDOM_H') can return either the integer 1 or the
boolean false, so it needs to be format()-ed and compared to a string.

Updated patch attached.

- ilmari

From 88b155c691806bd116b001334cad8ffc1f43e741 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Dagfinn=20Ilmari=20Manns=C3=A5ker?= <ilmari@ilmari.org>
Date: Wed, 30 Jul 2025 12:36:46 +0100
Subject: [PATCH v4] Support getentropy() as source of pg_strong_random() where
 available

---
 configure                   | 24 ++++++++++++++++++-
 configure.ac                |  8 ++++++-
 meson.build                 |  9 ++++++++
 src/include/pg_config.h.in  |  6 +++++
 src/port/pg_strong_random.c | 46 ++++++++++++++++++++++++++++++++++---
 5 files changed, 88 insertions(+), 5 deletions(-)

diff --git a/configure b/configure
index 507a2437c33..f11cd4265bf 100755
--- a/configure
+++ b/configure
@@ -16243,6 +16243,25 @@ cat >>confdefs.h <<_ACEOF
 _ACEOF
 
 
+ac_fn_c_check_header_mongrel "$LINENO" "sys/random.h" "ac_cv_header_sys_random_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_random_h" = xyes; then :
+  for ac_func in getentropy
+do :
+  ac_fn_c_check_func "$LINENO" "getentropy" "ac_cv_func_getentropy"
+if test "x$ac_cv_func_getentropy" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_GETENTROPY 1
+_ACEOF
+
+$as_echo "#define HAVE_GETENTROPY 1" >>confdefs.h
+
+fi
+done
+
+fi
+
+
+
 ac_fn_c_check_func "$LINENO" "explicit_bzero" "ac_cv_func_explicit_bzero"
 if test "x$ac_cv_func_explicit_bzero" = xyes; then :
   $as_echo "#define HAVE_EXPLICIT_BZERO 1" >>confdefs.h
@@ -18479,6 +18498,9 @@ $as_echo "Windows native" >&6; }
 elif test x"$cross_compiling" = x"yes"; then
   { $as_echo "$as_me:${as_lineno-$LINENO}: result: assuming /dev/urandom" >&5
 $as_echo "assuming /dev/urandom" >&6; }
+elif test x"$ac_cv_func_getentropy" = x"yes"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: getentropy" >&5
+$as_echo "getentropy" >&6; }
 else
   { $as_echo "$as_me:${as_lineno-$LINENO}: result: /dev/urandom" >&5
 $as_echo "/dev/urandom" >&6; }
@@ -18505,7 +18527,7 @@ fi
   if test x"$ac_cv_file__dev_urandom" = x"no" ; then
     as_fn_error $? "
 no source of strong random numbers was found
-PostgreSQL can use OpenSSL, native Windows API or /dev/urandom as a source of random numbers." "$LINENO" 5
+PostgreSQL can use OpenSSL, native Windows API, getentropy function, or /dev/urandom as a source of random numbers."
"$LINENO"5
 
   fi
 fi
 
diff --git a/configure.ac b/configure.ac
index 5f4548adc5c..9cf453fcd23 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1850,6 +1850,10 @@ AC_CHECK_DECLS([memset_s], [], [], [#define __STDC_WANT_LIB_EXT1__ 1
 # This is probably only present on macOS, but may as well check always
 AC_CHECK_DECLS(F_FULLFSYNC, [], [], [#include <fcntl.h>])
 
+AC_CHECK_HEADER([sys/random.h],
+ [AC_CHECK_FUNCS([getentropy],
+  [AC_DEFINE(HAVE_GETENTROPY, 1, [Define to 1 if you have getentropy])])])
+
 AC_REPLACE_FUNCS(m4_normalize([
     explicit_bzero
     getopt
@@ -2314,6 +2318,8 @@ elif test x"$PORTNAME" = x"win32" ; then
   AC_MSG_RESULT([Windows native])
 elif test x"$cross_compiling" = x"yes"; then
   AC_MSG_RESULT([assuming /dev/urandom])
+elif test x"$ac_cv_func_getentropy" = x"yes"; then
+  AC_MSG_RESULT(getentropy)
 else
   AC_MSG_RESULT([/dev/urandom])
   AC_CHECK_FILE([/dev/urandom], [], [])
@@ -2321,7 +2327,7 @@ else
   if test x"$ac_cv_file__dev_urandom" = x"no" ; then
     AC_MSG_ERROR([
 no source of strong random numbers was found
-PostgreSQL can use OpenSSL, native Windows API or /dev/urandom as a source of random numbers.])
+PostgreSQL can use OpenSSL, native Windows API, getentropy function, or /dev/urandom as a source of random numbers.])
   fi
 fi
 
diff --git a/meson.build b/meson.build
index ca423dc8e12..70f5d6494cb 100644
--- a/meson.build
+++ b/meson.build
@@ -2627,6 +2627,7 @@ header_checks = [
   'sys/personality.h',
   'sys/prctl.h',
   'sys/procctl.h',
+  'sys/random.h',
   'sys/signalfd.h',
   'sys/ucred.h',
   'termios.h',
@@ -2705,6 +2706,14 @@ return 0;
    don't.'''.format(func))
 endforeach
 
+if cc.has_function('getentropy',
+    args: test_c_args,
+    prefix: '''
+#include <unistd.h>
+@0@
+'''.format('@0@'.format(cdata.get('HAVE_SYS_RANDOM_H')) == '1' ? '#include <sys/random.h>' : ''))
+  cdata.set('HAVE_GETENTROPY', 1)
+endif
 
 if cc.has_type('struct option',
     args: test_c_args, include_directories: postgres_inc,
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index c4dc5d72bdb..147ab293518 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -172,6 +172,9 @@
 /* Define to 1 if you have the `getauxval' function. */
 #undef HAVE_GETAUXVAL
 
+/* Define to 1 if you have getentropy */
+#undef HAVE_GETENTROPY
+
 /* Define to 1 if you have the `getifaddrs' function. */
 #undef HAVE_GETIFADDRS
 
@@ -448,6 +451,9 @@
 /* Define to 1 if you have the <sys/procctl.h> header file. */
 #undef HAVE_SYS_PROCCTL_H
 
+/* Define to 1 if you have the <sys/random.h> header file. */
+#undef HAVE_SYS_RANDOM_H
+
 /* Define to 1 if you have the <sys/signalfd.h> header file. */
 #undef HAVE_SYS_SIGNALFD_H
 
diff --git a/src/port/pg_strong_random.c b/src/port/pg_strong_random.c
index ea6780dcc9f..da482e96ae7 100644
--- a/src/port/pg_strong_random.c
+++ b/src/port/pg_strong_random.c
@@ -40,7 +40,8 @@
  *
  * 1. OpenSSL's RAND_bytes()
  * 2. Windows' CryptGenRandom() function
- * 3. /dev/urandom
+ * 3. getentropy() function
+ * 4. /dev/urandom
  *
  * Returns true on success, and false if none of the sources
  * were available. NB: It is important to check the return value!
@@ -134,10 +135,49 @@ pg_strong_random(void *buf, size_t len)
     return false;
 }
 
-#else                            /* not USE_OPENSSL or WIN32 */
+#elif HAVE_GETENTROPY
+
+#include <limits.h>
+
+#ifdef HAVE_SYS_RANDOM_H
+#include <sys/random.h>
+#endif
+
+#ifndef GETENTROPY_MAX
+#define GETENTROPY_MAX    256
+#endif
+
+void
+pg_strong_random_init(void)
+{
+    /* No initialization needed */
+}
+
+bool
+pg_strong_random(void *buf, size_t len)
+{
+    char       *p = buf;
+    ssize_t        res;
+
+    while (len)
+    {
+        size_t        l = Min(len, GETENTROPY_MAX);
+
+        res = getentropy(p, l);
+        if (res < 0)
+            return false;
+
+        p += l;
+        len -= l;
+    }
+
+    return true;
+}
+
+#else                            /* not USE_OPENSSL, WIN32, or HAVE_GETENTROPY */
 
 /*
- * Without OpenSSL or Win32 support, just read /dev/urandom ourselves.
+ * Without OpenSSL, Win32, or getentropy() support, just read /dev/urandom ourselves.
  */
 
 void
-- 
2.50.1


Re: Support getrandom() for pg_strong_random() source

От
Peter Eisentraut
Дата:
On 30.07.25 13:55, Daniel Gustafsson wrote:
>> The point still stands that the number of installations without OpenSSL support is approximately zero, so what is
thepurpose of this patch if approximately no one will be able to use it?
 

> The main usecase I've heard discussed (mostly in hallway tracks IIRC) is to
> allow multiple PRNG's so that codepaths which favor performance over
> cryptographic properties can choose, this would not be that but a small step on
> that path (whether or not that's the appropriate step is debatable).

This sounds like a reasonable goal.  Intuitively, you want stronger 
randomness for hashing a password than for generating UUIDs.  Then 
again, it's not clear how much stronger exactly.  RFC 9562 does call for 
"cryptographically secure" random numbers.  Do we want multiple levels 
of "strong" or "secure"?  This needs a lot more analysis.



Re: Support getrandom() for pg_strong_random() source

От
Jacob Champion
Дата:
On Wed, Jul 30, 2025 at 4:09 AM Peter Eisentraut <peter@eisentraut.org> wrote:
> The POSIX description of getentropy() says:
>
> "The intended use of this function is to create a seed for other
> pseudo-random number generators."
>
> So using getentropy() for generating the random numbers that are passed
> back to the application code would appear to be the wrong use.

What are the situations in which a stream of numbers would be suitable
for seeding a CSPRNG, but not suitable as output from a CSPRNG?

On Wed, Jul 30, 2025 at 4:10 AM Peter Eisentraut <peter@eisentraut.org> wrote:
> The point still stands that the number of installations without OpenSSL
> support is approximately zero, so what is the purpose of this patch if
> approximately no one will be able to use it?

Upthread I'd suggested that we put some thought into making it
configurable, with the understanding that we'd need to document
exactly what we think the advantages of the approaches are.

--Jacob



Re: Support getrandom() for pg_strong_random() source

От
Peter Eisentraut
Дата:
On 30.07.25 18:13, Jacob Champion wrote:
> On Wed, Jul 30, 2025 at 4:09 AM Peter Eisentraut<peter@eisentraut.org> wrote:
>> The POSIX description of getentropy() says:
>>
>> "The intended use of this function is to create a seed for other
>> pseudo-random number generators."
>>
>> So using getentropy() for generating the random numbers that are passed
>> back to the application code would appear to be the wrong use.
> What are the situations in which a stream of numbers would be suitable
> for seeding a CSPRNG, but not suitable as output from a CSPRNG?

I imagine a "get entropy" operation could be very slow or even blocking, 
whereas a random number generator might just have to do some arithmetic 
starting from the previous seed state.

I mean, they called it "get entropy", not "get random", for a reason?




Re: Support getrandom() for pg_strong_random() source

От
Jacob Champion
Дата:
On Wed, Jul 30, 2025 at 12:58 PM Peter Eisentraut <peter@eisentraut.org> wrote:
> I imagine a "get entropy" operation could be very slow or even blocking,
> whereas a random number generator might just have to do some arithmetic
> starting from the previous seed state.

Agreed -- it could absolutely be slower, but if it's not slower in
practice in a user's environment, is there a problem with using it as
the basis for pg_strong_random()? That doesn't seem "wrong" to me; it
just seems like a tradeoff that would take investigation.

(The "blocking" fear is related to the research I linked above -- we
don't really want our CSPRNG to block in the way that /dev/random used
to, because that's not helpful. But we absolutely want it to block if
the CSPRNG state hasn't initialized yet. The goal continues to be
strength over performance IMO -- but there is circumstantial evidence
here that getentropy() could maybe get us both, in some environments.)

--Jacob



Re: Support getrandom() for pg_strong_random() source

От
Michael Paquier
Дата:
On Wed, Jul 30, 2025 at 02:03:53PM -0700, Jacob Champion wrote:
> On Wed, Jul 30, 2025 at 12:58 PM Peter Eisentraut <peter@eisentraut.org> wrote:
> > I imagine a "get entropy" operation could be very slow or even blocking,
> > whereas a random number generator might just have to do some arithmetic
> > starting from the previous seed state.
>
> Agreed -- it could absolutely be slower, but if it's not slower in
> practice in a user's environment, is there a problem with using it as
> the basis for pg_strong_random()? That doesn't seem "wrong" to me; it
> just seems like a tradeoff that would take investigation.

Yeah, we need to be careful here.  Having a blocking or less efficient
operation would be bad for the UUID generation, especially in
INSERT-only workloads and there are a lot of such things these days
that also want to maintain some uniqueness of the data gathered across
multiple nodes.  I'm questioning whether the UUID generation could
become a bottleneck if we are not careful, showing high in profiles.
--
Michael

Вложения

Re: Support getrandom() for pg_strong_random() source

От
Masahiko Sawada
Дата:
On Wed, Jul 30, 2025 at 2:04 PM Jacob Champion
<jacob.champion@enterprisedb.com> wrote:
>
> On Wed, Jul 30, 2025 at 12:58 PM Peter Eisentraut <peter@eisentraut.org> wrote:
> > I imagine a "get entropy" operation could be very slow or even blocking,
> > whereas a random number generator might just have to do some arithmetic
> > starting from the previous seed state.
>
> Agreed -- it could absolutely be slower, but if it's not slower in
> practice in a user's environment, is there a problem with using it as
> the basis for pg_strong_random()? That doesn't seem "wrong" to me; it
> just seems like a tradeoff that would take investigation.

Regarding glibc's getrandom() and getentropy() implementation[1],
getentropy() seems to be implemented as a wrapper of getrandom() in a
sense. That is, getrandom() has more fine grained control such as
specifying blocking behavior and the source (/dev/random or
/dev/urandom). glibc's getentropy() simply calls getrandom() with
flag=0 and 256 byte limitation. I think there is no difference between
random bytes generated by getrandom() and getentropy() in strength.
And according Linux manual for getentropy(),

A call to getentropy() may block if the system has just booted and the
kernel has not yet collected enough randomness to initialize the
entropy pool.

Which is the same behavior of calling getrandom() without GRND_NONBLOCK.

I believe FreeBSD's getentropy() is almost the same; it internally
calls getrandom()[2].

On the other hand, I found a blog post[3] (10 years-old post) that on
Solaris the output of getentropy() should not be used where randomness
is needed. I'm not sure it's still true but I guess that it might be
reasonable to consider that this is correct behavior in principle, and
that the behavior of glibc etc. is in some sense an exception.

Regards,

[1]
https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/getentropy.c;h=a62c9fb09962d4918a9c8cdd5545ad803b62fb82;hb=d2097651cc57834dbfcaa102ddfacae0d86cfb66
[2] https://github.com/freebsd/freebsd-src/blob/main/lib/libc/gen/getentropy.c
[3] https://blogs.oracle.com/solaris/post/solaris-new-system-calls-getentropy2-and-getrandom2

--
Masahiko Sawada
Amazon Web Services: https://aws.amazon.com



Re: Support getrandom() for pg_strong_random() source

От
Jacob Champion
Дата:
On Fri, Aug 8, 2025 at 3:25 PM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
> On the other hand, I found a blog post[3] (10 years-old post) that on
> Solaris the output of getentropy() should not be used where randomness
> is needed. I'm not sure it's still true but I guess that it might be
> reasonable to consider that this is correct behavior in principle, and
> that the behavior of glibc etc. is in some sense an exception.

Thanks for finding that! Ah, FIPS:

> More specifically the data returned by getentropy(2) has not had the required FIPS 140-2 processing for the DRBG
appliedto it. 

So FIPS compliance is a case where "a stream of numbers would be
suitable for seeding a CSPRNG, but not suitable as output from a
CSPRNG". That's evidence enough for me to abandon my preference for
getentropy() (whether Solaris still does that or not).

I've been looking at libsodium's randomness implementations [1]:

> On Windows systems, the RtlGenRandom() function is used.
> On OpenBSD and Bitrig, the arc4random() function is used.
> On recent FreeBSD and Linux kernels, the getrandom system call is used.
> On other Unices, the /dev/urandom device is used.

(Note that libsodium has some internal concept of a "safe" arc4random
implementation, which it locks to certain platforms. If an OS is still
literally using RC4 we would not want to use it.)

So, my next question: is getrandom() always preferable to /dev/urandom?

--Jacob

[1] https://doc.libsodium.org/generating_random_data



Re: Support getrandom() for pg_strong_random() source

От
Masahiko Sawada
Дата:
On Tue, Jul 29, 2025 at 9:38 AM Dagfinn Ilmari Mannsåker
<ilmari@ilmari.org> wrote:
>
> Jacob Champion <jacob.champion@enterprisedb.com> writes:
>
> > On Mon, Jul 28, 2025 at 6:30 PM Michael Paquier <michael@paquier.xyz> wrote:
> >
> >> Could getentropy() be more efficient at the end on most platforms,
> >> meaning that this could limit the meaning of having a GUC switch?
> >
> > I don't know. [2] implies that the performance comparison depends on
> > several factors, and falls in favor of OpenSSL when the number of
> > bytes per call is large
> [...]
> > [2] https://dotat.at/@/2024-10-01-getentropy.html
>
> Note that that test was done on an older Linux kernel without the vDSO
> implementation of getentropy(), so on newer kernel (>=6.11) and glibc
> (>= 2.41) versions the difference might be smaller or the other way
> around.

FYI I've benchmarked vDSO implementation of getrandom() with Fedora 42
(kernel 6.15, glibc 2.41). I've modified the test program linked by
the blog post[1] so that it measures vDSO implementation of
getrandom() and directly calling getrandom system call. I've attached
the test program. Here is the result:

$ ./bench
init openssl    1929533

        len    entropy    openssl vgetrandom  getrandom
         16        353        400         39        235
         64        373        401        125        368
        256        675        420        432        664
       1024       2651        494       1352       1792

The 'vgetrandom' column shows nanoseconds per function call of vDSO
implementation of getrandom() function whereas the 'getrandom' column
shows nanoseconds per getrandom system call.

For smaller bytes, vgetrandom (i.e., simply calling the getrandom()
function) is much faster than other methods. For larger bytes (such
1024), openssl had the best performance. This fact is very attractive
to me in terms of using it for UUID generation.

Regards,

[1] https://dotat.at/@/2024-10-01-getentropy.html

--
Masahiko Sawada
Amazon Web Services: https://aws.amazon.com

Вложения

Re: Support getrandom() for pg_strong_random() source

От
Masahiko Sawada
Дата:
On Fri, Aug 8, 2025 at 3:37 PM Jacob Champion
<jacob.champion@enterprisedb.com> wrote:
>
> On Fri, Aug 8, 2025 at 3:25 PM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
> > On the other hand, I found a blog post[3] (10 years-old post) that on
> > Solaris the output of getentropy() should not be used where randomness
> > is needed. I'm not sure it's still true but I guess that it might be
> > reasonable to consider that this is correct behavior in principle, and
> > that the behavior of glibc etc. is in some sense an exception.
>
> Thanks for finding that! Ah, FIPS:
>
> > More specifically the data returned by getentropy(2) has not had the required FIPS 140-2 processing for the DRBG
appliedto it. 
>
> So FIPS compliance is a case where "a stream of numbers would be
> suitable for seeding a CSPRNG, but not suitable as output from a
> CSPRNG". That's evidence enough for me to abandon my preference for
> getentropy() (whether Solaris still does that or not).

Makes sense.

>
> I've been looking at libsodium's randomness implementations [1]:
>
> > On Windows systems, the RtlGenRandom() function is used.
> > On OpenBSD and Bitrig, the arc4random() function is used.
> > On recent FreeBSD and Linux kernels, the getrandom system call is used.
> > On other Unices, the /dev/urandom device is used.
>
> (Note that libsodium has some internal concept of a "safe" arc4random
> implementation, which it locks to certain platforms. If an OS is still
> literally using RC4 we would not want to use it.)
>
> So, my next question: is getrandom() always preferable to /dev/urandom?

I believe so. While /dev/urandom source should be kept as a fallback
for older kernels, we should use getrandom() if available. For
example, getrandom() can be used even in the face of file-descriptor
exhaustion and lack of access to the random devices[1]. Also, it would
be much faster than reading /dev/urandom as I shared the benchmark
result[2].

Regards,

[1] https://lwn.net/Articles/884875/
[2] https://www.postgresql.org/message-id/CAD21AoD1%2B6FwGb0d4W3YEwOVJi_McuyuvpnjUJE8B8Ejy21MMw%40mail.gmail.com

--
Masahiko Sawada
Amazon Web Services: https://aws.amazon.com



Re: Support getrandom() for pg_strong_random() source

От
Jacob Champion
Дата:
On Thu, Aug 14, 2025 at 3:16 PM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
>
> On Fri, Aug 8, 2025 at 3:37 PM Jacob Champion
> <jacob.champion@enterprisedb.com> wrote:
>
> > So, my next question: is getrandom() always preferable to /dev/urandom?
>
> I believe so. While /dev/urandom source should be kept as a fallback
> for older kernels, we should use getrandom() if available. For
> example, getrandom() can be used even in the face of file-descriptor
> exhaustion and lack of access to the random devices[1]. Also, it would
> be much faster than reading /dev/urandom as I shared the benchmark
> result[2].

Yeah. My personal reasons to be excited about it are
1) the newer, more sensible one-shot blocking behavior for safety, and
2) the ability for the OS to figure out when a virtualized environment
has potentially "forked"

So I think I would be in favor of adding this as an always-preferred
alternative to /dev/urandom, to begin.

Thinking a bit further ahead: what are some criteria we would need to
research to decide whether getrandom() would be preferable to OpenSSL?
Gathering a couple of considerations from upthread:
- FIPS behavior
- Speed vs. size of a "typical" request
- Version-specific behavior of OpenSSL and/or the OS
- Need for safety in virtualized environments
- ...?

Thanks,
--Jacob



Re: Support getrandom() for pg_strong_random() source

От
Michael Paquier
Дата:
On Mon, Aug 18, 2025 at 08:38:25AM -0700, Jacob Champion wrote:
> - Need for safety in virtualized environments
> - ...?

Interesting.  What do you mean by this point?  Isolation of the
random computations on a VM/container basis even if these are
originally from the same host?
--
Michael

Вложения

Re: Support getrandom() for pg_strong_random() source

От
Jacob Champion
Дата:
On Mon, Aug 18, 2025 at 4:17 PM Michael Paquier <michael@paquier.xyz> wrote:
>
> On Mon, Aug 18, 2025 at 08:38:25AM -0700, Jacob Champion wrote:
> > - Need for safety in virtualized environments
> > - ...?
>
> Interesting.  What do you mean by this point?  Isolation of the
> random computations on a VM/container basis even if these are
> originally from the same host?

One motivating example is "I paused my VM and cloned it and now both
application instances are giving me the same random numbers." (I
haven't looked into OpenSSL enough to know if it has developed some
magic way around this, for the record.) NetBSD talks about this a bit
at [1].

I'd imagine that there are other nice things about moving it down into
the kernel, like core dumps becoming ever so slightly less dangerous?
But that's pretty out there.

--Jacob

[1] https://man.netbsd.org/acpivmgenid.4



Re: Support getrandom() for pg_strong_random() source

От
Masahiko Sawada
Дата:
On Mon, Aug 18, 2025 at 8:38 AM Jacob Champion
<jacob.champion@enterprisedb.com> wrote:
>
> On Thu, Aug 14, 2025 at 3:16 PM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
> >
> > On Fri, Aug 8, 2025 at 3:37 PM Jacob Champion
> > <jacob.champion@enterprisedb.com> wrote:
> >
> > > So, my next question: is getrandom() always preferable to /dev/urandom?
> >
> > I believe so. While /dev/urandom source should be kept as a fallback
> > for older kernels, we should use getrandom() if available. For
> > example, getrandom() can be used even in the face of file-descriptor
> > exhaustion and lack of access to the random devices[1]. Also, it would
> > be much faster than reading /dev/urandom as I shared the benchmark
> > result[2].
>
> Yeah. My personal reasons to be excited about it are
> 1) the newer, more sensible one-shot blocking behavior for safety, and
> 2) the ability for the OS to figure out when a virtualized environment
> has potentially "forked"
>
> So I think I would be in favor of adding this as an always-preferred
> alternative to /dev/urandom, to begin.
>
> Thinking a bit further ahead: what are some criteria we would need to
> research to decide whether getrandom() would be preferable to OpenSSL?
> Gathering a couple of considerations from upthread:
> - FIPS behavior

Do you mean random numbers generated by getrandom() complaints FIPS?
Based on my research, there doesn't appear to be any explicit
statement indicating that Linux's CSPRNG module complies with FIPS
requirements. However, there is a proposal to implement LRNG[1], which
would be FIPS-compliant. In systems that require FIPS compliance, it
seems that random numbers generated by getrandom() (or getentropy())
are typically used as a seed for FIPS-compliant random number
generators, such as OpenSSL's RAND_bytes() function.

Regards,

[1] https://lwn.net/Articles/877607/

--
Masahiko Sawada
Amazon Web Services: https://aws.amazon.com



Re: Support getrandom() for pg_strong_random() source

От
Jacob Champion
Дата:
On Mon, Aug 25, 2025 at 11:30 AM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
> > Gathering a couple of considerations from upthread:
> > - FIPS behavior
>
> Do you mean random numbers generated by getrandom() complaints FIPS?
> Based on my research, there doesn't appear to be any explicit
> statement indicating that Linux's CSPRNG module complies with FIPS
> requirements. However, there is a proposal to implement LRNG[1], which
> would be FIPS-compliant.

Right. I guess what I'm asking with that particular bullet point is:

If, tomorrow, I threw caution to the wind and proposed that we use
getrandom() on Linux over OpenSSL by default, would any FIPS users
complain? Or are they all using distributions that have already
applied FIPS patches to the getrandom() part of the kernel anyway?

(But I intended for that to be a possible future point of discussion,
not a blocker for your smaller proposal.)

Thanks,
--Jacob



Re: Support getrandom() for pg_strong_random() source

От
Masahiko Sawada
Дата:
On Mon, Aug 25, 2025 at 1:07 PM Jacob Champion
<jacob.champion@enterprisedb.com> wrote:
>
> On Mon, Aug 25, 2025 at 11:30 AM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
> > > Gathering a couple of considerations from upthread:
> > > - FIPS behavior
> >
> > Do you mean random numbers generated by getrandom() complaints FIPS?
> > Based on my research, there doesn't appear to be any explicit
> > statement indicating that Linux's CSPRNG module complies with FIPS
> > requirements. However, there is a proposal to implement LRNG[1], which
> > would be FIPS-compliant.
>
> Right. I guess what I'm asking with that particular bullet point is:
>
> If, tomorrow, I threw caution to the wind and proposed that we use
> getrandom() on Linux over OpenSSL by default, would any FIPS users
> complain? Or are they all using distributions that have already
> applied FIPS patches to the getrandom() part of the kernel anyway?

Valid point. I guess the approach of selecting the random number
source at compile time might be inflexible, and there does not seem to
be a one-size-fits-all solution when it comes to things like this. The
fact made me think we could have PostgreSQL select its random number
source when it starts up instead of compile time, giving us the
flexibility to cater to various scenarios. For instance, we could
introduce a GUC parameter that lets users specify their preferred
random number source. Or the server can automatically select it based
on the kernel's FIPS mode (i.e., checking
/proc/sys/crypto/fips_enabled).

Regards,

--
Masahiko Sawada
Amazon Web Services: https://aws.amazon.com



Re: Support getrandom() for pg_strong_random() source

От
Jacob Champion
Дата:
On Mon, Aug 25, 2025 at 3:22 PM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
>
> For instance, we could
> introduce a GUC parameter that lets users specify their preferred
> random number source. Or the server can automatically select it based
> on the kernel's FIPS mode (i.e., checking
> /proc/sys/crypto/fips_enabled).

Interesting idea. (Are there any users reading along who would
definitely use such a feature?)

--Jacob



Re: Support getrandom() for pg_strong_random() source

От
Daniel Gustafsson
Дата:
> On 26 Aug 2025, at 00:38, Jacob Champion <jacob.champion@enterprisedb.com> wrote:
>
> On Mon, Aug 25, 2025 at 3:22 PM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
>>
>> For instance, we could
>> introduce a GUC parameter that lets users specify their preferred
>> random number source. Or the server can automatically select it based
>> on the kernel's FIPS mode (i.e., checking
>> /proc/sys/crypto/fips_enabled).
>
> Interesting idea. (Are there any users reading along who would
> definitely use such a feature?)

I worry about the added complexity this would bring.  It's already quite
complicated to configure postgres, and making an informed decision about which
RNG source to choose for cryptographically strong random won't be easy without
domain knowledge.

Taking a step back and re-reading the thread, this started as a proposal to
improve uuid generation on non-Windows platforms when not using OpenSSL.  While
non-SSL installations will be incredibly rare in production, it will likely be
a bit more common in PG development situations and speeding up test-runs in
such situations has value.  I think this thread has shown merit to the idea of
replacing using /dev/urandom with a more modern API, but after sleeping on it
I'm less convinced that a'la carte CSPRNG configuration has enough upsides to
warrant the risk of users accidentally becoming non-FIPS compliant.

Another related thing to consider, uuid-ossp contrib module use arc4random() in
the non e2fs case.

--
Daniel Gustafsson




Re: Support getrandom() for pg_strong_random() source

От
Masahiko Sawada
Дата:
On Tue, Aug 26, 2025 at 12:42 AM Daniel Gustafsson <daniel@yesql.se> wrote:
>
> > On 26 Aug 2025, at 00:38, Jacob Champion <jacob.champion@enterprisedb.com> wrote:
> >
> > On Mon, Aug 25, 2025 at 3:22 PM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
> >>
> >> For instance, we could
> >> introduce a GUC parameter that lets users specify their preferred
> >> random number source. Or the server can automatically select it based
> >> on the kernel's FIPS mode (i.e., checking
> >> /proc/sys/crypto/fips_enabled).
> >
> > Interesting idea. (Are there any users reading along who would
> > definitely use such a feature?)
>
> I worry about the added complexity this would bring.  It's already quite
> complicated to configure postgres, and making an informed decision about which
> RNG source to choose for cryptographically strong random won't be easy without
> domain knowledge.
>
> Taking a step back and re-reading the thread, this started as a proposal to
> improve uuid generation on non-Windows platforms when not using OpenSSL.  While
> non-SSL installations will be incredibly rare in production, it will likely be
> a bit more common in PG development situations and speeding up test-runs in
> such situations has value.  I think this thread has shown merit to the idea of
> replacing using /dev/urandom with a more modern API, but after sleeping on it
> I'm less convinced that a'la carte CSPRNG configuration has enough upsides to
> warrant the risk of users accidentally becoming non-FIPS compliant.

The primary motivation is to enhance the performance of random data
generation and UUID creation in scenarios where FIPS compliance is not
mandatory. As I previously reported[1], getrandom() demonstrates
superior performance for small random data operations, with the
efficiency gain becoming even more significant in newer kernels thanks
to the vDSO implementation of getrandom() (note that I assume
cryptographic equivalence between random data generated by
RAND_bytes() in non-FIPS mode and that produced by getrandom()).

Although this would introduce additional configuration complexity, I
guess that FIPS-compliant random data is unnecessary for most users,
and getrandom()'s output is typically sufficient for many
implementations. I think while maintaining RAND_bytes() as the default
option for OpenSSL-enabled installations, we could somehow provide
users with the flexibility to opt for getrandom() when preferred.

>
> Another related thing to consider, uuid-ossp contrib module use arc4random() in
> the non e2fs case.

An alternative approach for users seeking to generate UUIDs via
getrandom() would be to utilize UUIDv7 through uuid_generate_time_v7()
provided by libuuid in e2fs cases. Since this method internally
leverages getrandom(), it should benefit from vDSO execution
capabilities. However, we need to note that UUIDv7 values generated
through uuid_generate_time_v7() exhibit several distinctions from
those produced by PostgreSQL's implementation.

Regards,

[1] https://www.postgresql.org/message-id/CAD21AoD1%2B6FwGb0d4W3YEwOVJi_McuyuvpnjUJE8B8Ejy21MMw%40mail.gmail.com

--
Masahiko Sawada
Amazon Web Services: https://aws.amazon.com



Re: Support getrandom() for pg_strong_random() source

От
Masahiko Sawada
Дата:
On Wed, Aug 27, 2025 at 4:48 PM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
>
> On Tue, Aug 26, 2025 at 12:42 AM Daniel Gustafsson <daniel@yesql.se> wrote:
> >
> > > On 26 Aug 2025, at 00:38, Jacob Champion <jacob.champion@enterprisedb.com> wrote:
> > >
> > > On Mon, Aug 25, 2025 at 3:22 PM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
> > >>
> > >> For instance, we could
> > >> introduce a GUC parameter that lets users specify their preferred
> > >> random number source. Or the server can automatically select it based
> > >> on the kernel's FIPS mode (i.e., checking
> > >> /proc/sys/crypto/fips_enabled).
> > >
> > > Interesting idea. (Are there any users reading along who would
> > > definitely use such a feature?)
> >
> > I worry about the added complexity this would bring.  It's already quite
> > complicated to configure postgres, and making an informed decision about which
> > RNG source to choose for cryptographically strong random won't be easy without
> > domain knowledge.
> >
> > Taking a step back and re-reading the thread, this started as a proposal to
> > improve uuid generation on non-Windows platforms when not using OpenSSL.  While
> > non-SSL installations will be incredibly rare in production, it will likely be
> > a bit more common in PG development situations and speeding up test-runs in
> > such situations has value.  I think this thread has shown merit to the idea of
> > replacing using /dev/urandom with a more modern API, but after sleeping on it
> > I'm less convinced that a'la carte CSPRNG configuration has enough upsides to
> > warrant the risk of users accidentally becoming non-FIPS compliant.
>
> The primary motivation is to enhance the performance of random data
> generation and UUID creation in scenarios where FIPS compliance is not
> mandatory. As I previously reported[1], getrandom() demonstrates
> superior performance for small random data operations, with the
> efficiency gain becoming even more significant in newer kernels thanks
> to the vDSO implementation of getrandom() (note that I assume
> cryptographic equivalence between random data generated by
> RAND_bytes() in non-FIPS mode and that produced by getrandom()).
>
> Although this would introduce additional configuration complexity, I
> guess that FIPS-compliant random data is unnecessary for most users,
> and getrandom()'s output is typically sufficient for many
> implementations. I think while maintaining RAND_bytes() as the default
> option for OpenSSL-enabled installations, we could somehow provide
> users with the flexibility to opt for getrandom() when preferred.

I've drafted this idea and attached two patches. The first patch
allows the user to select the random source function used in the
backend. 'openssl' is the default value if PostgreSQL is built with
openssl but users can set it to 'system' use the '/dev/urandom/'
approach (or CryptGenRandom on Windows) instead if they want. In
frontend code, there is nothing changed; the actual implementation of
pg_strong_random is chosed at build time and openssl's RAND_bytes() is
always used if the source code is built with openssl. Therefore, it
doesn't break any existing use cases but provides a way to select the
random source function.The second patch adds support for getrandom()
as the default random source of 'system' random source type on
Unix-like platforms.

With these two patches, for example, users can set random_source_type
to 'system' in the configuration file or a connection string in order
to use getrandom() for random data generation for UUID generation even
on openssl-enabled builds:

% echo "show random_source_type; select uuidv7();"  | bin/psql -d
"dbname=postgres port=5432 options='-c random_source_type=openssl'" -X
 random_source_type
--------------------
 openssl
(1 row)

                uuidv7
--------------------------------------
 01997599-b6b6-7590-9825-f36253059956
(1 row)

% echo "show random_source_type; select uuidv7();"  | bin/psql -d
"dbname=postgres port=5432 options='-c random_source_type=system'" -X
 random_source_type
--------------------
 system
(1 row)

                uuidv7
--------------------------------------
 01997599-f069-76b6-9ce2-0308d0cd6a0b
(1 row)

Regards,

--
Masahiko Sawada
Amazon Web Services: https://aws.amazon.com

Вложения

Re: Support getrandom() for pg_strong_random() source

От
Jacob Champion
Дата:
On Tue, Sep 23, 2025 at 1:41 AM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
> With these two patches, for example, users can set random_source_type
> to 'system' in the configuration file or a connection string in order
> to use getrandom() for random data generation for UUID generation even
> on openssl-enabled builds:

I'm wary of letting unprivileged users switch this implementation. I
think our developers should be allowed to treat the user as an
adversary when developing features on top of pg_strong_random(), and
it doesn't make sense for an adversary to control properties of your
CSPRNG. I'm also worried that allowing users to change the FIPS
properties of their systems could lead to compliance headaches for
some DBAs, but maybe somebody knows a reason why that wouldn't be a
concern in practice.

But if only a superuser can change this, I'm not sure that it's going
to fit your use case anymore. Which probably brings the conversation
back to Daniel's note upthread -- is it worth the cost to expose this
as a runtime knob?

--Jacob



Re: Support getrandom() for pg_strong_random() source

От
Michael Paquier
Дата:
On Mon, Sep 29, 2025 at 03:15:37PM -0700, Jacob Champion wrote:
> I'm wary of letting unprivileged users switch this implementation. I
> think our developers should be allowed to treat the user as an
> adversary when developing features on top of pg_strong_random(), and
> it doesn't make sense for an adversary to control properties of your
> CSPRNG. I'm also worried that allowing users to change the FIPS
> properties of their systems could lead to compliance headaches for
> some DBAs, but maybe somebody knows a reason why that wouldn't be a
> concern in practice.

I'm pretty sure that all cloud vendors would face this dilemma, and
another thing that I suspect it that they would restrict entirely the
access to this GUC.

> But if only a superuser can change this, I'm not sure that it's going
> to fit your use case anymore. Which probably brings the conversation
> back to Daniel's note upthread -- is it worth the cost to expose this
> as a runtime knob?

I don't think we should expose that as a runtime-updatable parameter.
Even for UUIDs, I am reading the RFC as "more entropy the better" and
I would choose entropy over performance every single day, because it's
a no brainer if you care about cryptography, especially if this option
enforces which source to use for for *all* code paths that want random
bytes.  So there is no deal about performance here, at least IMHO.

Even as a superuser parameter, I'm having cold feet with this
prospect.  There are two aspects not discussed on this thread that
could justify a PGC_POSTMASTER:
- Testing, by being able to switch from one source to the other,
providing more coverage with external libraries, useful for the
buildfarm.
- Insurance policy against vendor and library bugs.  By switching to a
different source with an existing build, it is possible to redirect
the source of a bug somewhere else.  It was also one of the reasons
behind the GUCs that control the SSL protocol versions, where we
wanted to bypass some versions.  With TLSv3, this is less an issue
these days, compared to SSLv1/2, still the argument applied when the
SSL protocol GUCs were added.
--
Michael

Вложения

Re: Support getrandom() for pg_strong_random() source

От
Masahiko Sawada
Дата:
On Mon, Sep 29, 2025 at 11:01 PM Michael Paquier <michael@paquier.xyz> wrote:
>
> On Mon, Sep 29, 2025 at 03:15:37PM -0700, Jacob Champion wrote:
> > I'm wary of letting unprivileged users switch this implementation. I
> > think our developers should be allowed to treat the user as an
> > adversary when developing features on top of pg_strong_random(), and
> > it doesn't make sense for an adversary to control properties of your
> > CSPRNG. I'm also worried that allowing users to change the FIPS
> > properties of their systems could lead to compliance headaches for
> > some DBAs, but maybe somebody knows a reason why that wouldn't be a
> > concern in practice.
>
> I'm pretty sure that all cloud vendors would face this dilemma, and
> another thing that I suspect it that they would restrict entirely the
> access to this GUC.
>
> > But if only a superuser can change this, I'm not sure that it's going
> > to fit your use case anymore. Which probably brings the conversation
> > back to Daniel's note upthread -- is it worth the cost to expose this
> > as a runtime knob?
>
> I don't think we should expose that as a runtime-updatable parameter.

I agree that it should not be exposed as a runtime parameter.

> Even for UUIDs, I am reading the RFC as "more entropy the better" and
> I would choose entropy over performance every single day, because it's
> a no brainer if you care about cryptography, especially if this option
> enforces which source to use for for *all* code paths that want random
> bytes.  So there is no deal about performance here, at least IMHO.

I'm still studying this area but is there any difference in entropy
between random numbers generated by getrandom() and OpenSSL's
RAND_bytes() in terms of entropy? The RFC says "Implementations SHOULD
utilize a cryptographically secure pseudorandom number generator
(CSPRNG) to provide values that are both difficult to predict
("unguessable") and have a low likelihood of collision ("unique")."
and IIUC getrandom() generates random numbers from the kernel's CSPRNG
module.

>
> Even as a superuser parameter, I'm having cold feet with this
> prospect.  There are two aspects not discussed on this thread that
> could justify a PGC_POSTMASTER:
> - Testing, by being able to switch from one source to the other,
> providing more coverage with external libraries, useful for the
> buildfarm.
> - Insurance policy against vendor and library bugs.  By switching to a
> different source with an existing build, it is possible to redirect
> the source of a bug somewhere else.  It was also one of the reasons
> behind the GUCs that control the SSL protocol versions, where we
> wanted to bypass some versions.  With TLSv3, this is less an issue
> these days, compared to SSLv1/2, still the argument applied when the
> SSL protocol GUCs were added.

Interesting points. If we can provide a knob as a GUC, I agree that it
should be a PGC_POSTMASTER parameter.

Regards,

--
Masahiko Sawada
Amazon Web Services: https://aws.amazon.com



Re: Support getrandom() for pg_strong_random() source

От
Daniel Gustafsson
Дата:
> On 30 Sep 2025, at 00:15, Jacob Champion <jacob.champion@enterprisedb.com> wrote:

> I'm wary of letting unprivileged users switch this implementation. I
> think our developers should be allowed to treat the user as an
> adversary when developing features on top of pg_strong_random(), and
> it doesn't make sense for an adversary to control properties of your
> CSPRNG.

Agreed.

> I'm also worried that allowing users to change the FIPS
> properties of their systems could lead to compliance headaches for
> some DBAs,

Very much so.  It might not move the needle in practice, but the fact that it
could be changed will inevitably lead to a feature request to be able to
disable it.


I think we're trying to fit two square pegs in the same not-square hole here.
While none of the pegs want poor entropy, one (for example UUID generation)
favours speed over CSPRNG properties where the other couldn't care less about
speed if any CSPRNG properties are even looked at the wrong way on a bad day.

What if we instead expand the API to provide pg_random (or pg_fast_random)
which can be a selectable implementation, and pg_strong_random is left as today
a compile time selection?  This would allow extension authors and built-in *non
security/auth* features which need to squeeze all the performance they can out
of the API to use an alternative implementation while leaving pg_strong_random
to give CSPRNG guarantees to code that need it.

--
Daniel Gustafsson




Re: Support getrandom() for pg_strong_random() source

От
Masahiko Sawada
Дата:
On Tue, Sep 30, 2025 at 12:44 AM Daniel Gustafsson <daniel@yesql.se> wrote:
>
> > On 30 Sep 2025, at 00:15, Jacob Champion <jacob.champion@enterprisedb.com> wrote:
>
> > I'm wary of letting unprivileged users switch this implementation. I
> > think our developers should be allowed to treat the user as an
> > adversary when developing features on top of pg_strong_random(), and
> > it doesn't make sense for an adversary to control properties of your
> > CSPRNG.
>
> Agreed.
>
> > I'm also worried that allowing users to change the FIPS
> > properties of their systems could lead to compliance headaches for
> > some DBAs,
>
> Very much so.  It might not move the needle in practice, but the fact that it
> could be changed will inevitably lead to a feature request to be able to
> disable it.
>
>
> I think we're trying to fit two square pegs in the same not-square hole here.
> While none of the pegs want poor entropy, one (for example UUID generation)
> favours speed over CSPRNG properties where the other couldn't care less about
> speed if any CSPRNG properties are even looked at the wrong way on a bad day.
>
> What if we instead expand the API to provide pg_random (or pg_fast_random)
> which can be a selectable implementation, and pg_strong_random is left as today
> a compile time selection?  This would allow extension authors and built-in *non
> security/auth* features which need to squeeze all the performance they can out
> of the API to use an alternative implementation while leaving pg_strong_random
> to give CSPRNG guarantees to code that need it.

Sounds reasonable. But I have one question: in systems that must be
FIPS compliant, is it okay to generate UUIDs using random numbers from
non-FIPS compliant sources? If yes, we can use
pg_random/pg_fast_random() for UUID generation in all cases.

Regards,

--
Masahiko Sawada
Amazon Web Services: https://aws.amazon.com