From aa5d84563cfb8e854cfd1eac4c3d573e0718ba74 Mon Sep 17 00:00:00 2001 From: ailinkid <314806019@qq.com> Date: Fri, 16 Jul 2021 16:37:26 +0800 Subject: [PATCH 1/6] access the table storage stats need super privilege Signed-off-by: ailinkid <314806019@qq.com> --- executor/infoschema_reader.go | 3 +++ executor/infoschema_reader_test.go | 26 ++++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/executor/infoschema_reader.go b/executor/infoschema_reader.go index c381f934af211..8b5550578c62f 100644 --- a/executor/infoschema_reader.go +++ b/executor/infoschema_reader.go @@ -1616,6 +1616,9 @@ type tableStorageStatsRetriever struct { } func (e *tableStorageStatsRetriever) retrieve(ctx context.Context, sctx sessionctx.Context) ([][]types.Datum, error) { + if !hasPriv(sctx, mysql.ProcessPriv) { + return nil, plannercore.ErrSpecificAccessDenied.GenWithStackByArgs("PROCESS") + } if e.retrieved { return nil, nil } diff --git a/executor/infoschema_reader_test.go b/executor/infoschema_reader_test.go index 23a92313aa220..9b8ce21c45dd7 100644 --- a/executor/infoschema_reader_test.go +++ b/executor/infoschema_reader_test.go @@ -909,6 +909,32 @@ func (s *testInfoschemaClusterTableSuite) TestTableStorageStats(c *C) { "test 2", )) c.Assert(len(tk.MustQuery("select TABLE_NAME from information_schema.TABLE_STORAGE_STATS where TABLE_SCHEMA = 'mysql';").Rows()), Equals, 24) + + // More tests about the privileges. + tk.MustExec("create user 'testuser'@'localhost'") + tk.MustExec("create user 'testuser2'@'localhost'") + tk1 := testkit.NewTestKit(c, store) + defer tk1.MustExec("drop user 'testuser'@'localhost'") + defer tk1.MustExec("drop user 'testuser2'@'localhost'") + + tk.MustExec("grant process on *.* to 'testuser2'@'localhost'") + c.Assert(tk.Se.Auth(&auth.UserIdentity{ + Username: "testuser", + Hostname: "localhost", + }, nil, nil), Equals, true) + + err = tk.QueryToErr("select * from information_schema.TABLE_STORAGE_STATS where TABLE_SCHEMA = 'information_schema'") + c.Assert(err, NotNil) + // This error is come from cop(TiDB) fetch from rpc server. + c.Assert(err.Error(), Equals, "[planner:1227]Access denied; you need (at least one of) the PROCESS privilege(s) for this operation") + + c.Assert(tk.Se.Auth(&auth.UserIdentity{ + Username: "testuser2", + Hostname: "localhost", + }, nil, nil), Equals, true) + + err = tk.QueryToErr("select * from information_schema.TABLE_STORAGE_STATS where TABLE_SCHEMA = 'information_schema'") + c.Assert(err, IsNil) } func (s *testInfoschemaTableSuite) TestSequences(c *C) { From 5fbbdd1823fdc113f05150b6f27e2478380d417f Mon Sep 17 00:00:00 2001 From: ailinkid <314806019@qq.com> Date: Fri, 16 Jul 2021 16:42:23 +0800 Subject: [PATCH 2/6] change process to super Signed-off-by: ailinkid <314806019@qq.com> --- executor/infoschema_reader.go | 4 ++-- executor/infoschema_reader_test.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/executor/infoschema_reader.go b/executor/infoschema_reader.go index 8b5550578c62f..f4cd611af661d 100644 --- a/executor/infoschema_reader.go +++ b/executor/infoschema_reader.go @@ -1616,8 +1616,8 @@ type tableStorageStatsRetriever struct { } func (e *tableStorageStatsRetriever) retrieve(ctx context.Context, sctx sessionctx.Context) ([][]types.Datum, error) { - if !hasPriv(sctx, mysql.ProcessPriv) { - return nil, plannercore.ErrSpecificAccessDenied.GenWithStackByArgs("PROCESS") + if !hasPriv(sctx, mysql.SuperPriv) { + return nil, plannercore.ErrSpecificAccessDenied.GenWithStackByArgs("SUPER") } if e.retrieved { return nil, nil diff --git a/executor/infoschema_reader_test.go b/executor/infoschema_reader_test.go index 9b8ce21c45dd7..c2fc9e5c0028a 100644 --- a/executor/infoschema_reader_test.go +++ b/executor/infoschema_reader_test.go @@ -917,7 +917,7 @@ func (s *testInfoschemaClusterTableSuite) TestTableStorageStats(c *C) { defer tk1.MustExec("drop user 'testuser'@'localhost'") defer tk1.MustExec("drop user 'testuser2'@'localhost'") - tk.MustExec("grant process on *.* to 'testuser2'@'localhost'") + tk.MustExec("grant super on *.* to 'testuser2'@'localhost'") c.Assert(tk.Se.Auth(&auth.UserIdentity{ Username: "testuser", Hostname: "localhost", @@ -926,7 +926,7 @@ func (s *testInfoschemaClusterTableSuite) TestTableStorageStats(c *C) { err = tk.QueryToErr("select * from information_schema.TABLE_STORAGE_STATS where TABLE_SCHEMA = 'information_schema'") c.Assert(err, NotNil) // This error is come from cop(TiDB) fetch from rpc server. - c.Assert(err.Error(), Equals, "[planner:1227]Access denied; you need (at least one of) the PROCESS privilege(s) for this operation") + c.Assert(err.Error(), Equals, "[planner:1227]Access denied; you need (at least one of) the SUPER privilege(s) for this operation") c.Assert(tk.Se.Auth(&auth.UserIdentity{ Username: "testuser2", From 8004a9ab4582879f8765701a397f5dd5f749469b Mon Sep 17 00:00:00 2001 From: ailinkid <314806019@qq.com> Date: Mon, 19 Jul 2021 13:26:43 +0800 Subject: [PATCH 3/6] add the privilege check Signed-off-by: ailinkid <314806019@qq.com> --- executor/infoschema_reader.go | 21 ++++++++++++++++----- executor/infoschema_reader_test.go | 9 +++------ 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/executor/infoschema_reader.go b/executor/infoschema_reader.go index f4cd611af661d..e236edb6cfc4a 100644 --- a/executor/infoschema_reader.go +++ b/executor/infoschema_reader.go @@ -1616,9 +1616,6 @@ type tableStorageStatsRetriever struct { } func (e *tableStorageStatsRetriever) retrieve(ctx context.Context, sctx sessionctx.Context) ([][]types.Datum, error) { - if !hasPriv(sctx, mysql.SuperPriv) { - return nil, plannercore.ErrSpecificAccessDenied.GenWithStackByArgs("SUPER") - } if e.retrieved { return nil, nil } @@ -1674,19 +1671,33 @@ func (e *tableStorageStatsRetriever) initialize(sctx sessionctx.Context) error { } } + // Privilege checker. + checker := func(db, table string) bool { + if pm := privilege.GetPrivilegeManager(sctx); pm != nil { + return pm.RequestVerification(sctx.GetSessionVars().ActiveRoles, db, table, "", mysql.SuperPriv) + } + return true + } + // Extract the tables to the initialTable. for _, DB := range databases { // The user didn't specified the table, extract all tables of this db to initialTable. if len(tables) == 0 { tbs := is.SchemaTables(model.NewCIStr(DB)) for _, tb := range tbs { - e.initialTables = append(e.initialTables, &initialTable{DB, tb.Meta()}) + // For every db.table, check it's privileges. + if checker(DB, tb.Meta().Name.L) { + e.initialTables = append(e.initialTables, &initialTable{DB, tb.Meta()}) + } } } else { // The user specified the table, extract the specified tables of this db to initialTable. for tb := range tables { if tb, err := is.TableByName(model.NewCIStr(DB), model.NewCIStr(tb)); err == nil { - e.initialTables = append(e.initialTables, &initialTable{DB, tb.Meta()}) + // For every db.table, check it's privileges. + if checker(DB, tb.Meta().Name.L) { + e.initialTables = append(e.initialTables, &initialTable{DB, tb.Meta()}) + } } } } diff --git a/executor/infoschema_reader_test.go b/executor/infoschema_reader_test.go index c2fc9e5c0028a..f1e08d97a2532 100644 --- a/executor/infoschema_reader_test.go +++ b/executor/infoschema_reader_test.go @@ -923,18 +923,15 @@ func (s *testInfoschemaClusterTableSuite) TestTableStorageStats(c *C) { Hostname: "localhost", }, nil, nil), Equals, true) - err = tk.QueryToErr("select * from information_schema.TABLE_STORAGE_STATS where TABLE_SCHEMA = 'information_schema'") - c.Assert(err, NotNil) - // This error is come from cop(TiDB) fetch from rpc server. - c.Assert(err.Error(), Equals, "[planner:1227]Access denied; you need (at least one of) the SUPER privilege(s) for this operation") + // User has no access to this schema, so the result set is empty. + tk.MustQuery("select count(1) from information_schema.TABLE_STORAGE_STATS where TABLE_SCHEMA = 'information_schema'").Check(testkit.Rows("0")) c.Assert(tk.Se.Auth(&auth.UserIdentity{ Username: "testuser2", Hostname: "localhost", }, nil, nil), Equals, true) - err = tk.QueryToErr("select * from information_schema.TABLE_STORAGE_STATS where TABLE_SCHEMA = 'information_schema'") - c.Assert(err, IsNil) + tk.MustQuery("select count(1) from information_schema.TABLE_STORAGE_STATS where TABLE_SCHEMA = 'mysql'").Check(testkit.Rows("24")) } func (s *testInfoschemaTableSuite) TestSequences(c *C) { From 0a236fd468b8745015054313bd15d6d9f7b1bcfc Mon Sep 17 00:00:00 2001 From: ailinkid <314806019@qq.com> Date: Mon, 19 Jul 2021 17:54:09 +0800 Subject: [PATCH 4/6] address comment Signed-off-by: ailinkid <314806019@qq.com> --- executor/infoschema_reader.go | 2 +- executor/infoschema_reader_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/executor/infoschema_reader.go b/executor/infoschema_reader.go index e9997ef08adae..f17f631407e9d 100644 --- a/executor/infoschema_reader.go +++ b/executor/infoschema_reader.go @@ -1675,7 +1675,7 @@ func (e *tableStorageStatsRetriever) initialize(sctx sessionctx.Context) error { // Privilege checker. checker := func(db, table string) bool { if pm := privilege.GetPrivilegeManager(sctx); pm != nil { - return pm.RequestVerification(sctx.GetSessionVars().ActiveRoles, db, table, "", mysql.SuperPriv) + return pm.RequestVerification(sctx.GetSessionVars().ActiveRoles, db, table, "", mysql.AllPrivMask) } return true } diff --git a/executor/infoschema_reader_test.go b/executor/infoschema_reader_test.go index 39967e10561bf..f6c731174f58e 100644 --- a/executor/infoschema_reader_test.go +++ b/executor/infoschema_reader_test.go @@ -923,7 +923,7 @@ func (s *testInfoschemaClusterTableSuite) TestTableStorageStats(c *C) { defer tk1.MustExec("drop user 'testuser'@'localhost'") defer tk1.MustExec("drop user 'testuser2'@'localhost'") - tk.MustExec("grant super on *.* to 'testuser2'@'localhost'") + tk.MustExec("grant all privileges on *.* to 'testuser2'@'localhost'") c.Assert(tk.Se.Auth(&auth.UserIdentity{ Username: "testuser", Hostname: "localhost", From 8d0dcdca41492a5b27bffd89828148e8f372dbbb Mon Sep 17 00:00:00 2001 From: ailinkid <314806019@qq.com> Date: Mon, 19 Jul 2021 18:03:06 +0800 Subject: [PATCH 5/6] address comment Signed-off-by: ailinkid <314806019@qq.com> --- executor/infoschema_reader_test.go | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/executor/infoschema_reader_test.go b/executor/infoschema_reader_test.go index f6c731174f58e..ca1bb0caaa13e 100644 --- a/executor/infoschema_reader_test.go +++ b/executor/infoschema_reader_test.go @@ -919,9 +919,11 @@ func (s *testInfoschemaClusterTableSuite) TestTableStorageStats(c *C) { // More tests about the privileges. tk.MustExec("create user 'testuser'@'localhost'") tk.MustExec("create user 'testuser2'@'localhost'") + tk.MustExec("create user 'testuser3'@'localhost'") tk1 := testkit.NewTestKit(c, store) defer tk1.MustExec("drop user 'testuser'@'localhost'") defer tk1.MustExec("drop user 'testuser2'@'localhost'") + defer tk1.MustExec("drop user 'testuser3'@'localhost'") tk.MustExec("grant all privileges on *.* to 'testuser2'@'localhost'") c.Assert(tk.Se.Auth(&auth.UserIdentity{ @@ -930,7 +932,7 @@ func (s *testInfoschemaClusterTableSuite) TestTableStorageStats(c *C) { }, nil, nil), Equals, true) // User has no access to this schema, so the result set is empty. - tk.MustQuery("select count(1) from information_schema.TABLE_STORAGE_STATS where TABLE_SCHEMA = 'information_schema'").Check(testkit.Rows("0")) + tk.MustQuery("select count(1) from information_schema.TABLE_STORAGE_STATS where TABLE_SCHEMA = 'mysql'").Check(testkit.Rows("0")) c.Assert(tk.Se.Auth(&auth.UserIdentity{ Username: "testuser2", @@ -938,6 +940,13 @@ func (s *testInfoschemaClusterTableSuite) TestTableStorageStats(c *C) { }, nil, nil), Equals, true) tk.MustQuery("select count(1) from information_schema.TABLE_STORAGE_STATS where TABLE_SCHEMA = 'mysql'").Check(testkit.Rows("24")) + + c.Assert(tk.Se.Auth(&auth.UserIdentity{ + Username: "testuser3", + Hostname: "localhost", + }, nil, nil), Equals, true) + + tk.MustQuery("select count(1) from information_schema.TABLE_STORAGE_STATS where TABLE_SCHEMA = 'mysql'").Check(testkit.Rows("0")) } func (s *testInfoschemaTableSuite) TestSequences(c *C) { From a17fe7813dea66a23c065f5c2ff7fb08a245faca Mon Sep 17 00:00:00 2001 From: ailinkid <314806019@qq.com> Date: Mon, 19 Jul 2021 18:16:13 +0800 Subject: [PATCH 6/6] address comment Signed-off-by: ailinkid <314806019@qq.com> --- executor/infoschema_reader_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/executor/infoschema_reader_test.go b/executor/infoschema_reader_test.go index ca1bb0caaa13e..0dd9bd9620f52 100644 --- a/executor/infoschema_reader_test.go +++ b/executor/infoschema_reader_test.go @@ -926,6 +926,7 @@ func (s *testInfoschemaClusterTableSuite) TestTableStorageStats(c *C) { defer tk1.MustExec("drop user 'testuser3'@'localhost'") tk.MustExec("grant all privileges on *.* to 'testuser2'@'localhost'") + tk.MustExec("grant select on *.* to 'testuser3'@'localhost'") c.Assert(tk.Se.Auth(&auth.UserIdentity{ Username: "testuser", Hostname: "localhost", @@ -946,7 +947,7 @@ func (s *testInfoschemaClusterTableSuite) TestTableStorageStats(c *C) { Hostname: "localhost", }, nil, nil), Equals, true) - tk.MustQuery("select count(1) from information_schema.TABLE_STORAGE_STATS where TABLE_SCHEMA = 'mysql'").Check(testkit.Rows("0")) + tk.MustQuery("select count(1) from information_schema.TABLE_STORAGE_STATS where TABLE_SCHEMA = 'mysql'").Check(testkit.Rows("24")) } func (s *testInfoschemaTableSuite) TestSequences(c *C) {