BenSpex opened a new issue, #2474:
URL: https://github.com/apache/age/issues/2474

   ## Environment
   - Apache AGE **1.7.0** (`apache/age:release_PG18_1.7.0`) — **crashes**
   - Apache AGE **1.8.0** (current master, `apache/age:dev_snapshot_PG18`) — 
**still crashes**
   - PostgreSQL 18.1, official `apache/age` image (age in 
`shared_preload_libraries`)
   
   ## Summary
   When a **non-superuser** role that is subject to **FORCE ROW LEVEL 
SECURITY** with a policy on an
   **edge label table** runs `MATCH (n) DETACH DELETE n` where `n` has at least 
one connected edge, the
   backend crashes with **SIGSEGV (signal 11)** ("server closed the connection 
unexpectedly"). The
   server restarts and recovers, but the operation cannot complete.
   
   RLS enforcement for Cypher DELETE was added at the executor level in #2309; 
this appears to be a gap
   in the `DETACH DELETE` implicit-edge-cleanup path when an edge-label RLS 
policy is in force.
   
   ## Minimal reproduction
   ```sql
   -- === as a SUPERUSER ===
   LOAD 'age';
   SET search_path = ag_catalog, "$user", public;
   SELECT create_graph('g');
   SELECT create_vlabel('g', 'V');
   SELECT create_elabel('g', 'E');
   
   CREATE ROLE rls_user LOGIN PASSWORD 'pw';
   GRANT USAGE ON SCHEMA ag_catalog, g TO rls_user;
   GRANT SELECT, INSERT, UPDATE, DELETE ON g."V", g."E", g."_ag_label_vertex", 
g."_ag_label_edge" TO rls_user;
   GRANT USAGE ON ALL SEQUENCES IN SCHEMA g TO rls_user;
   ALTER ROLE rls_user SET search_path = "$user", public, ag_catalog;
   
   -- an ordinary agtype-keyed policy, fixed to tid='x' for the repro
   ALTER TABLE g."V" ENABLE ROW LEVEL SECURITY; ALTER TABLE g."V" FORCE ROW 
LEVEL SECURITY;
   ALTER TABLE g."E" ENABLE ROW LEVEL SECURITY; ALTER TABLE g."E" FORCE ROW 
LEVEL SECURITY;
   CREATE POLICY p ON g."V" FOR ALL TO rls_user
     USING      (ag_catalog.agtype_access_operator(properties, '"tid"'::agtype) 
= '"x"'::agtype)
     WITH CHECK (ag_catalog.agtype_access_operator(properties, '"tid"'::agtype) 
= '"x"'::agtype);
   CREATE POLICY p ON g."E" FOR ALL TO rls_user
     USING      (ag_catalog.agtype_access_operator(properties, '"tid"'::agtype) 
= '"x"'::agtype)
     WITH CHECK (ag_catalog.agtype_access_operator(properties, '"tid"'::agtype) 
= '"x"'::agtype);
   
   -- === reconnect as rls_user ===
   -- \c "dbname=... user=rls_user password=pw"
   SET search_path = "$user", public, ag_catalog;
   SELECT * FROM cypher('g', $$ CREATE (:V {tid:'x'})-[:E {tid:'x'}]->(:V 
{tid:'x'}) $$) AS (v agtype);
   SELECT * FROM cypher('g', $$ MATCH (n) DETACH DELETE n $$) AS (v agtype);  
-- <-- SIGSEGV here
   ```
   
   ## Observed
   ```
   server closed the connection unexpectedly
        This probably means the server terminated abnormally before or while 
processing the request.
   connection to server was lost
   ```
   Server log: `LOG: client backend (PID …) was terminated by signal 11: 
Segmentation fault`.
   
   ## Expected
   `DETACH DELETE` deletes the vertex and its connected edges that are visible 
to the role under RLS,
   without crashing (as it does for a superuser / a role that bypasses RLS).
   
   ## Narrowing (what works vs. crashes, same non-superuser role, same FORCE 
RLS)
   - ✅ edge `CREATE` (WITH CHECK enforced correctly)
   - ✅ edge `SET` / property `UPDATE`
   - ✅ **edge-only** delete: `MATCH ()-[r:E]->() DELETE r`
   - ✅ **node-only** `DETACH DELETE` (vertex with **no** connected edge)
   - ✅ two-step: `MATCH ()-[r]->() DELETE r` then `MATCH (n) DELETE n`
   - ❌ **`DETACH DELETE` of a vertex WITH a connected edge → SIGSEGV** (the 
only failing path)
   - ✅ the same `DETACH DELETE` as a superuser (RLS bypass) — so it is specific 
to RLS-bound roles.
   
   Disabling the RLS policy on the **edge** label (`g."E"`) alone avoids the 
crash (the vertex-label
   policy is not the trigger), which points at the edge-policy evaluation 
during DETACH's implicit edge
   deletion.
   
   ## Impact
   Any multi-tenant AGE deployment that isolates tenants via RLS on the graph 
label tables cannot run
   `DETACH DELETE` (e.g. a projection rebuild) under the tenant-bound runtime 
role.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to