Skip to content

[fix](fe) Fix row policy bypass when leading hint rebuilds the join (#67776) - #68207

Draft
starocean999 wants to merge 1 commit into
apache:branch-4.2from
starocean999:b42_67776
Draft

starocean999 wants to merge 1 commit into
apache:branch-4.2from
starocean999:b42_67776

Conversation

@starocean999

Copy link
Copy Markdown
Contributor

pick #67776

…pache#67776)

Problem Summary:
Reproduction:
A normal user has a restrictive row policy `USING(k = 1)` on table `t1`.
Reading the table directly and joining it without a hint only returns
the
allowed row, but adding a leading hint leaks the protected row:

    -- returns only k = 1
SELECT t1.k, t1.v, t2.v FROM t1 JOIN t2 ON t1.k = t2.k ORDER BY t1.k;

    -- returns k = 1 and k = 2, the row policy is bypassed
    SELECT /*+ leading(t1 t2) */ t1.k, t1.v, t2.v
    FROM t1 JOIN t2 ON t1.k = t2.k ORDER BY t1.k;

`EXPLAIN VERBOSE` shows that the scan of `t1` in the hinted plan has no
`k = 1` predicate, while the un-hinted plan has one. It is an access
control
issue: the hint only changes the join order, so it must never change
which rows
a user is allowed to read.

Root cause:
`CheckPolicy` materializes a row policy as a `LogicalFilter` on the
relation
(and a data mask as a `LogicalProject` above it). The analysis rule
`CollectJoinConstraint` only remembered the scan itself, or the
`Project(OlapScan)` directly above it, in
`LeadingHint.relationIdToScanMap`.
`LeadingHint.generateLeadingJoinPlan` rebuilds the whole join from the
plans
remembered in that map, so every node that was not remembered - the row
policy
filter, the data mask project, a binder filter, and the pre-aggregation
of a
random distribution aggregate table - was silently dropped when the join
was
rebuilt.

Fix:
`CollectJoinConstraint` now remembers the whole plan below each side of
a join
instead of only the relation or the project above the relation
(`collectLeafPlan()`), so rebuilding the join reuses exactly the
original
leaves. `LeadingHint.getBitmap()` is generalized accordingly, so that a
leaf
which is built on one relation (e.g. the `LogicalAggregate` generated
for a
random distribution aggregate table) is still resolved to its table
bitmap.

Before the fix, the hinted query returned `(1, 10, 100)` and `(2, 20,
200)`;
after the fix it returns only `(1, 10, 100)`, the same as the un-hinted
query.
As a side effect, `SELECT /*+ leading(...) */ ...` on a random
distribution
aggregate table no longer loses its pre-aggregation, which previously
returned
un-merged rows or failed the `CheckAfterRewrite` slot validation.
@hello-stephen

Copy link
Copy Markdown
Contributor

Thank you for your contribution to Apache Doris.
Don't know what should be done next? See How to process your PR.

Please clearly describe your PR:

  1. What problem was fixed (it's best to include specific error reporting information). How it was fixed.
  2. Which behaviors were modified. What was the previous behavior, what is it now, why was it modified, and what possible impacts might there be.
  3. What features were added. Why was this function added?
  4. Which code was refactored and why was this part of the code refactored?
  5. Which functions were optimized and what is the difference before and after the optimization?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants