Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit6645ad6

Browse files
committed
Use a separate random seed for SQL random()/setseed() functions.
Previously, the SQL random() function depended on libc's random(3),and setseed() invoked srandom(3). This results in interference betweenthese functions and backend-internal uses of random(3). We'd never paidtoo much mind to that, but in the wake of commit88bdbd3 which addedlog_statement_sample_rate, the interference arguably has a securityconsequence: if log_statement_sample_rate is active then an unprivilegeduser could probably control which if any of his SQL commands get logged,by issuing setseed() at the right times. That seems bad.To fix this reliably, we need random() and setseed() to use their ownprivate random state variable. Standard random(3) isn't amenable to suchusage, so let's switch to pg_erand48(). It's hard to say whether that'smore or less "random" than any particular platform's version of random(3),but it does have a wider seed value and a longer period than are requiredby POSIX, so we can hope that this isn't a big downgrade. Also, we shouldnow have uniform behavior of random() across platforms, which is worthsomething.While at it, upgrade the per-process seed initialization method to usepg_strong_random() if available, greatly reducing the predictabilityof the initial seed value. (I'll separately do something similar forthe internal uses of random().)In addition to forestalling the possible security problem, this has abenefit in the other direction, which is that we can now documentsetseed() as guaranteeing a reproducible sequence of random() values.Previously, because of the possibility of internal calls of random(3),we could not promise any such thing.Discussion:https://postgr.es/m/3859.1545849900@sss.pgh.pa.us
1 parent1a4eba4 commit6645ad6

File tree

2 files changed

+53
-13
lines changed

2 files changed

+53
-13
lines changed

‎doc/src/sgml/func.sgml

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1136,11 +1136,15 @@
11361136
</table>
11371137

11381138
<para>
1139-
The characteristics of the values returned by
1140-
<literal><function>random()</function></literal> depend
1141-
on the system implementation. It is not suitable for cryptographic
1142-
applications; see <xref linkend="pgcrypto"/> module for an alternative.
1143-
</para>
1139+
The <function>random()</function> function uses a simple linear
1140+
congruential algorithm. It is fast but not suitable for cryptographic
1141+
applications; see the <xref linkend="pgcrypto"/> module for a more
1142+
secure alternative.
1143+
If <function>setseed()</function> is called, the results of
1144+
subsequent <function>random()</function> calls in the current session are
1145+
repeatable by re-issuing <function>setseed()</function> with the same
1146+
argument.
1147+
</para>
11441148

11451149
<para>
11461150
Finally, <xref linkend="functions-math-trig-table"/> shows the

‎src/backend/utils/adt/float.c

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,13 @@
2222
#include"catalog/pg_type.h"
2323
#include"common/int.h"
2424
#include"libpq/pqformat.h"
25+
#include"miscadmin.h"
2526
#include"utils/array.h"
27+
#include"utils/backend_random.h"
2628
#include"utils/float.h"
2729
#include"utils/fmgrprotos.h"
2830
#include"utils/sortsupport.h"
31+
#include"utils/timestamp.h"
2932

3033

3134
/* Configurable GUC parameter */
@@ -53,6 +56,10 @@ float8degree_c_sixty = 60.0;
5356
float8degree_c_one_half=0.5;
5457
float8degree_c_one=1.0;
5558

59+
/* State for drandom() and setseed() */
60+
staticbooldrandom_seed_set= false;
61+
staticunsigned shortdrandom_seed[3]= {0,0,0};
62+
5663
/* Local function prototypes */
5764
staticdoublesind_q1(doublex);
5865
staticdoublecosd_q1(doublex);
@@ -2378,8 +2385,30 @@ drandom(PG_FUNCTION_ARGS)
23782385
{
23792386
float8result;
23802387

2381-
/* result [0.0 - 1.0) */
2382-
result= (double)random() / ((double)MAX_RANDOM_VALUE+1);
2388+
/* Initialize random seed, if not done yet in this process */
2389+
if (unlikely(!drandom_seed_set))
2390+
{
2391+
/*
2392+
* If possible, initialize the seed using high-quality random bits.
2393+
* Should that fail for some reason, we fall back on a lower-quality
2394+
* seed based on current time and PID.
2395+
*/
2396+
if (!pg_backend_random((char*)drandom_seed,sizeof(drandom_seed)))
2397+
{
2398+
TimestampTznow=GetCurrentTimestamp();
2399+
uint64iseed;
2400+
2401+
/* Mix the PID with the most predictable bits of the timestamp */
2402+
iseed= (uint64)now ^ ((uint64)MyProcPid <<32);
2403+
drandom_seed[0]= (unsigned short)iseed;
2404+
drandom_seed[1]= (unsigned short) (iseed >>16);
2405+
drandom_seed[2]= (unsigned short) (iseed >>32);
2406+
}
2407+
drandom_seed_set= true;
2408+
}
2409+
2410+
/* pg_erand48 produces desired result range [0.0 - 1.0) */
2411+
result=pg_erand48(drandom_seed);
23832412

23842413
PG_RETURN_FLOAT8(result);
23852414
}
@@ -2392,13 +2421,20 @@ Datum
23922421
setseed(PG_FUNCTION_ARGS)
23932422
{
23942423
float8seed=PG_GETARG_FLOAT8(0);
2395-
intiseed;
2424+
uint64iseed;
23962425

2397-
if (seed<-1||seed>1)
2398-
elog(ERROR,"setseed parameter %f out of range [-1,1]",seed);
2399-
2400-
iseed= (int) (seed*MAX_RANDOM_VALUE);
2401-
srandom((unsignedint)iseed);
2426+
if (seed<-1||seed>1||isnan(seed))
2427+
ereport(ERROR,
2428+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2429+
errmsg("setseed parameter %g is out of allowed range [-1,1]",
2430+
seed)));
2431+
2432+
/* Use sign bit + 47 fractional bits to fill drandom_seed[] */
2433+
iseed= (int64) (seed* (float8)UINT64CONST(0x7FFFFFFFFFFF));
2434+
drandom_seed[0]= (unsigned short)iseed;
2435+
drandom_seed[1]= (unsigned short) (iseed >>16);
2436+
drandom_seed[2]= (unsigned short) (iseed >>32);
2437+
drandom_seed_set= true;
24022438

24032439
PG_RETURN_VOID();
24042440
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp