-
Nisha Gopalakrishnan authored
Analysis ======== SET READ_ONLY=1/SUPER_READ_ONLY = 1 under certain conditions does not block concurrent DDL executed by users without SUPER privileges. Consider the following scenario: connection 1(SUPER user) FLUSH TABLES WITH READ LOCK; connection 2:(Non SUPER user) CREATE TABLE t1 (fld1 INT); ---> Waits for GRL connection 3: (SUPER user) SET READ_ONLY=1; --> Succeeds connection 1(SUPER user) UNLOCK TABLES; --> Unblocks connection 2. CREATE TABLE tries to acquire IX in the GLOBAL namespace and is blocked because of the SHARED lock GLOBAL namespace held by FLUSH TABLES. SET READ_ONLY succeeds because the SHARED lock in GLOBAL and COMMIT namespace is granted. UNLOCK TABLES then releases the GRL held by FLUSH TABLES, which causes the the CREATE TABLE statement to resume without checking for the read_only state. Thus the CREATE TABLE statement succeeds even though the read_only has been enabled. This is a typical race condition situation where DDL checks 'read only' flag before acquiring IX lock in the GLOBAL namespace which protects from this flag being changed concurrently. This problem doesn't affect DML operations as there is an additional check for 'read_only' flag for such statements in mysql_lock_tables() (i.e. when IX lock in the GLOBAL namespace already has been acquired). Please note that this problem is less prominent in 8.0, where it affects only DDL which doesn't update any user or system table (for example, "DROP TABLE IF EXISTS no_such_table"). Fix === The read_only state is checked after the IX lock is acquired in the GLOBAL namespace in the following functions: lock_schema_name(), lock_tablespace_name() and lock_table_names() which provides protection against concurrent modification of the 'read_only' flag. Change-Id: I49a45aa627972d55e11b348bc2f5e5714215eae3
Nisha Gopalakrishnan authoredAnalysis ======== SET READ_ONLY=1/SUPER_READ_ONLY = 1 under certain conditions does not block concurrent DDL executed by users without SUPER privileges. Consider the following scenario: connection 1(SUPER user) FLUSH TABLES WITH READ LOCK; connection 2:(Non SUPER user) CREATE TABLE t1 (fld1 INT); ---> Waits for GRL connection 3: (SUPER user) SET READ_ONLY=1; --> Succeeds connection 1(SUPER user) UNLOCK TABLES; --> Unblocks connection 2. CREATE TABLE tries to acquire IX in the GLOBAL namespace and is blocked because of the SHARED lock GLOBAL namespace held by FLUSH TABLES. SET READ_ONLY succeeds because the SHARED lock in GLOBAL and COMMIT namespace is granted. UNLOCK TABLES then releases the GRL held by FLUSH TABLES, which causes the the CREATE TABLE statement to resume without checking for the read_only state. Thus the CREATE TABLE statement succeeds even though the read_only has been enabled. This is a typical race condition situation where DDL checks 'read only' flag before acquiring IX lock in the GLOBAL namespace which protects from this flag being changed concurrently. This problem doesn't affect DML operations as there is an additional check for 'read_only' flag for such statements in mysql_lock_tables() (i.e. when IX lock in the GLOBAL namespace already has been acquired). Please note that this problem is less prominent in 8.0, where it affects only DDL which doesn't update any user or system table (for example, "DROP TABLE IF EXISTS no_such_table"). Fix === The read_only state is checked after the IX lock is acquired in the GLOBAL namespace in the following functions: lock_schema_name(), lock_tablespace_name() and lock_table_names() which provides protection against concurrent modification of the 'read_only' flag. Change-Id: I49a45aa627972d55e11b348bc2f5e5714215eae3
Loading