diff --git a/mysql-test/main/mysqld--help.result b/mysql-test/main/mysqld--help.result index 9da52106f91..0f944f238f8 100644 --- a/mysql-test/main/mysqld--help.result +++ b/mysql-test/main/mysqld--help.result @@ -1038,6 +1038,14 @@ The following specify which files/extra groups are read (specified before remain --secure-file-priv=name Limit LOAD DATA, SELECT ... OUTFILE, and LOAD_FILE() to files within specified directory + --secure-timestamp=name + Restricts direct setting of a session timestamp. Possible + levels are: YES - timestamp cannot deviate from the + system clock, REPLICATION - replication thread can adjust + timestamp to match the master's, SUPER - a user with this + privilege and a replication thread can adjust timestamp, + NO - historical behavior, anyone can modify session + timestamp --server-id=# Uniquely identifies the server instance in the community of replication partners --session-track-schema @@ -1616,6 +1624,7 @@ rpl-semi-sync-slave-trace-level 32 safe-user-create FALSE secure-auth TRUE secure-file-priv (No default value) +secure-timestamp NO server-id 1 session-track-schema TRUE session-track-state-change FALSE diff --git a/mysql-test/suite/sys_vars/inc/secure_timestamp_func.inc b/mysql-test/suite/sys_vars/inc/secure_timestamp_func.inc new file mode 100644 index 00000000000..8bc3e42df59 --- /dev/null +++ b/mysql-test/suite/sys_vars/inc/secure_timestamp_func.inc @@ -0,0 +1,49 @@ +# +# MDEV-15923 option to control who can set session @@timestamp +# +source include/have_binlog_format_statement.inc; +source include/master-slave.inc; + +connection slave; +select @@secure_timestamp; + +### SUPER +disable_abort_on_error; +set timestamp=1234567890.101112; +enable_abort_on_error; +select if(now(6) > 20100101, 'READONLY', 'EDITABLE') as 'SUPER'; + +### non-privileged user +create user foo@127.0.0.1; +connect con2,127.0.0.1,foo,,test,$SLAVE_MYPORT; +disable_abort_on_error; +set timestamp=1234567890.101112; +enable_abort_on_error; +select if(now(6) > 20100101, 'READONLY', 'EDITABLE') as 'non-privileged'; +disconnect con2; +connection slave; +drop user foo@127.0.0.1; + +### replication +connection master; +set time_zone='+00:00'; +set timestamp=1234567890.101112; +select @@timestamp, now(6); + +create table t1 (b varchar(20), a timestamp(6) default current_timestamp(6)); +insert t1 (b) values ('replicated'); +sync_slave_with_master; +create trigger t1rbr before insert on t1 for each row set new.a=now(6); +set @@global.slave_run_triggers_for_rbr= yes; +binlog 'LQfqWg8BAAAA/AAAAAABAAABAAQAMTAuMy42LU1hcmlhREItZGVidWctbG9nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtB+paEzgNAAgAEgAEBAQEEgAA5AAEGggAAAAICAgCAAAACgoKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEEwQADQgICAoKCgFlBcaR'; +binlog '0gKWSRMBAAAAMQAAAHQDAAAAAB8AAAAAAAEABHRlc3QAAnQxAAIPEQMUAAYBQFUzwA==0gKWSRcBAAAAMAAAAKQDAAAAAB8AAAAAAAEAAv/8BmJpbmxvZ0mWAtIBivg3mwo+'; +set @@global.slave_run_triggers_for_rbr= default; +select b, if(a > 20100101, 'READONLY', 'EDITABLE') as 'REPLICATION' from t1; +connection master; +#set binlog_format=row; +#insert t1 (b) values ('binlog'); +#let datadir=`select @@datadir`; +#exec $MYSQL_BINLOG $datadir/master-bin.000001; +drop table t1; + +source include/rpl_end.inc; diff --git a/mysql-test/suite/sys_vars/r/secure_timestamp_no.result b/mysql-test/suite/sys_vars/r/secure_timestamp_no.result new file mode 100644 index 00000000000..34eeb083c28 --- /dev/null +++ b/mysql-test/suite/sys_vars/r/secure_timestamp_no.result @@ -0,0 +1,40 @@ +include/master-slave.inc +[connection master] +connection slave; +select @@secure_timestamp; +@@secure_timestamp +NO +set timestamp=1234567890.101112; +select if(now(6) > 20100101, 'READONLY', 'EDITABLE') as 'SUPER'; +SUPER +EDITABLE +create user foo@127.0.0.1; +connect con2,127.0.0.1,foo,,test,$SLAVE_MYPORT; +set timestamp=1234567890.101112; +select if(now(6) > 20100101, 'READONLY', 'EDITABLE') as 'non-privileged'; +non-privileged +EDITABLE +disconnect con2; +connection slave; +drop user foo@127.0.0.1; +connection master; +set time_zone='+00:00'; +set timestamp=1234567890.101112; +select @@timestamp, now(6); +@@timestamp now(6) +1234567890.101112 2009-02-13 23:31:30.101112 +create table t1 (b varchar(20), a timestamp(6) default current_timestamp(6)); +insert t1 (b) values ('replicated'); +connection slave; +create trigger t1rbr before insert on t1 for each row set new.a=now(6); +set @@global.slave_run_triggers_for_rbr= yes; +binlog 'LQfqWg8BAAAA/AAAAAABAAABAAQAMTAuMy42LU1hcmlhREItZGVidWctbG9nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtB+paEzgNAAgAEgAEBAQEEgAA5AAEGggAAAAICAgCAAAACgoKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEEwQADQgICAoKCgFlBcaR'; +binlog '0gKWSRMBAAAAMQAAAHQDAAAAAB8AAAAAAAEABHRlc3QAAnQxAAIPEQMUAAYBQFUzwA==0gKWSRcBAAAAMAAAAKQDAAAAAB8AAAAAAAEAAv/8BmJpbmxvZ0mWAtIBivg3mwo+'; +set @@global.slave_run_triggers_for_rbr= default; +select b, if(a > 20100101, 'READONLY', 'EDITABLE') as 'REPLICATION' from t1; +b REPLICATION +replicated EDITABLE +binlog EDITABLE +connection master; +drop table t1; +include/rpl_end.inc diff --git a/mysql-test/suite/sys_vars/r/secure_timestamp_rpl.result b/mysql-test/suite/sys_vars/r/secure_timestamp_rpl.result new file mode 100644 index 00000000000..e2d79745a46 --- /dev/null +++ b/mysql-test/suite/sys_vars/r/secure_timestamp_rpl.result @@ -0,0 +1,42 @@ +include/master-slave.inc +[connection master] +connection slave; +select @@secure_timestamp; +@@secure_timestamp +REPLICATION +set timestamp=1234567890.101112; +ERROR HY000: The MariaDB server is running with the --secure-timestamp=REPLICATION option so it cannot execute this statement +select if(now(6) > 20100101, 'READONLY', 'EDITABLE') as 'SUPER'; +SUPER +READONLY +create user foo@127.0.0.1; +connect con2,127.0.0.1,foo,,test,$SLAVE_MYPORT; +set timestamp=1234567890.101112; +ERROR HY000: The MariaDB server is running with the --secure-timestamp=REPLICATION option so it cannot execute this statement +select if(now(6) > 20100101, 'READONLY', 'EDITABLE') as 'non-privileged'; +non-privileged +READONLY +disconnect con2; +connection slave; +drop user foo@127.0.0.1; +connection master; +set time_zone='+00:00'; +set timestamp=1234567890.101112; +select @@timestamp, now(6); +@@timestamp now(6) +1234567890.101112 2009-02-13 23:31:30.101112 +create table t1 (b varchar(20), a timestamp(6) default current_timestamp(6)); +insert t1 (b) values ('replicated'); +connection slave; +create trigger t1rbr before insert on t1 for each row set new.a=now(6); +set @@global.slave_run_triggers_for_rbr= yes; +binlog 'LQfqWg8BAAAA/AAAAAABAAABAAQAMTAuMy42LU1hcmlhREItZGVidWctbG9nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtB+paEzgNAAgAEgAEBAQEEgAA5AAEGggAAAAICAgCAAAACgoKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEEwQADQgICAoKCgFlBcaR'; +binlog '0gKWSRMBAAAAMQAAAHQDAAAAAB8AAAAAAAEABHRlc3QAAnQxAAIPEQMUAAYBQFUzwA==0gKWSRcBAAAAMAAAAKQDAAAAAB8AAAAAAAEAAv/8BmJpbmxvZ0mWAtIBivg3mwo+'; +set @@global.slave_run_triggers_for_rbr= default; +select b, if(a > 20100101, 'READONLY', 'EDITABLE') as 'REPLICATION' from t1; +b REPLICATION +replicated EDITABLE +binlog READONLY +connection master; +drop table t1; +include/rpl_end.inc diff --git a/mysql-test/suite/sys_vars/r/secure_timestamp_super.result b/mysql-test/suite/sys_vars/r/secure_timestamp_super.result new file mode 100644 index 00000000000..6fbb5e5fbf0 --- /dev/null +++ b/mysql-test/suite/sys_vars/r/secure_timestamp_super.result @@ -0,0 +1,41 @@ +include/master-slave.inc +[connection master] +connection slave; +select @@secure_timestamp; +@@secure_timestamp +SUPER +set timestamp=1234567890.101112; +select if(now(6) > 20100101, 'READONLY', 'EDITABLE') as 'SUPER'; +SUPER +EDITABLE +create user foo@127.0.0.1; +connect con2,127.0.0.1,foo,,test,$SLAVE_MYPORT; +set timestamp=1234567890.101112; +ERROR 42000: Access denied; you need (at least one of) the SUPER privilege(s) for this operation +select if(now(6) > 20100101, 'READONLY', 'EDITABLE') as 'non-privileged'; +non-privileged +READONLY +disconnect con2; +connection slave; +drop user foo@127.0.0.1; +connection master; +set time_zone='+00:00'; +set timestamp=1234567890.101112; +select @@timestamp, now(6); +@@timestamp now(6) +1234567890.101112 2009-02-13 23:31:30.101112 +create table t1 (b varchar(20), a timestamp(6) default current_timestamp(6)); +insert t1 (b) values ('replicated'); +connection slave; +create trigger t1rbr before insert on t1 for each row set new.a=now(6); +set @@global.slave_run_triggers_for_rbr= yes; +binlog 'LQfqWg8BAAAA/AAAAAABAAABAAQAMTAuMy42LU1hcmlhREItZGVidWctbG9nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtB+paEzgNAAgAEgAEBAQEEgAA5AAEGggAAAAICAgCAAAACgoKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEEwQADQgICAoKCgFlBcaR'; +binlog '0gKWSRMBAAAAMQAAAHQDAAAAAB8AAAAAAAEABHRlc3QAAnQxAAIPEQMUAAYBQFUzwA==0gKWSRcBAAAAMAAAAKQDAAAAAB8AAAAAAAEAAv/8BmJpbmxvZ0mWAtIBivg3mwo+'; +set @@global.slave_run_triggers_for_rbr= default; +select b, if(a > 20100101, 'READONLY', 'EDITABLE') as 'REPLICATION' from t1; +b REPLICATION +replicated EDITABLE +binlog EDITABLE +connection master; +drop table t1; +include/rpl_end.inc diff --git a/mysql-test/suite/sys_vars/r/secure_timestamp_yes.result b/mysql-test/suite/sys_vars/r/secure_timestamp_yes.result new file mode 100644 index 00000000000..d317cfc30b2 --- /dev/null +++ b/mysql-test/suite/sys_vars/r/secure_timestamp_yes.result @@ -0,0 +1,42 @@ +include/master-slave.inc +[connection master] +connection slave; +select @@secure_timestamp; +@@secure_timestamp +YES +set timestamp=1234567890.101112; +ERROR HY000: The MariaDB server is running with the --secure-timestamp=YES option so it cannot execute this statement +select if(now(6) > 20100101, 'READONLY', 'EDITABLE') as 'SUPER'; +SUPER +READONLY +create user foo@127.0.0.1; +connect con2,127.0.0.1,foo,,test,$SLAVE_MYPORT; +set timestamp=1234567890.101112; +ERROR HY000: The MariaDB server is running with the --secure-timestamp=YES option so it cannot execute this statement +select if(now(6) > 20100101, 'READONLY', 'EDITABLE') as 'non-privileged'; +non-privileged +READONLY +disconnect con2; +connection slave; +drop user foo@127.0.0.1; +connection master; +set time_zone='+00:00'; +set timestamp=1234567890.101112; +select @@timestamp, now(6); +@@timestamp now(6) +1234567890.101112 2009-02-13 23:31:30.101112 +create table t1 (b varchar(20), a timestamp(6) default current_timestamp(6)); +insert t1 (b) values ('replicated'); +connection slave; +create trigger t1rbr before insert on t1 for each row set new.a=now(6); +set @@global.slave_run_triggers_for_rbr= yes; +binlog 'LQfqWg8BAAAA/AAAAAABAAABAAQAMTAuMy42LU1hcmlhREItZGVidWctbG9nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtB+paEzgNAAgAEgAEBAQEEgAA5AAEGggAAAAICAgCAAAACgoKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEEwQADQgICAoKCgFlBcaR'; +binlog '0gKWSRMBAAAAMQAAAHQDAAAAAB8AAAAAAAEABHRlc3QAAnQxAAIPEQMUAAYBQFUzwA==0gKWSRcBAAAAMAAAAKQDAAAAAB8AAAAAAAEAAv/8BmJpbmxvZ0mWAtIBivg3mwo+'; +set @@global.slave_run_triggers_for_rbr= default; +select b, if(a > 20100101, 'READONLY', 'EDITABLE') as 'REPLICATION' from t1; +b REPLICATION +replicated READONLY +binlog READONLY +connection master; +drop table t1; +include/rpl_end.inc diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result index 89b7b5c97cf..432c9f4c114 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_embedded.result @@ -3540,6 +3540,20 @@ NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST NULL READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME SECURE_TIMESTAMP +SESSION_VALUE NULL +GLOBAL_VALUE NO +GLOBAL_VALUE_ORIGIN COMPILE-TIME +DEFAULT_VALUE NO +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE ENUM +VARIABLE_COMMENT Restricts direct setting of a session timestamp. Possible levels are: YES - timestamp cannot deviate from the system clock, REPLICATION - replication thread can adjust timestamp to match the master's, SUPER - a user with this privilege and a replication thread can adjust timestamp, NO - historical behavior, anyone can modify session timestamp +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST NO,SUPER,REPLICATION,YES +READ_ONLY YES +COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SERVER_ID SESSION_VALUE 1 GLOBAL_VALUE 1 diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result index 3246d00d20e..cdc2f81e088 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result @@ -4156,6 +4156,20 @@ NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST NULL READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME SECURE_TIMESTAMP +SESSION_VALUE NULL +GLOBAL_VALUE NO +GLOBAL_VALUE_ORIGIN COMPILE-TIME +DEFAULT_VALUE NO +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE ENUM +VARIABLE_COMMENT Restricts direct setting of a session timestamp. Possible levels are: YES - timestamp cannot deviate from the system clock, REPLICATION - replication thread can adjust timestamp to match the master's, SUPER - a user with this privilege and a replication thread can adjust timestamp, NO - historical behavior, anyone can modify session timestamp +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST NO,SUPER,REPLICATION,YES +READ_ONLY YES +COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SERVER_ID SESSION_VALUE 1 GLOBAL_VALUE 1 diff --git a/mysql-test/suite/sys_vars/t/secure_timestamp_no-slave.opt b/mysql-test/suite/sys_vars/t/secure_timestamp_no-slave.opt new file mode 100644 index 00000000000..4c9000c0ebe --- /dev/null +++ b/mysql-test/suite/sys_vars/t/secure_timestamp_no-slave.opt @@ -0,0 +1 @@ +--secure-timestamp=no diff --git a/mysql-test/suite/sys_vars/t/secure_timestamp_no.test b/mysql-test/suite/sys_vars/t/secure_timestamp_no.test new file mode 100644 index 00000000000..8871666abd0 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/secure_timestamp_no.test @@ -0,0 +1,4 @@ +# +# MDEV-15923 option to control who can set session @@timestamp +# +source inc/secure_timestamp_func.inc; diff --git a/mysql-test/suite/sys_vars/t/secure_timestamp_rpl-slave.opt b/mysql-test/suite/sys_vars/t/secure_timestamp_rpl-slave.opt new file mode 100644 index 00000000000..13754861d0f --- /dev/null +++ b/mysql-test/suite/sys_vars/t/secure_timestamp_rpl-slave.opt @@ -0,0 +1 @@ +--secure-timestamp=replication diff --git a/mysql-test/suite/sys_vars/t/secure_timestamp_rpl.test b/mysql-test/suite/sys_vars/t/secure_timestamp_rpl.test new file mode 100644 index 00000000000..8871666abd0 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/secure_timestamp_rpl.test @@ -0,0 +1,4 @@ +# +# MDEV-15923 option to control who can set session @@timestamp +# +source inc/secure_timestamp_func.inc; diff --git a/mysql-test/suite/sys_vars/t/secure_timestamp_super-slave.opt b/mysql-test/suite/sys_vars/t/secure_timestamp_super-slave.opt new file mode 100644 index 00000000000..f747ec6c0c9 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/secure_timestamp_super-slave.opt @@ -0,0 +1 @@ +--secure-timestamp=super diff --git a/mysql-test/suite/sys_vars/t/secure_timestamp_super.test b/mysql-test/suite/sys_vars/t/secure_timestamp_super.test new file mode 100644 index 00000000000..8871666abd0 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/secure_timestamp_super.test @@ -0,0 +1,4 @@ +# +# MDEV-15923 option to control who can set session @@timestamp +# +source inc/secure_timestamp_func.inc; diff --git a/mysql-test/suite/sys_vars/t/secure_timestamp_yes-slave.opt b/mysql-test/suite/sys_vars/t/secure_timestamp_yes-slave.opt new file mode 100644 index 00000000000..a74d68957ef --- /dev/null +++ b/mysql-test/suite/sys_vars/t/secure_timestamp_yes-slave.opt @@ -0,0 +1 @@ +--secure-timestamp=yes diff --git a/mysql-test/suite/sys_vars/t/secure_timestamp_yes.test b/mysql-test/suite/sys_vars/t/secure_timestamp_yes.test new file mode 100644 index 00000000000..8871666abd0 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/secure_timestamp_yes.test @@ -0,0 +1,4 @@ +# +# MDEV-15923 option to control who can set session @@timestamp +# +source inc/secure_timestamp_func.inc; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index af817894cf4..28b5d3bd0ad 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -534,6 +534,7 @@ ulonglong slave_skipped_errors; ulong feature_files_opened_with_delayed_keys= 0, feature_check_constraint= 0; ulonglong denied_connections; my_decimal decimal_zero; +long opt_secure_timestamp; /* Maximum length of parameter value which can be set through diff --git a/sql/mysqld.h b/sql/mysqld.h index 3b2a887d764..2e829e81a0d 100644 --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -302,6 +302,9 @@ extern my_bool encrypt_binlog; extern my_bool encrypt_tmp_disk_tables, encrypt_tmp_files; extern ulong encryption_algorithm; extern const char *encryption_algorithm_names[]; +extern long opt_secure_timestamp; + +enum secure_timestamp { SECTIME_NO, SECTIME_SUPER, SECTIME_REPL, SECTIME_YES }; #ifdef HAVE_PSI_INTERFACE #ifdef HAVE_MMAP diff --git a/sql/sql_class.h b/sql/sql_class.h index 74d00b96ca2..6241e80052c 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -3522,15 +3522,20 @@ public: */ inline void set_time(my_time_t t, ulong sec_part) { - start_time= t; - start_time_sec_part= sec_part > TIME_MAX_SECOND_PART ? 0 : sec_part; - user_time.val= hrtime_from_time(start_time) + start_time_sec_part; - if (slave_thread) - set_system_time_from_user_time(sec_part <= TIME_MAX_SECOND_PART); - else // BINLOG command - set_system_time(); - PSI_CALL_set_thread_start_time(start_time); - start_utime= utime_after_lock= microsecond_interval_timer(); + if (opt_secure_timestamp > (slave_thread ? SECTIME_REPL : SECTIME_SUPER)) + set_time(); // note that BINLOG itself requires SUPER + else + { + start_time= t; + start_time_sec_part= sec_part > TIME_MAX_SECOND_PART ? 0 : sec_part; + user_time.val= hrtime_from_time(start_time) + start_time_sec_part; + if (slave_thread) + set_system_time_from_user_time(sec_part <= TIME_MAX_SECOND_PART); + else // BINLOG command + set_system_time(); + PSI_CALL_set_thread_start_time(start_time); + start_utime= utime_after_lock= microsecond_interval_timer(); + } } void set_time_after_lock() { diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 97ab8de16a1..cf6fd14f8e6 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -4212,11 +4212,24 @@ static Sys_var_harows Sys_select_limit( SESSION_VAR(select_limit), NO_CMD_LINE, VALID_RANGE(0, HA_POS_ERROR), DEFAULT(HA_POS_ERROR), BLOCK_SIZE(1)); +static const char *secure_timestamp_levels[]= {"NO", "SUPER", "REPLICATION", "YES", 0}; +static bool check_timestamp(sys_var *self, THD *thd, set_var *var) +{ + if (opt_secure_timestamp == SECTIME_NO) + return false; + if (opt_secure_timestamp == SECTIME_SUPER) + return check_has_super(self, thd, var); + char buf[1024]; + strxnmov(buf, sizeof(buf), "--secure-timestamp=", + secure_timestamp_levels[opt_secure_timestamp], NULL); + my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), buf); + return true; +} static Sys_var_timestamp Sys_timestamp( "timestamp", "Set the time for this client", sys_var::ONLY_SESSION, NO_CMD_LINE, VALID_RANGE(0, TIMESTAMP_MAX_VALUE), - NO_MUTEX_GUARD, IN_BINLOG); + NO_MUTEX_GUARD, IN_BINLOG, ON_CHECK(check_timestamp)); static bool update_last_insert_id(THD *thd, set_var *var) { @@ -6052,3 +6065,13 @@ static Sys_var_uint Sys_in_subquery_conversion_threshold( SESSION_VAR(in_subquery_conversion_threshold), CMD_LINE(OPT_ARG), VALID_RANGE(0, UINT_MAX), DEFAULT(IN_SUBQUERY_CONVERSION_THRESHOLD), BLOCK_SIZE(1)); #endif + +static Sys_var_enum Sys_secure_timestamp( + "secure_timestamp", "Restricts direct setting of a session " + "timestamp. Possible levels are: YES - timestamp cannot deviate from " + "the system clock, REPLICATION - replication thread can adjust " + "timestamp to match the master's, SUPER - a user with this " + "privilege and a replication thread can adjust timestamp, NO - " + "historical behavior, anyone can modify session timestamp", + READ_ONLY GLOBAL_VAR(opt_secure_timestamp), CMD_LINE(REQUIRED_ARG), + secure_timestamp_levels, DEFAULT(SECTIME_NO)); diff --git a/sql/sys_vars.ic b/sql/sys_vars.ic index c9ada2d33c2..498204deb92 100644 --- a/sql/sys_vars.ic +++ b/sql/sys_vars.ic @@ -1892,10 +1892,11 @@ public: const char *comment, int flag_args, CMD_LINE getopt, double min_val, double max_val, - PolyLock *lock, enum binlog_status_enum binlog_status_arg) + PolyLock *lock, enum binlog_status_enum binlog_status_arg, + on_check_function on_check_func=0) : Sys_var_double(name_arg, comment, flag_args, 0, sizeof(double), getopt, min_val, - max_val, 0, lock, binlog_status_arg) + max_val, 0, lock, binlog_status_arg, on_check_func) { SYSVAR_ASSERT(scope() == ONLY_SESSION); SYSVAR_ASSERT(getopt.id < 0); // NO_CMD_LINE, because the offset is fake