Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

opt: check privileges after data sources in memo stale check #102375

Closed
DrewKimball opened this issue Apr 26, 2023 · 4 comments · Fixed by #102405
Closed

opt: check privileges after data sources in memo stale check #102375

DrewKimball opened this issue Apr 26, 2023 · 4 comments · Fixed by #102405
Assignees
Labels
A-sql-optimizer SQL logical planning and optimizations. branch-master Failures and bugs on the master branch. branch-release-22.1 Used to mark GA and release blockers, technical advisories, and bugs for 22.1 branch-release-22.2 Used to mark GA and release blockers, technical advisories, and bugs for 22.2 C-bug Code not up to spec/doc, specs & docs deemed correct. Solution expected to change code/behavior. C-technical-advisory Caused a technical advisory release-blocker Indicates a release-blocker. Use with branch-release-2x.x label to denote which branch is blocked. S-1-blocking-adoption T-sql-queries SQL Queries Team

Comments

@DrewKimball
Copy link
Collaborator

DrewKimball commented Apr 26, 2023

Describe the problem

#96045 moved the data sources used for metadata dependency tracking from a slice to a map. Maps in go are traversed in nondeterministic order, and the privileges on a data source are checked immediately after the data source itself is checked for staleness. This means that a table that is referenced only indirectly through a foreign key relation (by ID) can cause the memo stale check to return a privilege error in some cases when the referenced table is checked before the table that references it, and a user with different privileges + search path has run the same SQL statement.

To Reproduce

In an open CRDB session:

CREATE DATABASE test1;
USE test1;
CREATE TABLE ab (a INT PRIMARY KEY, b INT);
INSERT INTO ab VALUES (1, 1);
CREATE TABLE xy (x INT, y INT, FOREIGN KEY (x) REFERENCES ab(a));
CREATE ROLE test1;
GRANT ALL ON xy TO test1;
GRANT ALL ON ab TO test1;
ALTER ROLE test1 WITH LOGIN;

CREATE DATABASE test2;
USE test2;
CREATE TABLE ab (a INT PRIMARY KEY, b INT);
INSERT INTO ab VALUES (1, 1);
CREATE TABLE xy (x INT, y INT, FOREIGN KEY (x) REFERENCES ab(a));
CREATE ROLE test2;
GRANT ALL ON xy TO test2;
GRANT ALL ON ab TO test2;
ALTER ROLE test2 WITH LOGIN;

Run concurrently:

while true; do ./cockroach sql --insecure -u test1 -d test1 -e 'INSERT into xy VALUES(1, 1)' ; done
while true; do ./cockroach sql --insecure -u test2 -d test2 -e 'INSERT into xy VALUES(1, 1)' ; done

Example result:

INSERT 0 1

Time: 8ms

INSERT 0 1

Time: 6ms

ERROR: user test2 does not have SELECT privilege on relation ab
SQLSTATE: 42501
Failed running "sql"
INSERT 0 1

Time: 5ms

INSERT 0 1

Time: 8ms

Expected behavior
Rather than returning an error to the user, the cached memo should simply be invalidated.

Jira issue: CRDB-27415

gz#16801

gz#16795

@DrewKimball DrewKimball added C-bug Code not up to spec/doc, specs & docs deemed correct. Solution expected to change code/behavior. A-sql-optimizer SQL logical planning and optimizations. labels Apr 26, 2023
@DrewKimball DrewKimball self-assigned this Apr 26, 2023
@blathers-crl blathers-crl bot added the T-sql-queries SQL Queries Team label Apr 26, 2023
@chengxiong-ruan
Copy link
Contributor

chengxiong-ruan commented Apr 26, 2023

Nice! I actually tried the same repro last week but wasn't able to get the error for some reason :( maybe just bad luck...

DrewKimball added a commit to DrewKimball/cockroach that referenced this issue Apr 27, 2023
Previously, the `opt.Metadata` staleness check would check the access
privileges for a data source immediately after checking that the data
source still resolves as it originally did. This meant that the privilege
check for one data source could occur before checking staleness of other
data sources. Before cockroachdb#96045 this wasn't a problem, since these checks
would happen in the order in which the data sources were resolved. But
after cockroachdb#96045, the data sources were stored in a map instead of a slice,
which made the order in which the checks are performed nondeterministic.

This change in behavior can cause queries to return insufficient privilege
errors even when the current user has access privileges on all data sources
referenced by the query. This is because the query may *implicitly*
reference a table by ID if there is a foreign key relation from an explicitly
referenced data source. If the database is changed, this ID reference will
still resolve the same, but if the user is changed to one without privileges
on that table, the staleness check will result in an error. This wasn't a
problem before because the referencing table would always be checked first,
causing the staleness check to finish without an error.

This patch fixes the bug by moving the privilege checks until after all
data source resolution checks have succeeded.

Fixes cockroachdb#102375

Release note (bug fix): Fixed a bug introduced in versions 22.1.19,
22.2.8, and pre-release versions of 23.1 that could cause queries to
return spurious insufficient privilege errors. For the bug to occur,
two databases would need to have duplicate tables each with a foreign key
reference to another table. The error would then occur if the same SQL
string was executed against both databases concurrently by users that have
privileges over only one of the tables.
DrewKimball added a commit to DrewKimball/cockroach that referenced this issue Apr 27, 2023
Previously, the `opt.Metadata` staleness check would check the access
privileges for a data source immediately after checking that the data
source still resolves as it originally did. This meant that the privilege
check for one data source could occur before checking staleness of other
data sources. Before cockroachdb#96045 this wasn't a problem, since these checks
would happen in the order in which the data sources were resolved. But
after cockroachdb#96045, the data sources were stored in a map instead of a slice,
which made the order in which the checks are performed nondeterministic.

This change in behavior can cause queries to return insufficient privilege
errors even when the current user has access privileges on all data sources
referenced by the query. This is because the query may *implicitly*
reference a table by ID if there is a foreign key relation from an explicitly
referenced data source. If the database is changed, this ID reference will
still resolve the same, but if the user is changed to one without privileges
on that table, the staleness check will result in an error. This wasn't a
problem before because the referencing table would always be checked first,
causing the staleness check to finish without an error.

This patch fixes the bug by moving the privilege checks until after all
data source resolution checks have succeeded.

Fixes cockroachdb#102375

Release note (bug fix): Fixed a bug introduced in versions 22.1.19,
22.2.8, and pre-release versions of 23.1 that could cause queries to
return spurious insufficient privilege errors. For the bug to occur,
two databases would need to have duplicate tables each with a foreign key
reference to another table. The error would then occur if the same SQL
string was executed against both databases concurrently by users that have
privileges over only one of the tables.
@rytaft rytaft added release-blocker Indicates a release-blocker. Use with branch-release-2x.x label to denote which branch is blocked. branch-release-22.1 Used to mark GA and release blockers, technical advisories, and bugs for 22.1 branch-release-22.2 Used to mark GA and release blockers, technical advisories, and bugs for 22.2 branch-release-23.1 Used to mark GA and release blockers, technical advisories, and bugs for 23.1 branch-release-23.1.0 labels Apr 27, 2023
craig bot pushed a commit that referenced this issue Apr 28, 2023
102405: opt: check privileges after data sources in memo staleness check r=DrewKimball a=DrewKimball

Previously, the `opt.Metadata` staleness check would check the access privileges for a data source immediately after checking that the data source still resolves as it originally did. This meant that the privilege check for one data source could occur before checking staleness of other data sources. Before #96045 this wasn't a problem, since these checks would happen in the order in which the data sources were resolved. But after #96045, the data sources were stored in a map instead of a slice, which made the order in which the checks are performed nondeterministic.

This change in behavior can cause queries to return insufficient privilege errors even when the current user has access privileges on all data sources referenced by the query. This is because the query may *implicitly* reference a table by ID if there is a foreign key relation from an explicitly referenced data source. If the database is changed, this ID reference will still resolve the same, but if the user is changed to one without privileges on that table, the staleness check will result in an error. This wasn't a problem before because the referencing table would always be checked first, causing the staleness check to finish without an error.

This patch fixes the bug by moving the privilege checks until after all data source resolution checks have succeeded.

Fixes #102375

Release note (bug fix): Fixed a bug introduced in versions 22.1.19, 22.2.8, and pre-release versions of 23.1 that could cause queries to return spurious insufficient privilege errors. For the bug to occur, two databases would need to have duplicate tables each with a foreign key reference to another table. The error would then occur if the same SQL string was executed against both databases concurrently by users that have privileges over only one of the tables.

Co-authored-by: Drew Kimball <drewk@cockroachlabs.com>
@craig craig bot closed this as completed in 9381f84 Apr 28, 2023
blathers-crl bot pushed a commit that referenced this issue Apr 28, 2023
Previously, the `opt.Metadata` staleness check would check the access
privileges for a data source immediately after checking that the data
source still resolves as it originally did. This meant that the privilege
check for one data source could occur before checking staleness of other
data sources. Before #96045 this wasn't a problem, since these checks
would happen in the order in which the data sources were resolved. But
after #96045, the data sources were stored in a map instead of a slice,
which made the order in which the checks are performed nondeterministic.

This change in behavior can cause queries to return insufficient privilege
errors even when the current user has access privileges on all data sources
referenced by the query. This is because the query may *implicitly*
reference a table by ID if there is a foreign key relation from an explicitly
referenced data source. If the database is changed, this ID reference will
still resolve the same, but if the user is changed to one without privileges
on that table, the staleness check will result in an error. This wasn't a
problem before because the referencing table would always be checked first,
causing the staleness check to finish without an error.

This patch fixes the bug by moving the privilege checks until after all
data source resolution checks have succeeded.

Fixes #102375

Release note (bug fix): Fixed a bug introduced in versions 22.1.19,
22.2.8, and pre-release versions of 23.1 that could cause queries to
return spurious insufficient privilege errors. For the bug to occur,
two databases would need to have duplicate tables each with a foreign key
reference to another table. The error would then occur if the same SQL
string was executed against both databases concurrently by users that have
privileges over only one of the tables.
@rytaft rytaft added GA-blocker branch-master Failures and bugs on the master branch. labels Apr 28, 2023
DrewKimball added a commit to DrewKimball/cockroach that referenced this issue Apr 28, 2023
Previously, the `opt.Metadata` staleness check would check the access
privileges for a data source immediately after checking that the data
source still resolves as it originally did. This meant that the privilege
check for one data source could occur before checking staleness of other
data sources. Before cockroachdb#96045 this wasn't a problem, since these checks
would happen in the order in which the data sources were resolved. But
after cockroachdb#96045, the data sources were stored in a map instead of a slice,
which made the order in which the checks are performed nondeterministic.

This change in behavior can cause queries to return insufficient privilege
errors even when the current user has access privileges on all data sources
referenced by the query. This is because the query may *implicitly*
reference a table by ID if there is a foreign key relation from an explicitly
referenced data source. If the database is changed, this ID reference will
still resolve the same, but if the user is changed to one without privileges
on that table, the staleness check will result in an error. This wasn't a
problem before because the referencing table would always be checked first,
causing the staleness check to finish without an error.

This patch fixes the bug by moving the privilege checks until after all
data source resolution checks have succeeded.

Fixes cockroachdb#102375

Release note (bug fix): Fixed a bug introduced in versions 22.1.19,
22.2.8, and pre-release versions of 23.1 that could cause queries to
return spurious insufficient privilege errors. For the bug to occur,
two databases would need to have duplicate tables each with a foreign key
reference to another table. The error would then occur if the same SQL
string was executed against both databases concurrently by users that have
privileges over only one of the tables.
DrewKimball added a commit to DrewKimball/cockroach that referenced this issue Apr 28, 2023
Previously, the `opt.Metadata` staleness check would check the access
privileges for a data source immediately after checking that the data
source still resolves as it originally did. This meant that the privilege
check for one data source could occur before checking staleness of other
data sources. Before cockroachdb#96045 this wasn't a problem, since these checks
would happen in the order in which the data sources were resolved. But
after cockroachdb#96045, the data sources were stored in a map instead of a slice,
which made the order in which the checks are performed nondeterministic.

This change in behavior can cause queries to return insufficient privilege
errors even when the current user has access privileges on all data sources
referenced by the query. This is because the query may *implicitly*
reference a table by ID if there is a foreign key relation from an explicitly
referenced data source. If the database is changed, this ID reference will
still resolve the same, but if the user is changed to one without privileges
on that table, the staleness check will result in an error. This wasn't a
problem before because the referencing table would always be checked first,
causing the staleness check to finish without an error.

This patch fixes the bug by moving the privilege checks until after all
data source resolution checks have succeeded.

Fixes cockroachdb#102375

Release note (bug fix): Fixed a bug introduced in versions 22.1.19,
22.2.8, and pre-release versions of 23.1 that could cause queries to
return spurious insufficient privilege errors. For the bug to occur,
two databases would need to have duplicate tables each with a foreign key
reference to another table. The error would then occur if the same SQL
string was executed against both databases concurrently by users that have
privileges over only one of the tables.
DrewKimball added a commit to DrewKimball/cockroach that referenced this issue Apr 28, 2023
Previously, the `opt.Metadata` staleness check would check the access
privileges for a data source immediately after checking that the data
source still resolves as it originally did. This meant that the privilege
check for one data source could occur before checking staleness of other
data sources. Before cockroachdb#96045 this wasn't a problem, since these checks
would happen in the order in which the data sources were resolved. But
after cockroachdb#96045, the data sources were stored in a map instead of a slice,
which made the order in which the checks are performed nondeterministic.

This change in behavior can cause queries to return insufficient privilege
errors even when the current user has access privileges on all data sources
referenced by the query. This is because the query may *implicitly*
reference a table by ID if there is a foreign key relation from an explicitly
referenced data source. If the database is changed, this ID reference will
still resolve the same, but if the user is changed to one without privileges
on that table, the staleness check will result in an error. This wasn't a
problem before because the referencing table would always be checked first,
causing the staleness check to finish without an error.

This patch fixes the bug by moving the privilege checks until after all
data source resolution checks have succeeded.

Fixes cockroachdb#102375

Release note (bug fix): Fixed a bug introduced in versions 22.1.19,
22.2.8, and pre-release versions of 23.1 that could cause queries to
return spurious insufficient privilege errors. For the bug to occur,
two databases would need to have duplicate tables each with a foreign key
reference to another table. The error would then occur if the same SQL
string was executed against both databases concurrently by users that have
privileges over only one of the tables.
@joshimhoff
Copy link
Collaborator

Will the bug fix be in v22.2.9?

@chengxiong-ruan
Copy link
Contributor

release-22.2: opt: check privileges after data sources in memo staleness check #102652

yes, it will, given that the backport was merged on 04/29 and v22.2.9 and looks like there're still other v22.2.9 release blockers.

@joshimhoff
Copy link
Collaborator

Thanks!

cameronnunez pushed a commit to cameronnunez/cockroach that referenced this issue May 2, 2023
Previously, the `opt.Metadata` staleness check would check the access
privileges for a data source immediately after checking that the data
source still resolves as it originally did. This meant that the privilege
check for one data source could occur before checking staleness of other
data sources. Before cockroachdb#96045 this wasn't a problem, since these checks
would happen in the order in which the data sources were resolved. But
after cockroachdb#96045, the data sources were stored in a map instead of a slice,
which made the order in which the checks are performed nondeterministic.

This change in behavior can cause queries to return insufficient privilege
errors even when the current user has access privileges on all data sources
referenced by the query. This is because the query may *implicitly*
reference a table by ID if there is a foreign key relation from an explicitly
referenced data source. If the database is changed, this ID reference will
still resolve the same, but if the user is changed to one without privileges
on that table, the staleness check will result in an error. This wasn't a
problem before because the referencing table would always be checked first,
causing the staleness check to finish without an error.

This patch fixes the bug by moving the privilege checks until after all
data source resolution checks have succeeded.

Fixes cockroachdb#102375

Release note (bug fix): Fixed a bug introduced in versions 22.1.19,
22.2.8, and pre-release versions of 23.1 that could cause queries to
return spurious insufficient privilege errors. For the bug to occur,
two databases would need to have duplicate tables each with a foreign key
reference to another table. The error would then occur if the same SQL
string was executed against both databases concurrently by users that have
privileges over only one of the tables.
@mgartner mgartner moved this to Done in SQL Queries Jul 24, 2023
@rytaft rytaft added C-technical-advisory Caused a technical advisory and removed branch-release-23.1 Used to mark GA and release blockers, technical advisories, and bugs for 23.1 GA-blocker labels Dec 6, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-sql-optimizer SQL logical planning and optimizations. branch-master Failures and bugs on the master branch. branch-release-22.1 Used to mark GA and release blockers, technical advisories, and bugs for 22.1 branch-release-22.2 Used to mark GA and release blockers, technical advisories, and bugs for 22.2 C-bug Code not up to spec/doc, specs & docs deemed correct. Solution expected to change code/behavior. C-technical-advisory Caused a technical advisory release-blocker Indicates a release-blocker. Use with branch-release-2x.x label to denote which branch is blocked. S-1-blocking-adoption T-sql-queries SQL Queries Team
Projects
Archived in project
Development

Successfully merging a pull request may close this issue.

4 participants