Skip to content

fix(rbac): access control[manual-only] #35213

Merged
guanshengliang merged 25 commits intomainfrom
fix/TD-6837020675-main
Apr 27, 2026
Merged

fix(rbac): access control[manual-only] #35213
guanshengliang merged 25 commits intomainfrom
fix/TD-6837020675-main

Conversation

@kailixu
Copy link
Copy Markdown
Contributor

@kailixu kailixu commented Apr 22, 2026

Description

Issue(s)

  • Close/close/Fix/fix/Resolve/resolve: Issue Link

Checklist

Please check the items in the checklist if applicable.

  • Is the user manual updated?
  • Are the test cases passed and automated?
  • Is there no significant decrease in test coverage?

Copilot AI review requested due to automatic review settings April 22, 2026 11:05
@kailixu kailixu requested review from a team, dapan1121 and guanshengliang as code owners April 22, 2026 11:05
@kailixu kailixu changed the title fix(rbac): access control fix(rbac): access control[manual-only] Apr 22, 2026
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the database privilege check logic to distinguish between rollup and trim operations and enhances the test suite with RSMA creation and rollup privilege tests. However, a large block of existing test cases was inadvertently commented out, which should be restored, and a leftover comment string needs to be removed for code cleanliness.

Comment thread test/cases/25-Privileges/test_priv_control.py Outdated
Comment thread test/cases/25-Privileges/test_priv_control.py
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adjusts RBAC enforcement for ROLLUP DATABASE by mapping the privilege check to a dedicated rollup operation (instead of treating it like TRIM DATABASE), and updates the privilege test suite to set up RSMA prerequisites for rollup scenarios.

Changes:

  • Update mndProcessTrimDbReq() to check MND_OPER_ROLLUP_DB when trimReq.optrType == TSDB_OPTR_ROLLUP.
  • Extend the rollup privilege test to create a stable + RSMA before running ROLLUP DATABASE.
  • Comment out large portions of the privilege control test suite (table/row/column/RBAC/system/etc. sections).

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
test/cases/25-Privileges/test_priv_control.py Adds RSMA creation for rollup testing, but also disables many test sections by commenting them out.
source/dnode/mnode/impl/src/mndDb.c Routes DB privilege checks to ROLLUP vs TRIM based on STrimDbReq.optrType.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread test/cases/25-Privileges/test_priv_control.py Outdated
# Test: user can rollup database with privilege
self.login(user, pwd)
'''BUG20
'''BUG20 '''
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'''BUG20 ''' is a standalone triple-quoted string statement. If this is meant to be a comment/marker, prefer a normal # comment (or a tracked TODO with issue ID) to avoid leaving an unused runtime string literal in the test body.

Suggested change
'''BUG20 '''
# BUG20

Copilot uses AI. Check for mistakes.
Comment thread test/cases/25-Privileges/test_priv_control.py
Comment thread source/dnode/mnode/impl/src/mndDb.c
Copilot AI review requested due to automatic review settings April 22, 2026 12:53
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread test/cases/25-Privileges/test_priv_control.py Outdated
Comment thread test/cases/25-Privileges/test_priv_control.py
Comment thread test/cases/25-Privileges/test_priv_control.py
Copilot AI review requested due to automatic review settings April 23, 2026 10:06
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copilot AI review requested due to automatic review settings April 24, 2026 05:10
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.

Comments suppressed due to low confidence (1)

source/libs/executor/src/sysscanoperator.c:5248

  • doDestroySysTableScanInfo unconditionally calls tsem_destroy(&pInfo->ready), but createSysTableScanOperatorInfo only calls tsem_init(&pInfo->ready, ...) in the non-local-scan path. For the local-scan cases (TABLES, TAGS, FILESETS), ready is never initialized, so destroying it can fail (and is undefined depending on platform semaphore implementation).

Consider initializing ready for all paths, or guard tsem_destroy behind a flag / pInfo->self > 0 / pInfo->readHandle.mnd != NULL as appropriate.

  SSysTableScanInfo* pInfo = (SSysTableScanInfo*)param;
  int32_t            code = tsem_destroy(&pInfo->ready);
  if (code != TSDB_CODE_SUCCESS) {
    qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
  }
  blockDataDestroy(pInfo->pRes);

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread source/libs/executor/src/sysscanoperator.c
Comment on lines +4980 to 4987
// Block this worker thread until the response arrives. qSemWait notifies
// the worker pool and waits, then re-acquires on wake-up.
code = qSemWait((qTaskInfo_t)pTaskInfo, &pInfo->ready);
if (code != TSDB_CODE_SUCCESS) {
freeSysTableLoadCtx(pLoadCtx);
qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
qError("%s tsem_wait failed at line %d since %s", __func__, __LINE__, tstrerror(code));
pTaskInfo->code = code;
T_LONG_JMP(pTaskInfo->env, code);
}
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sysTableScanFromMNode previously used tsem_timewait(..., VTB_REF_RPC_TIMEOUT_MS) but now blocks with qSemWait(..., &pInfo->ready) which has no timeout (it wraps tsem_wait). If the RPC callback is never invoked (transport error, dropped response, cancellation edge case), this worker thread can block indefinitely.

If a timeout is still required, consider adding a timed wait variant (e.g., qSemTimeWait) or restoring tsem_timewait and handling TSDB_CODE_TIMEOUT_ERROR explicitly.

Copilot uses AI. Check for mistakes.
Comment on lines 4232 to 4308
# Database privilege tests
print("[Database Privileges]")
self.create_snode()
self.create_qnode()
self.do_create_database_privilege()
self.do_alter_database_privilege()
self.do_drop_database_privilege()
self.do_use_database_privilege()
self.do_show_databases_privilege()
self.do_show_create_database_privilege()
self.do_flush_database_privilege()
self.do_compact_database_privilege()
self.do_trim_database_privilege()
self.do_rollup_database_privilege()
self.do_scan_database_privilege()
self.do_ssmigrate_database_privilege()

# Table privilege tests
print("")
print("[Table Privileges]")
self.do_create_table_privilege()
self.do_drop_table_privilege()
self.do_alter_table_privilege()
self.do_select_privilege()
self.do_insert_privilege()
self.do_delete_privilege()
self.do_select_column_privilege_comprehensive()
self.do_insert_column_privilege_comprehensive()
self.do_show_create_table_privilege()

# Column and row privilege tests
print("")
print("[Column and Row Privileges]")
self.do_row_privilege_with_tag_condition()
self.do_row_privilege_complex_conditions()
self.do_row_privilege_time_range()
self.do_row_privilege_mixed_conditions()
self.do_column_privilege()
self.do_column_mask_privilege()
self.do_column_row_combined_privilege()
self.do_column_privilege_update_priority()
self.do_privilege_update_time_priority()

# RBAC tests
print("")
print("[Role-Based Access Control]")
self.do_role_privilege()
self.do_role_creation_and_grant()
#self.do_role_lock_unlock() #can cause core BUG21
self.do_system_roles()
self.do_audit_database_privileges()

# System privilege tests
print("")
print("[System Privileges]")
self.do_user_management_privileges()
self.do_token_management_privileges()
self.do_totp_management_privileges()
self.do_password_management_privileges()
self.do_node_management_privileges()
self.do_mount_management_privileges()
# self.do_create_database_privilege()
# self.do_alter_database_privilege()
# self.do_drop_database_privilege()
# self.do_use_database_privilege()
# self.do_show_databases_privilege()
# self.do_show_create_database_privilege()
# self.do_flush_database_privilege()
# self.do_compact_database_privilege()
# self.do_trim_database_privilege()
# self.do_rollup_database_privilege()
# self.do_scan_database_privilege()
# self.do_ssmigrate_database_privilege()

# # # Table privilege tests
# print("")
# print("[Table Privileges]")
# self.do_create_table_privilege()
# self.do_drop_table_privilege()
# self.do_alter_table_privilege()
# self.do_select_privilege()
# self.do_insert_privilege()
# self.do_delete_privilege()
# self.do_select_column_privilege_comprehensive()
# self.do_insert_column_privilege_comprehensive()
# self.do_show_create_table_privilege()

# # # Column and row privilege tests
# print("")
# print("[Column and Row Privileges]")
# self.do_row_privilege_with_tag_condition()
# self.do_row_privilege_complex_conditions()
# self.do_row_privilege_time_range()
# self.do_row_privilege_mixed_conditions()
# self.do_column_privilege()
# self.do_column_mask_privilege()
# self.do_column_row_combined_privilege()
# self.do_column_privilege_update_priority()
# self.do_privilege_update_time_priority()

# # # RBAC tests
# print("")
# print("[Role-Based Access Control]")
# self.do_role_privilege()
# self.do_role_creation_and_grant()
# #self.do_role_lock_unlock() #can cause core BUG21
# self.do_system_roles()
# self.do_audit_database_privileges()

# # # System privilege tests
# print("")
# print("[System Privileges]")
# self.do_user_management_privileges()
# self.do_token_management_privileges()
# self.do_totp_management_privileges()
# self.do_password_management_privileges()
# self.do_node_management_privileges()
# self.do_mount_management_privileges()
self.do_system_variable_privileges()
self.do_information_schema_privileges()
self.do_system_monitoring_privileges()
self.do_show_grants_cluster_apps_privileges()
self.do_privilege_delegation()

# Function/index/tsrma/rsma privilege tests
print("")
print("[Function and Index Privileges]")
self.do_create_function_privilege()
self.do_create_index_privilege()
if platform.system().lower() != 'windows':
# windows does not support tsma
self.do_create_tsma_privilege()
self.do_create_rsma_privilege()
# self.do_information_schema_privileges()
# self.do_system_monitoring_privileges()
# self.do_show_grants_cluster_apps_privileges()
# self.do_privilege_delegation()

# # # Function/index/tsrma/rsma privilege tests
# print("")
# print("[Function and Index Privileges]")
# self.do_create_function_privilege()
# self.do_create_index_privilege()
# if platform.system().lower() != 'windows':
# # windows does not support tsma
# self.do_create_tsma_privilege()
# self.do_create_rsma_privilege()

Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

test_priv_control() now comments out the majority of the privilege test suite (database/table/RBAC/system/etc.) and effectively only runs do_system_variable_privileges(). This significantly reduces automated coverage for RBAC/privilege behavior and makes regressions much harder to catch.

If the intent is "manual-only", consider gating the full suite behind an explicit flag (env var / CLI option) or marking individual tests as skipped, rather than commenting out the calls in the main test entrypoint.

Copilot uses AI. Check for mistakes.
Comment on lines 2721 to 2724
self.exec_sql_failed("SHOW QUERIES", TSDB_CODE_PAR_PERMISSION_DENIED)
'''BUG17
'''BUG17'''
self.exec_sql_failed("SHOW CONNECTIONS", TSDB_CODE_PAR_PERMISSION_DENIED)
'''

Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do_system_monitoring_privileges still has inconsistent handling for the SHOW CONNECTIONS negative check: the earlier "without privilege" assertion is commented out via a triple-quoted block, but after revoke the assertion is executed (the '''BUG17''' line is now just a no-op string). This makes the test coverage uneven and the intent unclear.

Consider removing the triple-quote blocks entirely and using a normal comment/skip mechanism so SHOW CONNECTIONS is either tested in both places or explicitly skipped in both.

Copilot uses AI. Check for mistakes.
Copilot AI review requested due to automatic review settings April 25, 2026 07:38
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 5 comments.

Comments suppressed due to low confidence (1)

source/libs/executor/src/sysscanoperator.c:5247

  • doDestroySysTableScanInfo() always calls tsem_destroy(&pInfo->ready), but pInfo->ready is only initialized via tsem_init() in the remote/MNode path. For local-scan operators (e.g. TABLES/TAGS/FILESETS), this may destroy an uninitialized semaphore and can crash or return undefined errors. Track initialization (e.g. a readyInited flag) and only destroy when initialized, or initialize ready for all code paths.
  SSysTableScanInfo* pInfo = (SSysTableScanInfo*)param;
  int32_t            code = tsem_destroy(&pInfo->ready);
  if (code != TSDB_CODE_SUCCESS) {
    qError("%s failed at line %d since %s", __func__, __LINE__, tstrerror(code));
  }

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +4235 to +4259
# self.do_create_database_privilege()
# self.do_alter_database_privilege()
# self.do_drop_database_privilege()
# self.do_use_database_privilege()
# self.do_show_databases_privilege()
# self.do_show_create_database_privilege()
# self.do_flush_database_privilege()
# self.do_compact_database_privilege()
# self.do_trim_database_privilege()
# self.do_rollup_database_privilege()
# self.do_scan_database_privilege()
# self.do_ssmigrate_database_privilege()

# # # Table privilege tests
# print("")
# print("[Table Privileges]")
# self.do_create_table_privilege()
# self.do_drop_table_privilege()
# self.do_alter_table_privilege()
# self.do_select_privilege()
# self.do_insert_privilege()
# self.do_delete_privilege()
# self.do_select_column_privilege_comprehensive()
# self.do_insert_column_privilege_comprehensive()
# self.do_show_create_table_privilege()
Copy link

Copilot AI Apr 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

test_priv_control() now comments out almost the entire privilege test suite (DB/Table/RBAC/System/etc.) and effectively only runs do_information_schema_privileges(). This will drastically reduce regression detection in CI; please avoid disabling tests by commenting out calls—use the framework’s skip/mark mechanism or gate the “manual-only” subset behind an explicit runtime flag/env var while keeping the default run comprehensive.

Suggested change
# self.do_create_database_privilege()
# self.do_alter_database_privilege()
# self.do_drop_database_privilege()
# self.do_use_database_privilege()
# self.do_show_databases_privilege()
# self.do_show_create_database_privilege()
# self.do_flush_database_privilege()
# self.do_compact_database_privilege()
# self.do_trim_database_privilege()
# self.do_rollup_database_privilege()
# self.do_scan_database_privilege()
# self.do_ssmigrate_database_privilege()
# # # Table privilege tests
# print("")
# print("[Table Privileges]")
# self.do_create_table_privilege()
# self.do_drop_table_privilege()
# self.do_alter_table_privilege()
# self.do_select_privilege()
# self.do_insert_privilege()
# self.do_delete_privilege()
# self.do_select_column_privilege_comprehensive()
# self.do_insert_column_privilege_comprehensive()
# self.do_show_create_table_privilege()
self.do_create_database_privilege()
self.do_alter_database_privilege()
self.do_drop_database_privilege()
self.do_use_database_privilege()
self.do_show_databases_privilege()
self.do_show_create_database_privilege()
self.do_flush_database_privilege()
self.do_compact_database_privilege()
self.do_trim_database_privilege()
self.do_rollup_database_privilege()
self.do_scan_database_privilege()
self.do_ssmigrate_database_privilege()
# # # Table privilege tests
print("")
print("[Table Privileges]")
self.do_create_table_privilege()
self.do_drop_table_privilege()
self.do_alter_table_privilege()
self.do_select_privilege()
self.do_insert_privilege()
self.do_delete_privilege()
self.do_select_column_privilege_comprehensive()
self.do_insert_column_privilege_comprehensive()
self.do_show_create_table_privilege()

Copilot uses AI. Check for mistakes.
Comment thread source/libs/executor/src/sysscanoperator.c
Comment thread source/libs/parser/src/parTranslater.c Outdated
Comment on lines +7207 to +7209
// Fast path: if all sys-table priv bits are set, any table is accessible.
// privInfo bits 3-8: privInfoBasic|privInfoPrivileged|privInfoAudit|privInfoSec|privPerfBasic|privPerfPrivileged
if ((pParCxt->privInfo & 0x01F8u) == 0x01F8u) return 0;
Copy link

Copilot AI Apr 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

transCheckSysTablePriv() uses a hard-coded bitmask (0x01F8u) for sys-table privilege bits. This is brittle and easy to break if the bit layout changes; please replace it with named constants/macros (or compute from the actual bitfield definitions) so the intent and maintenance contract are explicit.

Copilot uses AI. Check for mistakes.
Comment thread source/libs/parser/src/parTranslater.c Outdated
Comment thread source/common/src/systable.c
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 23 out of 23 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

source/libs/parser/src/parTranslater.c:14666

  • In translateCheckUserOptsPriv(), the password privilege branch compares authRsp.user with pParCxt->pUser, which will always match because catalogGetUserAuth() was requested for pParCxt->pUser. This makes the code always enforce PRIV_PASS_ALTER_SELF even when changing another user’s password, and also leaves targetUser unused. Compare targetUser against the current user (or pParCxt->pUser) to decide between PRIV_PASS_ALTER vs PRIV_PASS_ALTER_SELF.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +4249 to +4256
# self.do_create_database_privilege()
# self.do_alter_database_privilege()
# self.do_drop_database_privilege()
# self.do_use_database_privilege()
# self.do_show_databases_privilege()
# self.do_show_create_database_privilege()
# self.do_flush_database_privilege()
# self.do_compact_database_privilege()
Copy link

Copilot AI Apr 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

test_priv_control() now comments out almost the entire privilege test suite (DB/table/RBAC/system/function/view/stream/etc.) while the docstring and labels still describe it as a comprehensive CI test. This effectively removes coverage for most privilege checks and could let RBAC regressions slip through CI. If the intent is to make this "manual-only", consider gating sections behind an explicit flag/environment variable or splitting a dedicated, smaller manual test case instead of permanently commenting out the calls.

Copilot uses AI. Check for mistakes.
Copilot AI review requested due to automatic review settings April 26, 2026 12:38
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 25 out of 26 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

source/libs/parser/src/parTranslater.c:14660

  • The password-change privilege check compares authRsp.user with pParCxt->pUser, which are both the current user, so it will always take the “self password” path even when altering another user’s password. targetUser is computed but never used. Compare the target username being altered against the current user to decide between PRIV_PASS_ALTER vs PRIV_PASS_ALTER_SELF.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread test/cases/24-Users/test_user_passwd.py Outdated
tdLog.info(f"api path: {apiPath}")
if platform.system().lower() == 'linux':
p = subprocess.Popen(f"cd {apiPath} && make", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
p = subprocess.Popen(f"cd {apiPath} && make -f make_partial", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
Copy link

Copilot AI Apr 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On Linux this invokes make -f make_partial, but the added file in script/api/ is named makefile_partial. As-is the build step will fail with “No rule to make target 'make_partial'”. Update the filename (or add the expected makefile) so the test can compile passwdTest.c reliably.

Suggested change
p = subprocess.Popen(f"cd {apiPath} && make -f make_partial", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
p = subprocess.Popen(f"cd {apiPath} && make -f makefile_partial", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

Copilot uses AI. Check for mistakes.
Copilot AI review requested due to automatic review settings April 26, 2026 16:01
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 26 out of 27 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread test/cases/24-Users/test_user_passwd.py Outdated
Comment on lines +41 to +46
p = subprocess.Popen(f"cd {apiPath} && make -f make_partial", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = p.communicate()
if 0 != p.returncode:
tdLog.exit("Test script passwdTest.c make failed")
else:
p = subprocess.Popen(f"cd {apiPath} && jom -f makefile_win64.mak", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
p = subprocess.Popen(f"cd {apiPath} && jom -f makefile_partial_win64.mak", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
Copy link

Copilot AI Apr 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Linux build path: make -f make_partial refers to a non-existent makefile in script/api (the added file is makefile_partial). This will fail the passwd test on Linux unless there is an untracked make_partial file in the environment. Update the command to point at the actual filename (or rename the makefile to match).

Copilot uses AI. Check for mistakes.
Comment thread source/libs/executor/src/sysscanoperator.c
Comment thread source/client/src/clientImpl.c
Copilot AI review requested due to automatic review settings April 26, 2026 16:46
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 28 out of 29 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (1)

source/libs/parser/src/parTranslater.c:14666

  • In translateCheckUserOptsPriv(), the password privilege check compares authRsp.user with pParCxt->pUser, which are effectively the same current user, so the code will always take the “own password” branch and require PRIV_PASS_ALTER_SELF even when altering another user. targetUser is computed but never used. Please compare the current user (pParCxt->pUser) to the target user being altered/created (targetUser) to decide between PRIV_PASS_ALTER vs PRIV_PASS_ALTER_SELF.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copilot AI review requested due to automatic review settings April 27, 2026 01:45
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 28 out of 29 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (1)

source/libs/parser/src/parTranslater.c:14633

  • The password privilege check is comparing authRsp.user against pParCxt->pUser, which (given catalogGetUserAuth(..., pParCxt->pUser, &authRsp)) will always match the current user. This makes ALTER USER password changes always follow the “change own password” branch and can wrongly deny admins changing other users’ passwords. Use targetUser vs the current user to decide whether to require PRIV_PASS_ALTER or PRIV_PASS_ALTER_SELF (and remove the now-unused/incorrect comparison).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copilot AI review requested due to automatic review settings April 27, 2026 06:48
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 29 out of 30 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

source/libs/parser/src/parTranslater.c:14633

  • translateCheckUserOptsPriv() calculates targetUser but then compares authRsp.user vs pParCxt->pUser, which are both the current user returned by catalogGetUserAuth(). This makes the password privilege check always take the “self” branch, so changing another user’s password (and CREATE USER with a password) is validated against PRIV_PASS_ALTER_SELF instead of PRIV_PASS_ALTER. Compare targetUser with the current user (e.g., pParCxt->pUser) to decide whether this is a self-password change.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

if (code != 0) {
mError("failed to get show variables info since %s", tstrerror(code));
}
mndReleaseUser(pMnode, pUser);
Copy link

Copilot AI Apr 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mndReleaseUser(pMnode, pUser) is called unconditionally, but pUser can still be NULL on error paths before mndAcquireUser() succeeds. mndReleaseUser() does not handle NULL (it calls sdbRelease directly), so this can crash. Guard the release (e.g., if (pUser) ...) similarly to other mnode codepaths.

Suggested change
mndReleaseUser(pMnode, pUser);
if (pUser != NULL) {
mndReleaseUser(pMnode, pUser);
}

Copilot uses AI. Check for mistakes.
self.do_role_privilege()
self.do_role_creation_and_grant()
#self.do_role_lock_unlock() #can cause core BUG21
self.do_role_lock_unlock() #can cause core BUG21
Copy link

Copilot AI Apr 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test is now unconditionally running do_role_lock_unlock() while the inline comment still says it “can cause core BUG21”. If the crash is still reproducible, this will make CI flaky; if it’s fixed, please remove/update the comment (or gate the test by version/feature flag) so it doesn’t signal known instability.

Suggested change
self.do_role_lock_unlock() #can cause core BUG21
# Historically this test could trigger core BUG21, so keep it opt-in
# until it is confirmed safe across supported environments.
if os.environ.get("RUN_ROLE_LOCK_UNLOCK_TEST", "").lower() in ("1", "true", "yes", "on"):
self.do_role_lock_unlock()

Copilot uses AI. Check for mistakes.
@guanshengliang guanshengliang merged commit 908abd4 into main Apr 27, 2026
12 of 13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants