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

Commitc33c423

Browse files
committed
Add security checks to selectivity estimation functions
Some selectivity estimation functions run user-supplied operators overdata obtained from pg_statistic without security checks, which allowsthose operators to leak pg_statistic data without having privileges onthe underlying tables. Fix by checking that one of the following issatisfied: (1) the user has table or column privileges on the tableunderlying the pg_statistic data, or (2) the function implementing theuser-supplied operator is leak-proof. If neither is satisfied, planningwill proceed as if there are no statistics available.At least one of these is satisfied in most cases in practice. The onlysituations that are negatively impacted are user-defined ornot-leak-proof operators on a security-barrier view.Reported-by: Robert Haas <robertmhaas@gmail.com>Author: Peter Eisentraut <peter_e@gmx.net>Author: Tom Lane <tgl@sss.pgh.pa.us>Security:CVE-2017-7484
1 parent3178f46 commitc33c423

File tree

7 files changed

+376
-32
lines changed

7 files changed

+376
-32
lines changed

‎doc/src/sgml/planstats.sgml

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,4 +448,64 @@ rows = (outer_cardinality * inner_cardinality) * selectivity
448448

449449
</sect1>
450450

451+
<sect1 id="planner-stats-security">
452+
<title>Planner Statistics and Security</title>
453+
454+
<para>
455+
Access to the table <structname>pg_statistic</structname> is restricted to
456+
superusers, so that ordinary users cannot learn about the contents of the
457+
tables of other users from it. Some selectivity estimation functions will
458+
use a user-provided operator (either the operator appearing in the query or
459+
a related operator) to analyze the stored statistics. For example, in order
460+
to determine whether a stored most common value is applicable, the
461+
selectivity estimator will have to run the appropriate <literal>=</literal>
462+
operator to compare the constant in the query to the stored value.
463+
Thus the data in <structname>pg_statistic</structname> is potentially
464+
passed to user-defined operators. An appropriately crafted operator can
465+
intentionally leak the passed operands (for example, by logging them
466+
or writing them to a different table), or accidentally leak them by showing
467+
their values in error messages, in either case possibly exposing data from
468+
<structname>pg_statistic</structname> to a user who should not be able to
469+
see it.
470+
</para>
471+
472+
<para>
473+
In order to prevent this, the following applies to all built-in selectivity
474+
estimation functions. When planning a query, in order to be able to use
475+
stored statistics, the current user must either
476+
have <literal>SELECT</literal> privilege on the table or the involved
477+
columns, or the operator used must be <literal>LEAKPROOF</literal> (more
478+
accurately, the function that the operator is based on). If not, then the
479+
selectivity estimator will behave as if no statistics are available, and
480+
the planner will proceed with default or fall-back assumptions.
481+
</para>
482+
483+
<para>
484+
If a user does not have the required privilege on the table or columns,
485+
then in many cases the query will ultimately receive a permission-denied
486+
error, in which case this mechanism is invisible in practice. But if the
487+
user is reading from a security-barrier view, then the planner might wish
488+
to check the statistics of an underlying table that is otherwise
489+
inaccessible to the user. In that case, the operator should be leak-proof
490+
or the statistics will not be used. There is no direct feedback about
491+
that, except that the plan might be suboptimal. If one suspects that this
492+
is the case, one could try running the query as a more privileged user,
493+
to see if a different plan results.
494+
</para>
495+
496+
<para>
497+
This restriction applies only to cases where the planner would need to
498+
execute a user-defined operator on one or more values
499+
from <structname>pg_statistic</structname>. Thus the planner is permitted
500+
to use generic statistical information, such as the fraction of null values
501+
or the number of distinct values in a column, regardless of access
502+
privileges.
503+
</para>
504+
505+
<para>
506+
Selectivity estimation functions contained in third-party extensions that
507+
potentially operate on statistics with user-defined operators should follow
508+
the same security rules. Consult the PostgreSQL source code for guidance.
509+
</para>
510+
</sect1>
451511
</chapter>

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,8 @@ scalararraysel_containment(PlannerInfo *root,
132132
useOr= !useOr;
133133

134134
/* Get array element stats for var, if available */
135-
if (HeapTupleIsValid(vardata.statsTuple))
135+
if (HeapTupleIsValid(vardata.statsTuple)&&
136+
statistic_proc_security_check(&vardata,cmpfunc->fn_oid))
136137
{
137138
Form_pg_statisticstats;
138139
Datum*values;
@@ -363,7 +364,8 @@ calc_arraycontsel(VariableStatData *vardata, Datum constval,
363364
*/
364365
array=DatumGetArrayTypeP(constval);
365366

366-
if (HeapTupleIsValid(vardata->statsTuple))
367+
if (HeapTupleIsValid(vardata->statsTuple)&&
368+
statistic_proc_security_check(vardata,cmpfunc->fn_oid))
367369
{
368370
Form_pg_statisticstats;
369371
Datum*values;

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

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,7 @@ calc_rangesel(TypeCacheEntry *typcache, VariableStatData *vardata,
255255
if (nnumbers!=1)
256256
elog(ERROR,"invalid empty fraction statistic");/* shouldn't happen */
257257
empty_frac=numbers[0];
258+
free_attstatsslot(vardata->atttype,NULL,0,numbers,nnumbers);
258259
}
259260
else
260261
{
@@ -383,6 +384,15 @@ calc_hist_selectivity(TypeCacheEntry *typcache, VariableStatData *vardata,
383384
boolempty;
384385
doublehist_selec;
385386

387+
/* Can't use the histogram with insecure range support functions */
388+
if (!statistic_proc_security_check(vardata,
389+
typcache->rng_cmp_proc_finfo.fn_oid))
390+
return-1;
391+
if (OidIsValid(typcache->rng_subdiff_finfo.fn_oid)&&
392+
!statistic_proc_security_check(vardata,
393+
typcache->rng_subdiff_finfo.fn_oid))
394+
return-1;
395+
386396
/* Try to get histogram of ranges */
387397
if (!(HeapTupleIsValid(vardata->statsTuple)&&
388398
get_attstatsslot(vardata->statsTuple,
@@ -420,11 +430,19 @@ calc_hist_selectivity(TypeCacheEntry *typcache, VariableStatData *vardata,
420430
NULL,
421431
&length_hist_values,&length_nhist,
422432
NULL,NULL)))
433+
{
434+
free_attstatsslot(vardata->atttype,hist_values,nhist,NULL,0);
423435
return-1.0;
436+
}
424437

425438
/* check that it's a histogram, not just a dummy entry */
426439
if (length_nhist<2)
440+
{
441+
free_attstatsslot(vardata->atttype,
442+
length_hist_values,length_nhist,NULL,0);
443+
free_attstatsslot(vardata->atttype,hist_values,nhist,NULL,0);
427444
return-1.0;
445+
}
428446
}
429447

430448
/* Extract the bounds of the constant value. */
@@ -560,6 +578,10 @@ calc_hist_selectivity(TypeCacheEntry *typcache, VariableStatData *vardata,
560578
break;
561579
}
562580

581+
free_attstatsslot(vardata->atttype,
582+
length_hist_values,length_nhist,NULL,0);
583+
free_attstatsslot(vardata->atttype,hist_values,nhist,NULL,0);
584+
563585
returnhist_selec;
564586
}
565587

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp