[MDEV-19899] Multiple matching grants no longer stacked Created: 2019-06-28  Updated: 2019-08-22  Resolved: 2019-08-22

Status: Closed
Project: MariaDB Server
Component/s: Authentication and Privilege System
Affects Version/s: 10.4
Fix Version/s: N/A

Type: Bug Priority: Major
Reporter: sjon Assignee: Sergei Golubchik
Resolution: Not a Bug Votes: 0
Labels: regression

Issue Links:
Problem/Incident
is caused by MDEV-14732 mysql.db privileges evaluated on orde... Closed
is caused by MDEV-14735 better matching order for grants Closed

 Description   

Since upgrading from 10.3.16 to 10.4.6 our grants no longer work the same. I suspect this is caused by the linked MDEV-15649. We have multiple developers with their own prefixed databases. Other developers are allowed to view those, so we have:

GRANT SELECT ON `%-development`.* TO 'user'@'127.0.0.1';
GRANT SELECT, INSERT, UPDATE, DELETE ON `user-%`.* TO 'user'@'127.0.0.1';

this used to work fine. It no longer does (for some users). Reproducible testcase:

create user 'jtest'@'127.0.0.1' identified by 'jtest';
GRANT SELECT ON `%test`.* TO 'jtest'@'127.0.0.1';
GRANT SELECT, INSERT, DELETE ON `j-%`.* TO 'jtest'@'127.0.0.1';

(as user jtest)
insert into `j-test` values ('x');

# ERROR 1142 (42000): INSERT command denied to user 'jtest'@'127.0.0.1' for table 'j-test'



 Comments   
Comment by Vladislav Vaintroub [ 2019-06-29 ]

The multiple matching grants were never stacked. I guess (in absence of full information), that you have both user@localhost accounts, as well as
user@127.0.0.1 . Both accounts match the user exactly. and if you log in on the local host, it is (and always was), strictly speaking, undefined, which of 2 accounts you'll end up with. 10.4 prefers "user@localhost", and depending on phase of the moon and on the order the accounts were defined in the mysql.user, maybe in 10.3 you got "user@127.0.0.1". In case like yours, please make sure that both accounts have the same grants.

Comment by sjon [ 2019-07-02 ]

I only have @127.0.0.1 definitions on this server:

both select count(*) from mysql.user where Host='localhost'; and select count(*) from mysql.db where Host='localhost'; return 0

I've updated the original report-description. I realize 'stacked' might not be the proper term - but can you confirm whether or not the behavior as described in the testcase is correct or not?

Comment by Alice Sherepa [ 2019-07-31 ]

Thanks! Reproduced as described on 10.4, test passes on 10.3:

create database `j-test`;
create table `j-test`.t1(id int);
create table test.t1(id int);	
 
create user 'jtest'@localhost identified by 'jtest';
 
GRANT SELECT ON `%test`.* TO 'jtest'@localhost;
GRANT SELECT, INSERT, DELETE ON `j-%`.* TO 'jtest'@localhost;
 
show grants for 'jtest'@localhost;
 
connect conn1,localhost,jtest,jtest,test;
insert into `j-test`.t1 values (1);
select * from test.t1;
 
disconnect conn1;
connection default;
 
drop user 'jtest'@localhost;
drop database `j-test`;
drop table test.t1;

10.4 6dfa085fd5cfa9f4ed

create database `j-test`;
create table `j-test`.t1(id int);
create table test.t1(id int);
create user 'jtest'@localhost identified by 'jtest';
GRANT SELECT ON `%test`.* TO 'jtest'@localhost;
GRANT SELECT, INSERT, DELETE ON `j-%`.* TO 'jtest'@localhost;
show grants for 'jtest'@localhost;
Grants for jtest@localhost
GRANT USAGE ON *.* TO 'jtest'@'localhost' IDENTIFIED BY PASSWORD '*8EFCF76F0D8572B6A29E56D50FFD82F96F44E78B'
GRANT SELECT ON `%test`.* TO 'jtest'@'localhost'
GRANT SELECT, INSERT, DELETE ON `j-%`.* TO 'jtest'@'localhost'
connect conn1,localhost,jtest,jtest,test;
insert into `j-test`.t1 values (1);
main.1_my                                [ fail ]
        Test ended at 2019-07-31 11:57:20
 
CURRENT_TEST: main.1_my
mysqltest: At line 14: query 'insert into `j-test`.t1 values (1)' failed: 1142: INSERT command denied to user 'jtest'@'localhost' for table 't1'

Comment by Sergei Golubchik [ 2019-08-22 ]

This is not a bug. Old behavior was incorrect. The documentation states that all grants are sorted in order from most specific to least specific. And the first matching grant is applied. You have

GRANT SELECT ON `%test`.* TO 'jtest'@'127.0.0.1';
GRANT SELECT, INSERT, DELETE ON `j-%`.* TO 'jtest'@'127.0.0.1';

and you expect INSERT INTO `j-test`.t1 to work (grant on j-% is applied, not grant on %test).

This used to work because MariaDB incorrectly sorted %test grants after j-% grants, considering j-% grant as "more specific". This was incorrect, because there are fewer valid database names that match the %test pattern, so it is more specific and should've been sorted first.

This bug was fixed in 10.4.

Note, that if you swap your grants, like in

GRANT SELECT ON `j-%`.* TO 'jtest'@'127.0.0.1';
GRANT SELECT, INSERT, DELETE ON `%test`.* TO 'jtest'@'127.0.0.1';

you'll get an opposite effect, INSERT INTO `j-test` will work in 10.4 and will fail in 10.3.

Generated at Thu Feb 08 08:55:12 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.