summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergei Golubchik <serg@mariadb.org>2017-02-20 19:53:12 +0100
committerSergei Golubchik <serg@mariadb.org>2017-02-27 12:35:10 +0100
commit955f2f036d6252b90e2bffcec521dd4a7db0a30a (patch)
tree9ebe926cffe1e80ff852ee85da7ae42b18de7c64
parent93cb0246b8c883c4f5010468892986fa1d5ba379 (diff)
downloadmariadb-git-955f2f036d6252b90e2bffcec521dd4a7db0a30a.tar.gz
race-condition safe implementation of test_if_data_home_dir()
don't realpath() twice
-rw-r--r--sql/mysqld.cc2
-rw-r--r--sql/sql_parse.cc44
-rw-r--r--sql/sql_parse.h3
3 files changed, 34 insertions, 15 deletions
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 2e8a62ecb12..3d2de3126ff 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -7267,7 +7267,7 @@ static int mysql_init_variables(void)
mysql_home[0]= pidfile_name[0]= log_error_file[0]= 0;
#if defined(HAVE_REALPATH) && !defined(HAVE_valgrind) && !defined(HAVE_BROKEN_REALPATH)
/* We can only test for sub paths if my_symlink.c is using realpath */
- mysys_test_invalid_symlink= test_if_data_home_dir;
+ mysys_test_invalid_symlink= path_starts_from_data_home_dir;
#endif
opt_log= opt_slow_log= 0;
opt_bin_log= opt_bin_log_used= 0;
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 32784f6432a..c3170d04304 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -7697,26 +7697,20 @@ bool check_ident_length(LEX_STRING *ident)
Check if path does not contain mysql data home directory
SYNOPSIS
- test_if_data_home_dir()
- dir directory
+ path_starts_from_data_home_dir()
+ dir directory, with all symlinks resolved
RETURN VALUES
0 ok
1 error ; Given path contains data directory
*/
-C_MODE_START
+extern "C" {
-int test_if_data_home_dir(const char *dir)
+int path_starts_from_data_home_dir(const char *path)
{
- char path[FN_REFLEN];
- int dir_len;
- DBUG_ENTER("test_if_data_home_dir");
+ int dir_len= strlen(path);
+ DBUG_ENTER("path_starts_from_data_home_dir");
- if (!dir)
- DBUG_RETURN(0);
-
- (void) fn_format(path, dir, "", "", MY_RETURN_REAL_PATH);
- dir_len= strlen(path);
if (mysql_unpacked_real_data_home_len<= dir_len)
{
if (dir_len > mysql_unpacked_real_data_home_len &&
@@ -7744,7 +7738,31 @@ int test_if_data_home_dir(const char *dir)
DBUG_RETURN(0);
}
-C_MODE_END
+}
+
+/*
+ Check if path does not contain mysql data home directory
+
+ SYNOPSIS
+ test_if_data_home_dir()
+ dir directory
+
+ RETURN VALUES
+ 0 ok
+ 1 error ; Given path contains data directory
+*/
+
+int test_if_data_home_dir(const char *dir)
+{
+ char path[FN_REFLEN];
+ DBUG_ENTER("test_if_data_home_dir");
+
+ if (!dir)
+ DBUG_RETURN(0);
+
+ (void) fn_format(path, dir, "", "", MY_RETURN_REAL_PATH);
+ DBUG_RETURN(path_starts_from_data_home_dir(path));
+}
/**
diff --git a/sql/sql_parse.h b/sql/sql_parse.h
index 66a8f6efc7d..c5ea38706c4 100644
--- a/sql/sql_parse.h
+++ b/sql/sql_parse.h
@@ -33,7 +33,8 @@ enum enum_mysql_completiontype {
COMMIT_RELEASE=-1, COMMIT=0, COMMIT_AND_CHAIN=6
};
-extern "C" int test_if_data_home_dir(const char *dir);
+extern "C" int path_starts_from_data_home_dir(const char *dir);
+int test_if_data_home_dir(const char *dir);
bool multi_update_precheck(THD *thd, TABLE_LIST *tables);
bool multi_delete_precheck(THD *thd, TABLE_LIST *tables);