Bug #101592 Re-open the bug #89850 Throwing exception if access to granted for table
Submitted: 12 Nov 2020 20:28 Modified: 24 Feb 2021 16:12
Reporter: Stanislav Revin Email Updates:
Status: Closed Impact on me:
None 
Category:Connector / NET Severity:S2 (Serious)
Version:8.0.19.0, 8.0.22 OS:Windows
Assigned to: CPU Architecture:Any
Tags: SELECT command denied to user '***'@'***' for table 'bogus_table

[12 Nov 2020 20:28] Stanislav Revin
Description:
Exception thrown after query when user does not have right for select from bogus_table.

How to repeat:
Here is an example to reproduce it:

	var query = "SELECT * FROM INFORMATION_SCHEMA.tables";

	using (var cmd = new MySqlCommand(query))
	{
		cmd.Connection = connection;
		cmd.CommandTimeout = 1800;
		int limit = 10;
		int count = 0;
		
		using (var reader = cmd.ExecuteReader())
		{
			
			if (reader.HasRows)
			{
				while (reader.Read() && count < limit)
				{
					Console.WriteLine(reader.GetString(0));
					count += 1;
				}
				
			}
			
			cmd.Cancel();
			
		}
		
	}

Suggested fix:
Just replace function ClearKillFlag in datareader.cs with this code

    private void ClearKillFlag()
    {
      // This query will silently crash because of the Kill call that happened before.
      string dummyStatement = "SELECT * FROM bogus_table LIMIT 0"; /* dummy query used to clear kill flag */
      MySqlCommand dummyCommand = new MySqlCommand(dummyStatement, _connection) {InternallyCreated = true};

      try
      {
        dummyCommand.ExecuteReader(); // ExecuteReader catches the exception and returns null, which is expected.
      }
      catch (MySqlException ex)
      {
        int[] errors = { (int)MySqlErrorCode.NoSuchTable, (int)MySqlErrorCode.TableAccessDenied, (int)MySqlErrorCode.UnknownTable};
        if (Array.IndexOf(errors, (int)ex.Number) < 0)
                    throw;
      }
    }
[12 Nov 2020 20:29] Stanislav Revin
Stack trace:

at MySql.Data.MySqlClient.MySqlStream.ReadPacket()
   at MySql.Data.MySqlClient.NativeDriver.GetResult(Int32& affectedRow, Int64& insertedId)
   at MySql.Data.MySqlClient.Driver.GetResult(Int32 statementId, Int32& affectedRows, Int64& insertedId)
   at MySql.Data.MySqlClient.Driver.NextResult(Int32 statementId, Boolean force)
   at MySql.Data.MySqlClient.MySqlDataReader.NextResult()
   at MySql.Data.MySqlClient.MySqlCommand.ExecuteReader(CommandBehavior behavior)
   at MySql.Data.MySqlClient.MySqlCommand.ExecuteReader()
   at MySql.Data.MySqlClient.MySqlDataReader.ClearKillFlag()
   at MySql.Data.MySqlClient.MySqlDataReader.Close()
   at MySql.Data.MySqlClient.MySqlDataReader.Dispose()
   at UserQuery
   at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ThreadHelper.ThreadStart()

Error code: 1109.

It sometimes can be 1142.
[12 Nov 2020 20:37] Stanislav Revin
So, if you call cmd.Cancel(), where cmd represents a MySqlCommand object, you'll get the above exception.

A trivial workaround is also possible but not recommended. The workaround reveals an issue with orphan permissions on database objects. A permission stays on a deleted object.

CREATE TABLE bogus_table (id int);

GRANT SELECT ON bogus_table TO 'YourUserName'@'YourServerName';

DROP TABLE bogus_table;

After executing the above statements, we will not get an exception that complains about the bogus_table not being there, because MySQL database thinks that there is a permission on that table in that database. It could be a potential security flaw.
[13 Nov 2020 8:01] MySQL Verification Team
Hello Stanislav Revin,

Thank you for the report and test case.
Verified as described.

regards,
Umesh
[18 Dec 2020 19:28] OCA Admin
Contribution submitted via Github - Relates to https://bugs.mysql.com/bug.php?id=101592 
(*) Contribution by Stanislav Revin (Github mrranknullity, mysql-connector-net/pull/37#issuecomment-747706501): I confirm the code being submitted is offered under the terms of the OCA, and that I am authorized to contribute it.

Contribution: git_patch_539913045.txt (text/plain), 1.68 KiB.

[18 Dec 2020 19:28] OCA Admin
Contribution submitted via Github - Relates to https://bugs.mysql.com/bug.php?id=101592 
(*) Contribution by Stanislav Revin (Github mrranknullity, mysql-connector-net/pull/36#issuecomment-747706095): I confirm the code being submitted is offered under the terms of the OCA, and that I am authorized to contribute it.

Contribution: git_patch_539909192.txt (text/plain), 1.97 KiB.

[18 Dec 2020 19:28] OCA Admin
Contribution submitted via Github - Relates to https://bugs.mysql.com/bug.php?id=101592 
(*) Contribution by Stanislav Revin (Github mrranknullity, mysql-connector-net/pull/35#issuecomment-747706341): I confirm the code being submitted is offered under the terms of the OCA, and that I am authorized to contribute it.

Contribution: git_patch_539895133.txt (text/plain), 1.71 KiB.

[24 Feb 2021 16:12] Christine Cole
Posted by developer:
 
Fixed as of the upcoming MySQL Connector/NET 8.0.24 release, and here's the proposed changelog entry from the documentation team:

Additional error codes now prevent unexpected exceptions after a query.
Thanks to Stanislav Revin for the patch.

Thank you for the bug report.