Fix drop_label privilege check for non-superusers (unrecognized class ID) - #2497
Fix drop_label privilege check for non-superusers (unrecognized class ID)#2497eeshwarg wants to merge 1 commit into
Conversation
range_var_callback_for_remove_relation() called object_ownercheck() with the wrong argument order for the PG16+ API object_ownercheck(classid, objectid, roleid). It passed rel_oid as the classid and a namespace OID as the objectid, so the classid lookup hit the default case and raised "unrecognized class ID" for any non-superuser dropping a graph label. Superusers were unaffected because object_ownercheck() early-returns via superuser_arg(). Pass RelationRelationId as the classid and rel_oid as the objectid, matching upstream PostgreSQL's RangeVarCallbackForDropRelation. Add a regression test in security.sql covering a NOSUPERUSER role that owns a graph/label and successfully runs drop_label. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Warning
Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.
Fixes a PostgreSQL 16+ ownership check bug that caused non-superusers to fail drop_label() (and related label drops) with ERROR: unrecognized class ID, by passing the correct (classid, objectid, roleid) arguments to object_ownercheck() and adding a regression test to prevent regressions.
Changes:
- Corrected
object_ownercheck()argument order inrange_var_callback_for_remove_relation(). - Added a non-superuser regression scenario covering create graph/label and successful
drop_label. - Updated regression expected output accordingly.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| src/backend/commands/label_commands.c | Fixes ownership check by calling object_ownercheck(RelationRelationId, rel_oid, GetUserId()). |
| regress/sql/security.sql | Adds regression test ensuring non-superuser owners can successfully drop_label(). |
| regress/expected/security.out | Captures expected output for the new regression test block. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| SELECT format('GRANT CREATE ON DATABASE %I TO age_nonsuper', current_database()) | ||
| \gexec |
Problem
Any non-superuser calling
drop_label('graph', 'label')(or dropping a vertex/edge label) fails with:Superusers are unaffected.
Root cause
In
src/backend/commands/label_commands.c,range_var_callback_for_remove_relation()calls the PG16+object_ownercheck()with the wrong argument order. The API is:AGE passed
rel_oidasclassid(should beRelationRelationId) and a namespace OID asobjectid(should berel_oid). Sinceclassidisn't a real catalog OID, the lookup hits thedefaultcase inget_object_propertyand raisesunrecognized class ID. Superusers escape becauseobject_ownercheckearly-returns viasuperuser_arg(roleid)before the classid lookup.This was introduced in the PG16 port: before PG16 the code used the correct 2-arg
pg_class_ownercheck(rel_oid, GetUserId()). The same defect is present onmaster,PG16,PG17, andPG18; PG15 and earlier are unaffected. This PR fixesmaster.Fix
This matches upstream PostgreSQL's own
RangeVarCallbackForDropRelationusage.RelationRelationIdis already available via existing includes (catalog/pg_class_d.h); no new include needed.Testing
regress/sql/security.sql: aNOSUPERUSERrole creates (and therefore owns) a graph and label, then successfully runsdrop_label. Verified it fails withERROR: unrecognized class IDon the unpatched build and passes after the fix.make installcheckfull suite: 42/42 tests pass (PostgreSQL 18).Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com