pgsql: Fix column-privilege leak in error-message paths
Fix column-privilege leak in error-message paths
While building error messages to return to the user,
BuildIndexValueDescription, ExecBuildSlotValueDescription and
ri_ReportViolation would happily include the entire key or entire row in
the result returned to the user, even if the user didn't have access to
view all of the columns being included.
Instead, include only those columns which the user is providing or which
the user has select rights on. If the user does not have any rights
to view the table or any of the columns involved then no detail is
provided and a NULL value is returned from BuildIndexValueDescription
and ExecBuildSlotValueDescription. Note that, for key cases, the user
must have access to all of the columns for the key to be shown; a
partial key will not be returned.
Further, in master only, do not return any data for cases where row
security is enabled on the relation and row security should be applied
for the user. This required a bit of refactoring and moving of things
around related to RLS- note the addition of utils/misc/rls.c.
Back-patch all the way, as column-level privileges are now in all
supported versions.
This has been assigned CVE-2014-8161, but since the issue and the patch
have already been publicized on pgsql-hackers, there's no point in trying
to hide this commit.
Branch
------
master
Details
-------
http://git.postgresql.org/pg/commitdiff/804b6b6db4dcfc590a468e7be390738f9f7755fb
Modified Files
--------------
src/backend/access/index/genam.c | 71 ++++++++++-
src/backend/access/nbtree/nbtinsert.c | 10 +-
src/backend/commands/copy.c | 10 +-
src/backend/commands/createas.c | 4 +-
src/backend/commands/matview.c | 7 ++
src/backend/commands/trigger.c | 6 +
src/backend/executor/execMain.c | 193 +++++++++++++++++++++++------
src/backend/executor/execUtils.c | 12 +-
src/backend/rewrite/rowsecurity.c | 81 +-----------
src/backend/utils/adt/ri_triggers.c | 87 ++++++++++---
src/backend/utils/cache/plancache.c | 2 +-
src/backend/utils/misc/Makefile | 2 +-
src/backend/utils/misc/guc.c | 2 +-
src/backend/utils/misc/rls.c | 114 +++++++++++++++++
src/backend/utils/sort/tuplesort.c | 9 +-
src/include/rewrite/rowsecurity.h | 36 ------
src/include/utils/rls.h | 58 +++++++++
src/test/regress/expected/privileges.out | 31 +++++
src/test/regress/expected/rowsecurity.out | 3 -
src/test/regress/sql/privileges.sql | 25 ++++
20 files changed, 569 insertions(+), 194 deletions(-)
--
Sent via pgsql-committers mailing list (pgsql-committers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-committers
Stephen Frost <sfrost@snowman.net> writes:
Fix column-privilege leak in error-message paths
This patch is at least one brick shy of a load:
regression=# create table t1 (f1 int);
CREATE TABLE
regression=# create unique index on t1 (abs(f1));
CREATE INDEX
regression=# create user joe;
CREATE ROLE
regression=# grant insert on t1 to joe;
GRANT
regression=# \c - joe
You are now connected to database "regression" as user "joe".
regression=> insert into t1 values (1);
INSERT 0 1
regression=> insert into t1 values (1);
ERROR: attribute 0 of relation with OID 45155 does not exist
The cause of that is the logic added to BuildIndexValueDescription, which
ignores the possibility that some of the index columns are expressions
(which will have a zero in indkey[]).
I'm not sure that it's worth trying to drill down and determine exactly
which column(s) are referenced by an expression. I'd be content if we
just decided that any index expression is off-limits to someone without
full SELECT access, which could be achieved with something like
{
AttrNumber attnum = idxrec->indkey.values[keyno];
- aclresult = pg_attribute_aclcheck(indrelid, attnum, GetUserId(),
- ACL_SELECT);
-
- if (aclresult != ACLCHECK_OK)
+ if (attnum == InvalidAttrNumber ||
+ pg_attribute_aclcheck(indrelid, attnum, GetUserId(),
+ ACL_SELECT) != ACLCHECK_OK)
{
/* No access, so clean up and return */
ReleaseSysCache(ht_idx);
(though a comment about it wouldn't be a bad thing either)
regards, tom lane
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers
* Tom Lane (tgl@sss.pgh.pa.us) wrote:
Stephen Frost <sfrost@snowman.net> writes:
Fix column-privilege leak in error-message paths
This patch is at least one brick shy of a load:
regression=# create table t1 (f1 int);
CREATE TABLE
regression=# create unique index on t1 (abs(f1));
CREATE INDEX
regression=# create user joe;
CREATE ROLE
regression=# grant insert on t1 to joe;
GRANT
regression=# \c - joe
You are now connected to database "regression" as user "joe".
regression=> insert into t1 values (1);
INSERT 0 1
regression=> insert into t1 values (1);
ERROR: attribute 0 of relation with OID 45155 does not exist
Urgh.
The cause of that is the logic added to BuildIndexValueDescription, which
ignores the possibility that some of the index columns are expressions
(which will have a zero in indkey[]).
Ah, yes, I didn't expect that, clearly.
I'm not sure that it's worth trying to drill down and determine exactly
which column(s) are referenced by an expression. I'd be content if we
just decided that any index expression is off-limits to someone without
full SELECT access, which could be achieved with something like
Sounds perfectly reasonable to me.
{
AttrNumber attnum = idxrec->indkey.values[keyno];- aclresult = pg_attribute_aclcheck(indrelid, attnum, GetUserId(), - ACL_SELECT); - - if (aclresult != ACLCHECK_OK) + if (attnum == InvalidAttrNumber || + pg_attribute_aclcheck(indrelid, attnum, GetUserId(), + ACL_SELECT) != ACLCHECK_OK) { /* No access, so clean up and return */ ReleaseSysCache(ht_idx);
Yup, that looks good to me.
(though a comment about it wouldn't be a bad thing either)
Agreed.
Will handle shortly.
Thanks!
Stephen
Tom,
* Tom Lane (tgl@sss.pgh.pa.us) wrote:
Stephen Frost <sfrost@snowman.net> writes:
Fix column-privilege leak in error-message paths
[...]
The cause of that is the logic added to BuildIndexValueDescription, which
ignores the possibility that some of the index columns are expressions
(which will have a zero in indkey[]).I'm not sure that it's worth trying to drill down and determine exactly
which column(s) are referenced by an expression. I'd be content if we
just decided that any index expression is off-limits to someone without
full SELECT access, which could be achieved with something like
Commit pushed with this approach.
(though a comment about it wouldn't be a bad thing either)
and a comment added explaining it.
Thanks again for pointing it out and please let me know if you see any
further issues.
Stephen