infoschema: improve the security vunerability of TABLE_CONSTRAINTS infoschema (#14037)
This commit is contained in:
@ -1706,10 +1706,15 @@ const (
|
||||
)
|
||||
|
||||
// dataForTableConstraints constructs data for table information_schema.constraints.See https://dev.mysql.com/doc/refman/5.7/en/table-constraints-table.html
|
||||
func dataForTableConstraints(schemas []*model.DBInfo) [][]types.Datum {
|
||||
func dataForTableConstraints(ctx sessionctx.Context, schemas []*model.DBInfo) [][]types.Datum {
|
||||
checker := privilege.GetPrivilegeManager(ctx)
|
||||
var rows [][]types.Datum
|
||||
for _, schema := range schemas {
|
||||
for _, tbl := range schema.Tables {
|
||||
if checker != nil && !checker.RequestVerification(ctx.GetSessionVars().ActiveRoles, schema.Name.L, tbl.Name.L, "", mysql.AllPrivMask) {
|
||||
continue
|
||||
}
|
||||
|
||||
if tbl.PKIsHandle {
|
||||
record := types.MakeDatums(
|
||||
catalogVal, // CONSTRAINT_CATALOG
|
||||
@ -2346,7 +2351,7 @@ func (it *infoschemaTable) getRows(ctx sessionctx.Context, cols []*table.Column)
|
||||
case tableSessionVar:
|
||||
fullRows, err = dataForSessionVar(ctx)
|
||||
case tableConstraints:
|
||||
fullRows = dataForTableConstraints(dbs)
|
||||
fullRows = dataForTableConstraints(ctx, dbs)
|
||||
case tableFiles:
|
||||
case tableProfiling:
|
||||
if v, ok := ctx.GetSessionVars().GetSystemVar("profiling"); ok && variable.TiDBOptOn(v) {
|
||||
|
||||
@ -445,6 +445,25 @@ func (s *testTableSuite) TestSomeTables(c *C) {
|
||||
tk.MustQuery("select * from information_schema.SESSION_VARIABLES where VARIABLE_NAME='tidb_retry_limit';").Check(testkit.Rows("tidb_retry_limit 10"))
|
||||
tk.MustQuery("select * from information_schema.ENGINES;").Check(testkit.Rows("InnoDB DEFAULT Supports transactions, row-level locking, and foreign keys YES YES YES"))
|
||||
tk.MustQuery("select * from information_schema.TABLE_CONSTRAINTS where TABLE_NAME='gc_delete_range';").Check(testkit.Rows("def mysql delete_range_index mysql gc_delete_range UNIQUE"))
|
||||
|
||||
//test the privilege of new user for information_schema.table_constraints
|
||||
tk.MustExec("create user constraints_tester")
|
||||
constraintsTester := testkit.NewTestKit(c, s.store)
|
||||
constraintsTester.MustExec("use information_schema")
|
||||
c.Assert(constraintsTester.Se.Auth(&auth.UserIdentity{
|
||||
Username: "constraints_tester",
|
||||
Hostname: "127.0.0.1",
|
||||
}, nil, nil), IsTrue)
|
||||
constraintsTester.MustQuery("select * from information_schema.TABLE_CONSTRAINTS;").Check([][]interface{}{})
|
||||
|
||||
//test the privilege of user with privilege of mysql.gc_delete_range for information_schema.table_constraints
|
||||
tk.MustExec("CREATE ROLE r_gc_delete_range ;")
|
||||
tk.MustExec("GRANT ALL PRIVILEGES ON mysql.gc_delete_range TO r_gc_delete_range;")
|
||||
tk.MustExec("GRANT r_gc_delete_range TO constraints_tester;")
|
||||
constraintsTester.MustExec("set role r_gc_delete_range")
|
||||
c.Assert(len(constraintsTester.MustQuery("select * from information_schema.TABLE_CONSTRAINTS where TABLE_NAME='gc_delete_range';").Rows()), Greater, 0)
|
||||
constraintsTester.MustQuery("select * from information_schema.TABLE_CONSTRAINTS where TABLE_NAME='tables_priv';").Check([][]interface{}{})
|
||||
|
||||
tk.MustQuery("select * from information_schema.KEY_COLUMN_USAGE where TABLE_NAME='stats_meta' and COLUMN_NAME='table_id';").Check(
|
||||
testkit.Rows("def mysql tbl def mysql stats_meta table_id 1 <nil> <nil> <nil> <nil>"))
|
||||
tk.MustQuery("select * from information_schema.SCHEMATA where schema_name='mysql';").Check(
|
||||
|
||||
Reference in New Issue
Block a user