Description:
In the "sig_handler mysql_end(int sig)" function, current MySQL source code reads:
/* write-history */
if (!write_history(histfile_tmp))
my_rename(histfile_tmp, histfile, MYF(MY_WME));
}
MySQL client is writing its history to a temporary location and then moving it into its final destination if writing was successful.
In our use-case, we want to log all SQL history to a specific location. On our system, every logged in user has a read-only environment variable named REAL_USERNAME that is used in a profile script at logon time to set the MYSQL_HISTFILE location to a specific (per user) file.
For security and auditing purposes, these files are stored with the "a" (append-only) flag on them. By using the "write then rename" method to write out the history file, MySQL is not playing nice with our requirement.
The readline library used by MySQL client exposes the "append_history" method that should be used instead.
Thank you.
How to repeat:
=== /etc/profile.d/mysql-history.sh:
MYSQL_HISTFILE=/var/log/.histories/mysql_${REAL_USERNAME}.log
readonly MYSQL_HISTFILE
export MYSQL_HISTFILE
if [ ! -f ${MYSQL_HISTFILE} ]
then
/bin/touch ${MYSQL_HISTFILE}
/bin/chmod o-r ${MYSQL_HISTFILE}
fi
if [ `uname -s` == "Linux" ]
then
/usr/bin/lsattr ${MYSQL_HISTFILE} 2>&1 | egrep -q "^[-]{5}a[-]{7}" > /dev/null
if [ $? == 1 ]
then
sudo /usr/bin/chattr +a ${MYSQL_HISTFILE} > /dev/null 2>&1
fi
fi
=== Launch mysql client, type a few commands, and exit.
=== MySQL client will complain about being denied to rename the file.
=== It would have succeed to append to the history file though.
Suggested fix:
Readline library exposes the "append_history" method that could be used instead of rewriting the whole history (write_history) followed by renaming the file.