From 59dd61704a854ec90f39af0d29002aec072e12cc Mon Sep 17 00:00:00 2001 From: Honza Horak Date: Mon, 31 Jul 2017 18:08:50 +0200 Subject: [PATCH] Remove snippets from mysql-preparep-db-dir.sh that could have security impact Related: CVE-2017-3312 --- community-mysql.spec | 2 ++ mysql-prepare-db-dir.sh | 77 ++++++++++++++++++++++++++--------------- 2 files changed, 52 insertions(+), 27 deletions(-) diff --git a/community-mysql.spec b/community-mysql.spec index cc4ca23..e2df280 100644 --- a/community-mysql.spec +++ b/community-mysql.spec @@ -976,6 +976,8 @@ fi * Fri Aug 04 2017 Honza Horak - 5.7.19-5 - Allow to use MD5 in FIPS mode Related: #1449689 +- Remove snippets from mysql-preparep-db-dir.sh that could have security impact + Related: CVE-2017-3312 * Wed Aug 02 2017 Fedora Release Engineering - 5.7.19-4 - Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild diff --git a/mysql-prepare-db-dir.sh b/mysql-prepare-db-dir.sh index 6b1b5f1..46cf636 100644 --- a/mysql-prepare-db-dir.sh +++ b/mysql-prepare-db-dir.sh @@ -2,6 +2,16 @@ # This script creates the mysql data directory during first service start. # In subsequent starts, it does nothing much. +# +# This script is meant to be run as non-root user either during initscript +# or systemd service execution, before starting the mysqld daemon. +# Running it as root may have some security risks, because it touches files +# that can be symlinks pointing to unexpected locations. +# +# On the other hand, when using non-standard locations for datadir and logfile, +# this script might not be able to create the files and the daemon won't start +# properly. A solution for that is to created the locations for datadir and +# logfile with correct ownership before starting the daemon. source "`dirname ${BASH_SOURCE[0]}`/mysql-scripts-common" @@ -36,36 +46,51 @@ else fi # Set up the errlogfile with appropriate permissions -touch "$errlogfile" -ret=$? -# Provide some advice if the log file cannot be touched -if [ $ret -ne 0 ] ; then - errlogdir=$(dirname $errlogfile) +if [ ! -e "$errlogfile" -a ! -h "$errlogfile" -a x$(dirname "$errlogfile") = "x/var/log" ]; then + case $(basename "$errlogfile") in + mysql*.log|mariadb*.log) install /dev/null -m0640 -o$myuser -g$mygroup "$errlogfile" ;; + *) ;; + esac +else + # Provide some advice if the log file cannot be created by this script + errlogdir=$(dirname "$errlogfile") if ! [ -d "$errlogdir" ] ; then echo "The directory $errlogdir does not exist." - elif [ -f "$errlogfile" ] ; then - echo "The log file $errlogfile cannot be touched, please, fix its permissions." - else - echo "The log file $errlogfile could not be created." + exit 1 + elif [ -e "$errlogfile" -a ! -w "$errlogfile" ] ; then + echo "The log file $errlogfile cannot be written, please, fix its permissions." + echo "The daemon will be run under $myuser:$mygroup" + exit 1 fi - echo "The daemon will be run under $myuser:$mygroup" - exit 1 fi -chown "$myuser:$mygroup" "$errlogfile" -chmod 0640 "$errlogfile" -[ -x /sbin/restorecon ] && /sbin/restorecon "$errlogfile" -# Make the data directory -if [ ! -d "$datadir/mysql" ] ; then - # First, make sure $datadir is there with correct permissions - # (note: if it's not, and we're not root, this'll fail ...) - if [ ! -e "$datadir" -a ! -h "$datadir" ] - then - mkdir -p "$datadir" || exit 1 - fi - chown "$myuser:$mygroup" "$datadir" - chmod 0755 "$datadir" - [ -x /sbin/restorecon ] && /sbin/restorecon "$datadir" + + +export LC_ALL=C + +# Returns content of the specified directory +# If listing files fails, fake-file is returned so which means +# we'll behave like there was some data initialized +# Some files or directories are fine to be there, so those are +# explicitly removed from the listing +# @param datadir +list_datadir () +{ + ( ls -1A "$1" 2>/dev/null || echo "fake-file" ) | grep -v \ + -e '^lost+found$' \ + -e '\.err$' \ + -e '^\.bash_history$' +} + +# Checks whether datadir should be initialized +# @param datadir +should_initialize () +{ + test -z "$(list_datadir "$1")" +} + +# Make the data directory if doesn't exist or empty +if should_initialize "$datadir" ; then # Now create the database echo "Initializing @NICE_PROJECT_NAME@ database" @@ -82,8 +107,6 @@ if [ ! -d "$datadir/mysql" ] ; then fi # upgrade does not need to be run on a fresh datadir echo "@VERSION@" >"$datadir/mysql_upgrade_info" - # In case we're running as root, make sure files are owned properly - chown -R "$myuser:$mygroup" "$datadir" fi exit 0