-
-
Notifications
You must be signed in to change notification settings - Fork 2k
MDEV-6733: Add DEFINER support to ALTER PROCEDURE #5060
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| # ALTER PROCEDURE DEFINER | ||
| CREATE USER 'user1'@'localhost'; | ||
| GRANT ALL PRIVILEGES ON test.* TO 'user1'@'localhost'; | ||
| connect con1, localhost, user1, , test; | ||
| CREATE PROCEDURE p1() SELECT 1; | ||
| ALTER PROCEDURE p1 DEFINER = 'user1'@'localhost'; | ||
| ALTER PROCEDURE p1 DEFINER = 'root'@'localhost'; | ||
| ERROR 42000: Access denied; you need (at least one of) the SUPER, SET USER privilege(s) for this operation | ||
| connection default; | ||
| ALTER PROCEDURE p1 DEFINER = 'root'@'localhost'; | ||
| SELECT definer FROM mysql.proc WHERE name = 'p1'; | ||
| definer | ||
| root@localhost | ||
| DROP PROCEDURE p1; | ||
| DROP USER 'user1'@'localhost'; | ||
| Warnings: | ||
| Note 4227 Dropped users 'user1'@'localhost' have active connections. Use KILL CONNECTION if they should not be used anymore. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| --echo # ALTER PROCEDURE DEFINER | ||
|
|
||
| CREATE USER 'user1'@'localhost'; | ||
| GRANT ALL PRIVILEGES ON test.* TO 'user1'@'localhost'; | ||
|
|
||
| --connect (con1, localhost, user1, , test) | ||
| CREATE PROCEDURE p1() SELECT 1; | ||
|
|
||
| ALTER PROCEDURE p1 DEFINER = 'user1'@'localhost'; | ||
|
|
||
| --error ER_SPECIFIC_ACCESS_DENIED_ERROR | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please provide a design document someplace: what is supposed to work and what isn't. This should ideally be into the MDEV itself. |
||
| ALTER PROCEDURE p1 DEFINER = 'root'@'localhost'; | ||
|
|
||
| --connection default | ||
| ALTER PROCEDURE p1 DEFINER = 'root'@'localhost'; | ||
|
|
||
| SELECT definer FROM mysql.proc WHERE name = 'p1'; | ||
|
|
||
| DROP PROCEDURE p1; | ||
| DROP USER 'user1'@'localhost'; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1711,7 +1711,7 @@ Sp_handler::sp_drop_routine(THD *thd, | |
|
|
||
| int | ||
| Sp_handler::sp_update_routine(THD *thd, const Database_qualified_name *name, | ||
| const st_sp_chistics *chistics) const | ||
| const st_sp_chistics *chistics, LEX_USER *definer) const | ||
| { | ||
| TABLE *table; | ||
| int ret; | ||
|
|
@@ -1768,6 +1768,20 @@ Sp_handler::sp_update_routine(THD *thd, const Database_qualified_name *name, | |
| if (chistics->agg_type != DEFAULT_AGGREGATE) | ||
| table->field[MYSQL_PROC_FIELD_AGGREGATE]-> | ||
| store((longlong)chistics->agg_type, TRUE); | ||
| if (definer) | ||
| { | ||
| if (definer->user.str && definer->host.str) | ||
| { | ||
| char definer_str[USER_HOST_BUFF_SIZE]; | ||
| uint definer_len= strxmov(definer_str, definer->user.str, "@", | ||
| definer->host.str, NullS) - | ||
| definer_str; | ||
| table->field[MYSQL_PROC_FIELD_DEFINER]->set_notnull(); | ||
| table->field[MYSQL_PROC_FIELD_DEFINER]->store(definer_str, definer_len, | ||
| system_charset_info); | ||
|
Comment on lines
+1775
to
+1781
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using a fixed-size buffer of String definer_str;
definer_str.append(definer->user.str, definer->user.length);
definer_str.append('@');
definer_str.append(definer->host.str, definer->host.length);
table->field[MYSQL_PROC_FIELD_DEFINER]->set_notnull();
table->field[MYSQL_PROC_FIELD_DEFINER]->store(definer_str.ptr(),
definer_str.length(),
system_charset_info); |
||
| sp_cache_invalidate(); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The call to |
||
| } | ||
| } | ||
| if ((ret= table->file->ha_update_row(table->record[1],table->record[0])) && | ||
| ret != HA_ERR_RECORD_IS_THE_SAME) | ||
| ret= SP_WRITE_ROW_FAILED; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6448,14 +6448,21 @@ alter_routine(THD *thd, LEX *lex) | |
| if (check_routine_access(thd, ALTER_PROC_ACL, &lex->spname->m_db, | ||
| &lex->spname->m_name, sph, 0)) | ||
| return 1; | ||
| if (lex->definer) | ||
| { | ||
| if ((!lex_string_eq(&lex->definer->user, thd->security_ctx->priv_user, strlen(thd->security_ctx->priv_user)) || | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe this is a bad design decision: only allow changing definers for your procedures. The proper (ideal) way to do this is at multiple levels (IMHO):
Anyways, it should be privilege based. |
||
| !lex_string_eq(&lex->definer->host, thd->security_ctx->priv_host, strlen(thd->security_ctx->priv_host))) && | ||
| check_global_access(thd, SET_USER_ACL | SUPER_ACL)) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. never re-use privileges like that. This turns them into roles. |
||
| return 1; | ||
| } | ||
|
Comment on lines
+6451
to
+6457
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Instead of manually implementing the privilege check, you should use the existing if (lex->definer && check_definer_access(thd, lex->definer))
return 1; |
||
| /* | ||
| Note that if you implement the capability of ALTER FUNCTION to | ||
| alter the body of the function, this command should be made to | ||
| follow the restrictions that log-bin-trust-function-creators=0 | ||
| already puts on CREATE FUNCTION. | ||
| */ | ||
| /* Conditionally writes to binlog */ | ||
| sp_result= sph->sp_update_routine(thd, lex->spname, &lex->sp_chistics); | ||
| sp_result= sph->sp_update_routine(thd, lex->spname, &lex->sp_chistics, lex->definer); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is where tests fail with a crash in buildbot: e.g.: |
||
| switch (sp_result) { | ||
| case SP_OK: | ||
| my_ok(thd); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1777,7 +1777,7 @@ rule: | |
|
|
||
| %type <lex_user> user grant_user grant_role user_or_role current_role | ||
| admin_option_for_role user_maybe_role role_name | ||
| user_name | ||
| user_name sp_a_chistic | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Declaring |
||
|
|
||
| %type <user_auth> opt_auth_str auth_expression auth_token | ||
| text_or_password | ||
|
|
@@ -3395,7 +3395,12 @@ sp_name: | |
|
|
||
| sp_a_chistics: | ||
| /* Empty */ {} | ||
| | sp_a_chistics sp_chistic {} | ||
| | sp_a_chistics sp_a_chistic {} | ||
| ; | ||
|
|
||
| sp_a_chistic: | ||
| sp_chistic {} | ||
| | definer {} | ||
| ; | ||
|
|
||
| sp_c_chistics: | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We customarily start with a prefix comment like
--echo MDEV-1234 this mdev does so and so