--- /dev/null
+--- a/scripts/mysqld_safe.sh
++++ b/scripts/mysqld_safe.sh
+@@ -281,8 +281,17 @@
+ --core-file-size=*) core_file_size="$val" ;;
+ --ledir=*) ledir="$val" ;;
+ --malloc-lib=*) set_malloc_lib "$val" ;;
+- --mysqld=*) MYSQLD="$val" ;;
++ --mysqld=*)
++ if [ -z "$pick_args" ]; then
++ log_error "--mysqld option can only be used as command line option, found in config file"
++ exit 1
++ fi
++ MYSQLD="$val" ;;
+ --mysqld-version=*)
++ if [ -z "$pick_args" ]; then
++ log_error "--mysqld-version option can only be used as command line option, found in config file"
++ exit 1
++ fi
+ if test -n "$val"
+ then
+ MYSQLD="mysqld-$val"
+@@ -377,37 +386,23 @@
+ }
+
+
+-mysql_config=
+-get_mysql_config() {
+- if [ -z "$mysql_config" ]; then
+- mysql_config=`echo "$0" | sed 's,/[^/][^/]*$,/mysql_config,'`
+- if [ ! -x "$mysql_config" ]; then
+- log_error "Can not run mysql_config $@ from '$mysql_config'"
+- exit 1
+- fi
+- fi
+-
+- "$mysql_config" "$@"
+-}
+-
+-
+ # set_malloc_lib LIB
+ # - If LIB is empty, do nothing and return
+-# - If LIB is 'tcmalloc', look for tcmalloc shared library in /usr/lib
+-# then pkglibdir. tcmalloc is part of the Google perftools project.
++# - If LIB is 'tcmalloc', look for tcmalloc shared library in $malloc_dirs.
++# tcmalloc is part of the Google perftools project.
+ # - If LIB is an absolute path, assume it is a malloc shared library
+ #
+ # Put LIB in mysqld_ld_preload, which will be added to LD_PRELOAD when
+ # running mysqld. See ld.so for details.
+ set_malloc_lib() {
++ # This list is kept intentionally simple.
++ malloc_dirs="/usr/lib /usr/lib64 /usr/lib/i386-linux-gnu /usr/lib/x86_64-linux-gnu"
+ malloc_lib="$1"
+
+ if [ "$malloc_lib" = tcmalloc ]; then
+ pkglibdir=`get_mysql_config --variable=pkglibdir`
+ malloc_lib=
+- # This list is kept intentionally simple. Simply set --malloc-lib
+- # to a full path if another location is desired.
+- for libdir in /usr/lib "$pkglibdir" "$pkglibdir/mysql"; do
++ for libdir in `echo $malloc_dirs`; do
+ for flavor in _minimal '' _and_profiler _debug; do
+ tmp="$libdir/libtcmalloc$flavor.so"
+ #log_notice "DEBUG: Checking for malloc lib '$tmp'"
+@@ -418,7 +413,7 @@
+ done
+
+ if [ -z "$malloc_lib" ]; then
+- log_error "no shared library for --malloc-lib=tcmalloc found in /usr/lib or $pkglibdir"
++ log_error "no shared library for --malloc-lib=tcmalloc found in $malloc_dirs"
+ exit 1
+ fi
+ fi
+@@ -429,9 +424,21 @@
+ case "$malloc_lib" in
+ /*)
+ if [ ! -r "$malloc_lib" ]; then
+- log_error "--malloc-lib '$malloc_lib' can not be read and will not be used"
++ log_error "--malloc-lib can not be read and will not be used"
+ exit 1
+ fi
++
++ # Restrict to a the list in $malloc_dirs above
++ case "`dirname "$malloc_lib"`" in
++ /usr/lib) ;;
++ /usr/lib64) ;;
++ /usr/lib/i386-linux-gnu) ;;
++ /usr/lib/x86_64-linux-gnu) ;;
++ *)
++ log_error "--malloc-lib must be located in one of the directories: $malloc_dirs"
++ exit 1
++ ;;
++ esac
+ ;;
+ *)
+ log_error "--malloc-lib must be an absolute path or 'tcmalloc'; " \
+@@ -647,7 +654,7 @@
+ log_notice "Logging to '$err_log'."
+ logging=file
+
+- if [ ! -f "$err_log" ]; then # if error log already exists,
++ if [ ! -f "$err_log" -a ! -h "$err_log" ]; then # if error log already exists,
+ touch "$err_log" # we just append. otherwise,
+ chmod "$fmode" "$err_log" # fix the permissions here!
+ fi
+@@ -672,7 +679,7 @@
+ USER_OPTION="--user=$user"
+ fi
+ # Change the err log to the right user, if it is in use
+- if [ $want_syslog -eq 0 ]; then
++ if [ $want_syslog -eq 0 -a ! -h "$err_log" ]; then
+ touch "$err_log"
+ chown $user "$err_log"
+ fi
+@@ -692,9 +699,11 @@
+ mysql_unix_port_dir=`dirname $safe_mysql_unix_port`
+ if [ ! -d $mysql_unix_port_dir ]
+ then
+- mkdir $mysql_unix_port_dir
+- chown $user $mysql_unix_port_dir
+- chmod 755 $mysql_unix_port_dir
++ if [ ! -h $mysql_unix_port_dir ]; then
++ mkdir $mysql_unix_port_dir
++ chown $user $mysql_unix_port_dir
++ chmod 755 $mysql_unix_port_dir
++ fi
+ fi
+
+ # If the user doesn't specify a binary, we assume name "mysqld"
+@@ -806,7 +815,9 @@
+ exit 1
+ fi
+ fi
+- rm -f "$pid_file"
++ if [ ! -h "$pid_file" ]; then
++ rm -f "$pid_file"
++ fi
+ if test -f "$pid_file"
+ then
+ log_error "Fatal error: Can't remove the pid file:
+@@ -861,7 +872,13 @@
+
+ while true
+ do
+- rm -f $safe_mysql_unix_port "$pid_file" # Some extra safety
++ # Some extra safety
++ if [ ! -h "$safe_mysql_unix_port" ]; then
++ rm -f "$safe_mysql_unix_port"
++ fi
++ if [ ! -h "$pid_file" ]; then
++ rm -f "$pid_file"
++ fi
+
+ start_time=`date +%M%S`
+
+@@ -879,7 +896,7 @@
+ eval_log_error "$cmd $wsrep_start_position_opt --wsrep_cluster_address=$url $nohup_redir"
+ fi
+
+- if [ $want_syslog -eq 0 -a ! -f "$err_log" ]; then
++ if [ $want_syslog -eq 0 -a ! -f "$err_log" -a ! -h "$err_log" ]; then
+ touch "$err_log" # hypothetical: log was renamed but not
+ chown $user "$err_log" # flushed yet. we'd recreate it with
+ chmod "$fmode" "$err_log" # wrong owner next time we log, so set
+--- a/sql/log.cc
++++ b/sql/log.cc
+@@ -1,4 +1,4 @@
+-/* Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
++/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+@@ -1496,6 +1496,78 @@
+ }
+
+
++bool is_valid_log_name(const char *name, size_t len)
++{
++ if (len > 3)
++ {
++ const char *tail= name + len - 4;
++ if (my_strcasecmp(system_charset_info, tail, ".ini") == 0 ||
++ my_strcasecmp(system_charset_info, tail, ".cnf") == 0)
++ {
++ return false;
++ }
++ }
++ return true;
++}
++
++
++/**
++ Get the real log file name, and possibly reopen file.
++
++ Use realpath() to get the path with symbolic links
++ expanded. Then, close the file, and reopen the real path using the
++ O_NOFOLLOW flag. This will reject following symbolic links.
++
++ @param file File descriptor.
++ @param log_file_key Key for P_S instrumentation.
++ @param open_flags Flags to use for opening the file.
++ @param opened_file_name Name of the open fd.
++
++ @retval file descriptor to open file with 'real_file_name', or '-1'
++ in case of errors.
++*/
++
++#ifndef _WIN32
++static File mysql_file_real_name_reopen(File file,
++#ifdef HAVE_PSI_INTERFACE
++ PSI_file_key log_file_key,
++#endif
++ int open_flags,
++ const char *opened_file_name)
++{
++ DBUG_ASSERT(file);
++ DBUG_ASSERT(opened_file_name);
++
++ /* Buffer for realpath must have capacity for PATH_MAX. */
++ char real_file_name[PATH_MAX];
++
++ /* Get realpath, validate, open realpath with O_NOFOLLOW. */
++ if (realpath(opened_file_name, real_file_name) == NULL)
++ {
++ (void) mysql_file_close(file, MYF(0));
++ return -1;
++ }
++
++ if (mysql_file_close(file, MYF(0)))
++ return -1;
++
++ if (strlen(real_file_name) > FN_REFLEN)
++ return -1;
++
++ if (!is_valid_log_name(real_file_name, strlen(real_file_name)))
++ {
++ sql_print_error("Invalid log file name after expanding symlinks: '%s'",
++ real_file_name);
++ return -1;
++ }
++
++ return mysql_file_open(log_file_key, real_file_name,
++ open_flags | O_NOFOLLOW,
++ MYF(MY_WME | ME_WAITTANG));
++}
++#endif // _WIN32
++
++
+ /*
+ Open a (new) log file.
+
+@@ -1566,6 +1638,18 @@
+ MYF(MY_WME | ME_WAITTANG))) < 0)
+ goto err;
+
++#ifndef _WIN32
++ /* Reopen and validate path. */
++ if ((log_type_arg == LOG_UNKNOWN || log_type_arg == LOG_NORMAL) &&
++ (file= mysql_file_real_name_reopen(file,
++#ifdef HAVE_PSI_INTERFACE
++ log_file_key,
++#endif
++ open_flags,
++ log_file_name)) < 0)
++ goto err;
++#endif // _WIN32
++
+ if ((pos= mysql_file_tell(file, MYF(MY_WME))) == MY_FILEPOS_ERROR)
+ {
+ if (my_errno == ESPIPE)
+--- a/sql/log.h
++++ b/sql/log.h
+@@ -610,6 +610,16 @@
+
+ char *make_log_name(char *buff, const char *name, const char* log_ext);
+
++/**
++ Check given log name against certain blacklisted names/extensions.
++
++ @param name Log name to check
++ @param len Length of log name
++
++ @returns true if name is valid, false otherwise.
++*/
++bool is_valid_log_name(const char *name, size_t len);
++
+ extern LOGGER logger;
+
+ #endif /* LOG_H */
+--- a/sql/mysqld.cc
++++ b/sql/mysqld.cc
+@@ -4225,11 +4225,22 @@
+ "--general-log-file option, log tables are used. "
+ "To enable logging to files use the --log-output=file option.");
+
+- if (opt_slow_log && opt_slow_logname && !(log_output_options & LOG_FILE)
+- && !(log_output_options & LOG_NONE))
+- sql_print_warning("Although a path was specified for the "
+- "--slow-query-log-file option, log tables are used. "
+- "To enable logging to files use the --log-output=file option.");
++ if (opt_logname &&
++ !is_valid_log_name(opt_logname, strlen(opt_logname)))
++ {
++ sql_print_error("Invalid value for --general_log_file: %s",
++ opt_logname);
++ return 1;
++ }
++
++ if (opt_slow_logname &&
++ !is_valid_log_name(opt_slow_logname, strlen(opt_slow_logname)))
++ {
++ sql_print_error("Invalid value for --slow_query_log_file: %s",
++ opt_slow_logname);
++ return 1;
++ }
++
+
+ if (!opt_logname || !*opt_logname)
+ opt_logname= make_default_log_name(logname_path, ".log");
+--- a/sql/sys_vars.cc
++++ b/sql/sys_vars.cc
+@@ -3686,6 +3686,14 @@
+ if (!var->save_result.string_value.str)
+ return true;
+
++ if (!is_valid_log_name(var->save_result.string_value.str,
++ var->save_result.string_value.length))
++ {
++ my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0),
++ self->name.str, var->save_result.string_value.str);
++ return true;
++ }
++
+ if (var->save_result.string_value.length > FN_REFLEN)
+ { // path is too long
+ my_error(ER_PATH_LENGTH, MYF(0), self->name.str);
+@@ -3732,7 +3740,7 @@
+ return false;
+ }
+ static bool fix_log(char** logname, const char* default_logname,
+- const char*ext, bool enabled, void (*reopen)(char*))
++ const char*ext, bool enabled, bool (*reopen)(char*))
+ {
+ if (!*logname) // SET ... = DEFAULT
+ {
+@@ -3744,16 +3752,17 @@
+ }
+ logger.lock_exclusive();
+ mysql_mutex_unlock(&LOCK_global_system_variables);
++ bool error= false;
+ if (enabled)
+- reopen(*logname);
++ error= reopen(*logname);
+ logger.unlock();
+ mysql_mutex_lock(&LOCK_global_system_variables);
+- return false;
++ return error;
+ }
+-static void reopen_general_log(char* name)
++static bool reopen_general_log(char* name)
+ {
+ logger.get_log_file_handler()->close(0);
+- logger.get_log_file_handler()->open_query_log(name);
++ return logger.get_log_file_handler()->open_query_log(name);
+ }
+ static bool fix_general_log_file(sys_var *self, THD *thd, enum_var_type type)
+ {
+@@ -3766,10 +3775,10 @@
+ IN_FS_CHARSET, DEFAULT(0), NO_MUTEX_GUARD, NOT_IN_BINLOG,
+ ON_CHECK(check_log_path), ON_UPDATE(fix_general_log_file));
+
+-static void reopen_slow_log(char* name)
++static bool reopen_slow_log(char* name)
+ {
+ logger.get_slow_log_file_handler()->close(0);
+- logger.get_slow_log_file_handler()->open_slow_log(name);
++ return logger.get_slow_log_file_handler()->open_slow_log(name);
+ }
+ static bool fix_slow_log_file(sys_var *self, THD *thd, enum_var_type type)
+ {
+--- a/support-files/mysql.server.sh
++++ b/support-files/mysql.server.sh
+@@ -255,11 +255,6 @@
+ if test -r "$basedir/my.cnf"
+ then
+ extra_args="-e $basedir/my.cnf"
+-else
+- if test -r "$datadir/my.cnf"
+- then
+- extra_args="-e $datadir/my.cnf"
+- fi
+ fi
+
+ parse_server_arguments `$print_defaults $extra_args mysqld server mysql_server mysql.server`
+@@ -289,7 +284,7 @@
+ then
+ # Give extra arguments to mysqld with the my.cnf file. This script
+ # may be overwritten at next upgrade.
+- $bindir/mysqld_safe --datadir="$datadir" --pid-file="$mysqld_pid_file_path" $other_args >/dev/null 2>&1 &
++ $bindir/mysqld_safe --datadir="$datadir" --pid-file="$mysqld_pid_file_path" $other_args >/dev/null &
+ wait_for_pid created "$!" "$mysqld_pid_file_path"; return_value=$?
+
+ # Make lock for RedHat / SuSE