Uploaded image for project: 'MariaDB Server'
  1. MariaDB Server
  2. MDEV-40301

Multi-user GRANT or DENY where one target does not exist is applied to the valid user on the primary but is not written to the binlog

    XMLWordPrintable

Details

    • Not for Release Notes

    Description

      Update: ref below for a more generic all-versions-affected GRANT based testcase, i.e. not using the new 13.1 DENY

      A multi-user DENY where one target does not exist is applied to the valid user on the primary but is not written to the binary log, so a replica keeps the access the primary just removed. u1 is granted SELECT on test, then DENY SELECT ON test.* TO u1, u2 runs where u2 does not exist. The primary denies u1 - a SELECT there is refused with ER_TABLEACCESS_DENIED_ERROR - but the statement errors overall on the missing u2, so it is not binlogged. After sync_slave_with_master the same SELECT by u1 on the replica returns the row.

      --source include/master-slave.inc
      connection master;
      CREATE TABLE test.t (a INT);
      INSERT INTO test.t VALUES (1);
      CREATE USER u1@'%' IDENTIFIED BY 'pw';
      GRANT SELECT ON test.* TO u1@'%';
      sync_slave_with_master;
      connection master;
      SET SESSION sql_mode='NO_AUTO_CREATE_USER';
      --error ER_PASSWORD_NO_MATCH
      DENY SELECT ON test.* TO u1@'%', u2@'%';
      connect (m,127.0.0.1,u1,pw,,$MASTER_MYPORT);
      --error ER_TABLEACCESS_DENIED_ERROR,ER_DBACCESS_DENIED_ERROR
      SELECT * FROM test.t;
      connection master;
      sync_slave_with_master;
      connection slave;
      connect (s,127.0.0.1,u1,pw,,$SLAVE_MYPORT);
      --error ER_TABLEACCESS_DENIED_ERROR,ER_DBACCESS_DENIED_ERROR
      SELECT * FROM test.t;
      connection master;
      DROP USER u1@'%';
      DROP TABLE test.t;
      --source include/rpl_end.inc
      

      Leads to:

      MDEV-14443 CS 13.1.0 0c709a5fe3db1733493c3b84bef9e4bc62555c17 (Optimized, Clang 22.1.8-20260622) Build 07/07/2026

      mysqltest: At line 20: query 'SELECT * FROM test.t' succeeded - should have failed with error ER_TABLEACCESS_DENIED_ERROR (1142)...
      

      DENY reuses the GRANT path, which binlogs only on full success (if (!result) write_bin_log(...) in mysql_grant / mysql_table_grant). For GRANT a stranded statement leaves the replica less privileged, which is safe; for DENY the safe direction is inverted, so the replica ends up more privileged than the primary. This is separate from MDEV-40025 - there the DENY is never applied (most-specific matching row wins, by design); here it is applied and enforced on the primary and only fails to replicate. Reproduces for binlog_format stmt, row and mix.

      Perhaps applying a multi-user DENY atomically (validate the whole list first, apply nothing on any failure), or binlogging it whenever at least one deny was applied so replicas match, could be viable paths forward.

       

      Attachments

        Issue Links

          Activity

            People

              bnestere Brandon Nesterenko
              Roel Roel Van de Paar
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Time Tracking

                  Estimated:
                  Original Estimate - 0d
                  0d
                  Remaining:
                  Remaining Estimate - 0d
                  0d
                  Logged:
                  Time Spent - 3h 10m
                  3h 10m

                  Git Integration

                    Error rendering 'com.xiplink.jira.git.jira_git_plugin:git-issue-webpanel'. Please contact your Jira administrators.