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

Commitd49f84b

Browse files
committed
Fix column-privilege leak in error-message paths
While building error messages to return to the user,BuildIndexValueDescription, ExecBuildSlotValueDescription andri_ReportViolation would happily include the entire key or entire row inthe result returned to the user, even if the user didn't have access toview all of the columns being included.Instead, include only those columns which the user is providing or whichthe user has select rights on. If the user does not have any rightsto view the table or any of the columns involved then no detail isprovided and a NULL value is returned from BuildIndexValueDescriptionand ExecBuildSlotValueDescription. Note that, for key cases, the usermust have access to all of the columns for the key to be shown; apartial key will not be returned.Back-patch all the way, as column-level privileges are now in allsupported versions.This has been assignedCVE-2014-8161, but since the issue and the patchhave already been publicized on pgsql-hackers, there's no point in tryingto hide this commit.
1 parent350f1e7 commitd49f84b

File tree

10 files changed

+344
-70
lines changed

10 files changed

+344
-70
lines changed

‎src/backend/access/index/genam.c

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,11 @@
2424
#include"catalog/index.h"
2525
#include"miscadmin.h"
2626
#include"storage/bufmgr.h"
27+
#include"utils/acl.h"
2728
#include"utils/builtins.h"
2829
#include"utils/lsyscache.h"
2930
#include"utils/rel.h"
31+
#include"utils/syscache.h"
3032
#include"utils/tqual.h"
3133

3234

@@ -152,6 +154,11 @@ IndexScanEnd(IndexScanDesc scan)
152154
* form "(key_name, ...)=(key_value, ...)". This is currently used
153155
* for building unique-constraint and exclusion-constraint error messages.
154156
*
157+
* Note that if the user does not have permissions to view all of the
158+
* columns involved then a NULL is returned. Returning a partial key seems
159+
* unlikely to be useful and we have no way to know which of the columns the
160+
* user provided (unlike in ExecBuildSlotValueDescription).
161+
*
155162
* The passed-in values/nulls arrays are the "raw" input to the index AM,
156163
* e.g. results of FormIndexDatum --- this is not necessarily what is stored
157164
* in the index, but it's what the user perceives to be stored.
@@ -161,13 +168,62 @@ BuildIndexValueDescription(Relation indexRelation,
161168
Datum*values,bool*isnull)
162169
{
163170
StringInfoDatabuf;
171+
Form_pg_indexidxrec;
172+
HeapTupleht_idx;
164173
intnatts=indexRelation->rd_rel->relnatts;
165174
inti;
175+
intkeyno;
176+
Oidindexrelid=RelationGetRelid(indexRelation);
177+
Oidindrelid;
178+
AclResultaclresult;
179+
180+
/*
181+
* Check permissions- if the user does not have access to view all of the
182+
* key columns then return NULL to avoid leaking data.
183+
*
184+
* First we need to check table-level SELECT access and then, if
185+
* there is no access there, check column-level permissions.
186+
*/
187+
188+
/*
189+
* Fetch the pg_index tuple by the Oid of the index
190+
*/
191+
ht_idx=SearchSysCache1(INDEXRELID,ObjectIdGetDatum(indexrelid));
192+
if (!HeapTupleIsValid(ht_idx))
193+
elog(ERROR,"cache lookup failed for index %u",indexrelid);
194+
idxrec= (Form_pg_index)GETSTRUCT(ht_idx);
195+
196+
indrelid=idxrec->indrelid;
197+
Assert(indexrelid==idxrec->indexrelid);
198+
199+
/* Table-level SELECT is enough, if the user has it */
200+
aclresult=pg_class_aclcheck(indrelid,GetUserId(),ACL_SELECT);
201+
if (aclresult!=ACLCHECK_OK)
202+
{
203+
/*
204+
* No table-level access, so step through the columns in the
205+
* index and make sure the user has SELECT rights on all of them.
206+
*/
207+
for (keyno=0;keyno<idxrec->indnatts;keyno++)
208+
{
209+
AttrNumberattnum=idxrec->indkey.values[keyno];
210+
211+
aclresult=pg_attribute_aclcheck(indrelid,attnum,GetUserId(),
212+
ACL_SELECT);
213+
214+
if (aclresult!=ACLCHECK_OK)
215+
{
216+
/* No access, so clean up and return */
217+
ReleaseSysCache(ht_idx);
218+
returnNULL;
219+
}
220+
}
221+
}
222+
ReleaseSysCache(ht_idx);
166223

167224
initStringInfo(&buf);
168225
appendStringInfo(&buf,"(%s)=(",
169-
pg_get_indexdef_columns(RelationGetRelid(indexRelation),
170-
true));
226+
pg_get_indexdef_columns(indexrelid, true));
171227

172228
for (i=0;i<natts;i++)
173229
{

‎src/backend/access/nbtree/nbtinsert.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -384,16 +384,20 @@ _bt_check_unique(Relation rel, IndexTuple itup, Relation heapRel,
384384
{
385385
Datumvalues[INDEX_MAX_KEYS];
386386
boolisnull[INDEX_MAX_KEYS];
387+
char*key_desc;
387388

388389
index_deform_tuple(itup,RelationGetDescr(rel),
389390
values,isnull);
391+
392+
key_desc=BuildIndexValueDescription(rel,values,
393+
isnull);
394+
390395
ereport(ERROR,
391396
(errcode(ERRCODE_UNIQUE_VIOLATION),
392397
errmsg("duplicate key value violates unique constraint \"%s\"",
393398
RelationGetRelationName(rel)),
394-
errdetail("Key %s already exists.",
395-
BuildIndexValueDescription(rel,
396-
values,isnull))));
399+
key_desc ?errdetail("Key %s already exists.",
400+
key_desc) :0));
397401
}
398402
}
399403
elseif (all_dead)

‎src/backend/commands/copy.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ typedef struct CopyStateData
151151
int*defmap;/* array of default att numbers */
152152
ExprState**defexprs;/* array of default att expressions */
153153
boolvolatile_defexprs;/* is any of defexprs volatile? */
154+
List*range_table;
154155

155156
/*
156157
* These variables are used to reduce overhead in textual COPY FROM.
@@ -747,6 +748,7 @@ DoCopy(const CopyStmt *stmt, const char *queryString)
747748
boolpipe= (stmt->filename==NULL);
748749
Relationrel;
749750
uint64processed;
751+
RangeTblEntry*rte;
750752

751753
/* Disallow file COPY except to superusers. */
752754
if (!pipe&& !superuser())
@@ -760,7 +762,6 @@ DoCopy(const CopyStmt *stmt, const char *queryString)
760762
{
761763
TupleDesctupDesc;
762764
AclModerequired_access= (is_from ?ACL_INSERT :ACL_SELECT);
763-
RangeTblEntry*rte;
764765
List*attnums;
765766
ListCell*cur;
766767

@@ -807,13 +808,15 @@ DoCopy(const CopyStmt *stmt, const char *queryString)
807808

808809
cstate=BeginCopyFrom(rel,stmt->filename,
809810
stmt->attlist,stmt->options);
811+
cstate->range_table=list_make1(rte);
810812
processed=CopyFrom(cstate);/* copy from file to database */
811813
EndCopyFrom(cstate);
812814
}
813815
else
814816
{
815817
cstate=BeginCopyTo(rel,stmt->query,queryString,stmt->filename,
816818
stmt->attlist,stmt->options);
819+
cstate->range_table=list_make1(rte);
817820
processed=DoCopyTo(cstate);/* copy from database to file */
818821
EndCopyTo(cstate);
819822
}
@@ -1957,6 +1960,7 @@ CopyFrom(CopyState cstate)
19571960
estate->es_result_relations=resultRelInfo;
19581961
estate->es_num_result_relations=1;
19591962
estate->es_result_relation_info=resultRelInfo;
1963+
estate->es_range_table=cstate->range_table;
19601964

19611965
/* Set up a tuple slot too */
19621966
myslot=ExecInitExtraTupleSlot(estate);

‎src/backend/commands/trigger.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,12 @@ intSessionReplicationRole = SESSION_REPLICATION_ROLE_ORIGIN;
6363
/* How many levels deep into trigger execution are we? */
6464
staticintMyTriggerDepth=0;
6565

66+
/*
67+
* Note that this macro also exists in executor/execMain.c. There does not
68+
* appear to be any good header to put it into, given the structures that
69+
* it uses, so we let them be duplicated. Be sure to update both if one needs
70+
* to be changed, however.
71+
*/
6672
#defineGetModifiedColumns(relinfo,estate) \
6773
(rt_fetch((relinfo)->ri_RangeTableIndex, (estate)->es_range_table)->modifiedCols)
6874

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp