From 9235578578074d675c5589bedc432ff9edb87ad4 Mon Sep 17 00:00:00 2001 From: tiancaiamao Date: Tue, 2 Jul 2019 10:44:30 +0800 Subject: [PATCH] executor: let flush privileges do nothing when `skip-grant-table` is configured (#10986) When skip-grant-table is enabled, privilege handle is not initialized, calling flush privileges would meet nil pointer panic --- executor/executor_test.go | 1 + executor/simple.go | 7 +++++++ executor/simple_test.go | 31 +++++++++++++++++++++++++++++-- 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/executor/executor_test.go b/executor/executor_test.go index 2b5aaa145f229..227f67602de65 100644 --- a/executor/executor_test.go +++ b/executor/executor_test.go @@ -94,6 +94,7 @@ var _ = Suite(&testBypassSuite{}) var _ = Suite(&testUpdateSuite{}) var _ = Suite(&testOOMSuite{}) var _ = Suite(&testPointGetSuite{}) +var _ = Suite(&testFlushSuite{}) type testSuite struct { cluster *mocktikv.Cluster diff --git a/executor/simple.go b/executor/simple.go index 9aef2dc611495..be97225d5629a 100644 --- a/executor/simple.go +++ b/executor/simple.go @@ -812,6 +812,13 @@ func (e *SimpleExec) executeFlush(s *ast.FlushStmt) error { return errors.New("FLUSH TABLES WITH READ LOCK is not supported. Please use @@tidb_snapshot") } case ast.FlushPrivileges: + // If skip-grant-table is configured, do not flush privileges. + // Because LoadPrivilegeLoop does not run and the privilege Handle is nil, + // Call dom.PrivilegeHandle().Update would panic. + if config.GetGlobalConfig().Security.SkipGrantTable { + return nil + } + dom := domain.GetDomain(e.ctx) sysSessionPool := dom.SysSessionPool() ctx, err := sysSessionPool.Get() diff --git a/executor/simple_test.go b/executor/simple_test.go index cbbf4a76d921d..185a64cc6833f 100644 --- a/executor/simple_test.go +++ b/executor/simple_test.go @@ -16,17 +16,19 @@ package executor_test import ( "context" - "github.com/pingcap/tidb/planner/core" - . "github.com/pingcap/check" "github.com/pingcap/parser/auth" "github.com/pingcap/parser/model" "github.com/pingcap/parser/mysql" "github.com/pingcap/parser/terror" + "github.com/pingcap/tidb/config" "github.com/pingcap/tidb/domain" "github.com/pingcap/tidb/executor" + "github.com/pingcap/tidb/planner/core" "github.com/pingcap/tidb/session" "github.com/pingcap/tidb/sessionctx" + "github.com/pingcap/tidb/store/mockstore" + "github.com/pingcap/tidb/store/mockstore/mocktikv" "github.com/pingcap/tidb/util/testkit" "github.com/pingcap/tidb/util/testutil" ) @@ -386,6 +388,31 @@ func (s *testSuite3) TestFlushPrivileges(c *C) { // After flush. _, err = se.Execute(ctx, `SELECT Password FROM mysql.User WHERE User="testflush" and Host="localhost"`) c.Check(err, IsNil) + +} + +type testFlushSuite struct{} + +func (s *testFlushSuite) TestFlushPrivilegesPanic(c *C) { + // Run in a separate suite because this test need to set SkipGrantTable config. + cluster := mocktikv.NewCluster() + mocktikv.BootstrapWithSingleStore(cluster) + mvccStore := mocktikv.MustNewMVCCStore() + store, err := mockstore.NewMockTikvStore( + mockstore.WithCluster(cluster), + mockstore.WithMVCCStore(mvccStore), + ) + c.Assert(err, IsNil) + defer store.Close() + + config.GetGlobalConfig().Security.SkipGrantTable = true + dom, err := session.BootstrapSession(store) + c.Assert(err, IsNil) + defer dom.Close() + + tk := testkit.NewTestKit(c, store) + tk.MustExec("FLUSH PRIVILEGES") + config.GetGlobalConfig().Security.SkipGrantTable = false } func (s *testSuite3) TestDropStats(c *C) {