From 0f3031e3da2c6169e2199be0422c28fb55b0388f Mon Sep 17 00:00:00 2001 From: crazycs Date: Tue, 20 Dec 2022 19:08:55 +0800 Subject: [PATCH] ddl: add privilege check when alter table add foreign key (#40051) close pingcap/tidb#40050 --- ddl/fktest/foreign_key_test.go | 18 ++++++++++++++++++ planner/core/planbuilder.go | 8 ++++++++ 2 files changed, 26 insertions(+) diff --git a/ddl/fktest/foreign_key_test.go b/ddl/fktest/foreign_key_test.go index 911f86f49ec85..13701ad5b610d 100644 --- a/ddl/fktest/foreign_key_test.go +++ b/ddl/fktest/foreign_key_test.go @@ -319,6 +319,24 @@ func TestCreateTableWithForeignKeyPrivilegeCheck(t *testing.T) { tk2.MustExec("create table t4 (a int, foreign key fk(a) references t1(id), foreign key (a) references t3(id));") } +func TestAlterTableWithForeignKeyPrivilegeCheck(t *testing.T) { + store, _ := testkit.CreateMockStoreAndDomain(t) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create user 'u1'@'%' identified by '';") + tk.MustExec("grant create,alter on *.* to 'u1'@'%';") + tk.MustExec("create table t1 (id int key);") + tk2 := testkit.NewTestKit(t, store) + tk2.MustExec("use test") + tk2.Session().Auth(&auth.UserIdentity{Username: "u1", Hostname: "localhost", CurrentUser: true, AuthUsername: "u1", AuthHostname: "%"}, nil, []byte("012345678901234567890")) + tk2.MustExec("create table t2 (a int)") + err := tk2.ExecToErr("alter table t2 add foreign key (a) references t1 (id) on update cascade") + require.Error(t, err) + require.Equal(t, "[planner:1142]REFERENCES command denied to user 'u1'@'%' for table 't1'", err.Error()) + tk.MustExec("grant references on test.t1 to 'u1'@'%';") + tk2.MustExec("alter table t2 add foreign key (a) references t1 (id) on update cascade") +} + func TestRenameTableWithForeignKeyMetaInfo(t *testing.T) { store, dom := testkit.CreateMockStoreAndDomain(t) tk := testkit.NewTestKit(t, store) diff --git a/planner/core/planbuilder.go b/planner/core/planbuilder.go index df7a0d893e4ed..26508814523d2 100644 --- a/planner/core/planbuilder.go +++ b/planner/core/planbuilder.go @@ -4522,6 +4522,14 @@ func (b *PlanBuilder) buildDDL(ctx context.Context, node ast.DDLNode) (Plan, err } b.visitInfo = appendVisitInfo(b.visitInfo, mysql.UpdatePriv, mysql.SystemDB, "stats_extended", "", authErr) + } else if spec.Tp == ast.AlterTableAddConstraint { + if b.ctx.GetSessionVars().User != nil && spec.Constraint != nil && + spec.Constraint.Tp == ast.ConstraintForeignKey && spec.Constraint.Refer != nil { + authErr = ErrTableaccessDenied.GenWithStackByArgs("REFERENCES", b.ctx.GetSessionVars().User.AuthUsername, + b.ctx.GetSessionVars().User.AuthHostname, spec.Constraint.Refer.Table.Name.L) + b.visitInfo = appendVisitInfo(b.visitInfo, mysql.ReferencesPriv, spec.Constraint.Refer.Table.Schema.L, + spec.Constraint.Refer.Table.Name.L, "", authErr) + } } } case *ast.AlterSequenceStmt: