From 19de52a044e336b3f2acb06d9c20ea3044f538ee Mon Sep 17 00:00:00 2001 From: Sebastian Kemper Date: Mon, 11 May 2020 22:14:54 +0200 Subject: [PATCH 1/4] mariadb: install config files readable for all Until now $(INSTALL_CONF) is used for configuration files that go into /etc/mysql. This commit replaces that with $(INSTALL_DATA). The configuration files are not only parsed by the server, but also by the clients (which can be anybody). This also removes a comment about a cron job from one of the configuration files. There is no cron job. Signed-off-by: Sebastian Kemper --- libs/libmariadb/Makefile | 4 ++-- utils/mariadb-common/Makefile | 4 ++-- utils/mariadb/Makefile | 6 +++--- utils/mariadb/conf/50-server.cnf | 1 - 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/libs/libmariadb/Makefile b/libs/libmariadb/Makefile index db9d259e7..64c849edf 100644 --- a/libs/libmariadb/Makefile +++ b/libs/libmariadb/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=libmariadb PKG_VERSION:=3.1.7 -PKG_RELEASE:=1 +PKG_RELEASE:=2 PKG_SOURCE:=mariadb-connector-c-$(PKG_VERSION)-src.tar.gz PKG_SOURCE_URL := \ @@ -160,7 +160,7 @@ define Package/$(PKG_NAME)/install $(PKG_INSTALL_DIR)$(MARIADB_PLUGIN_DIR)/sha256_password.so \ $(1)$(MARIADB_PLUGIN_DIR) $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/libmariadb.so.$(ABI_VERSION) $(1)/usr/lib - $(INSTALL_CONF) conf/50-client.cnf $(1)$(MARIADB_CONF_DIR)/conf.d + $(INSTALL_DATA) conf/50-client.cnf $(1)$(MARIADB_CONF_DIR)/conf.d endef define BuildPlugin diff --git a/utils/mariadb-common/Makefile b/utils/mariadb-common/Makefile index ce87718d6..ff0962cc4 100644 --- a/utils/mariadb-common/Makefile +++ b/utils/mariadb-common/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=mariadb-common PKG_VERSION:=1.0 -PKG_RELEASE:=1 +PKG_RELEASE:=2 PKG_MAINTAINER:=Sebastian Kemper PKG_LICENSE:=GPL-2.0 @@ -40,7 +40,7 @@ endef define Package/mariadb-common/install $(INSTALL_DIR) $(1)$(CONF_DIR) - $(INSTALL_CONF) conf/my.cnf $(1)$(CONF_DIR) + $(INSTALL_DATA) conf/my.cnf $(1)$(CONF_DIR) endef define Build/Compile diff --git a/utils/mariadb/Makefile b/utils/mariadb/Makefile index 8df97e865..5d5e1629e 100644 --- a/utils/mariadb/Makefile +++ b/utils/mariadb/Makefile @@ -486,7 +486,7 @@ endef define Package/mariadb-client-base/install $(INSTALL_DIR) $(1)$(CONF_DIR)/conf.d - $(INSTALL_CONF) conf/50-mysql-clients.cnf $(1)$(CONF_DIR)/conf.d + $(INSTALL_DATA) conf/50-mysql-clients.cnf $(1)$(CONF_DIR)/conf.d endef define Package/mariadb-client-extra/install @@ -507,8 +507,8 @@ define Package/mariadb-server-base/install $(INSTALL_DIR) $(1)/etc/init.d $(INSTALL_BIN) files/mysqld.init $(1)/etc/init.d/mysqld $(SED) '/^[a-z]/s/^/#/' $(PKG_INSTALL_DIR)$(SHARE_DIR)/wsrep.cnf - $(INSTALL_CONF) $(PKG_INSTALL_DIR)$(SHARE_DIR)/wsrep.cnf $(1)$(CONF_DIR)/conf.d/60-galera.cnf - $(INSTALL_CONF) conf/50-server.cnf $(1)$(CONF_DIR)/conf.d + $(INSTALL_DATA) $(PKG_INSTALL_DIR)$(SHARE_DIR)/wsrep.cnf $(1)$(CONF_DIR)/conf.d/60-galera.cnf + $(INSTALL_DATA) conf/50-server.cnf $(1)$(CONF_DIR)/conf.d $(INSTALL_CONF) files/mysqld.config $(1)/etc/config/mysqld $(INSTALL_DATA) $(PKG_INSTALL_DIR)$(SHARE_DIR)/charsets/* $(1)$(SHARE_DIR)/charsets $(INSTALL_DATA) $(PKG_INSTALL_DIR)$(SHARE_DIR)/english/errmsg.sys $(1)$(SHARE_DIR)/english diff --git a/utils/mariadb/conf/50-server.cnf b/utils/mariadb/conf/50-server.cnf index d478d1f5e..7e0c6d539 100644 --- a/utils/mariadb/conf/50-server.cnf +++ b/utils/mariadb/conf/50-server.cnf @@ -56,7 +56,6 @@ query_cache_size = 16M # # * Logging and Replication # -# Both location gets rotated by the cronjob. # Be aware that this log type is a performance killer. # As of 5.1 you can enable the log at runtime! #general_log_file = /var/log/mysql/mysql.log From b16e9c1e2d73cb06eddbe8cec1429a2e6386ea59 Mon Sep 17 00:00:00 2001 From: Sebastian Kemper Date: Mon, 11 May 2020 22:28:06 +0200 Subject: [PATCH 2/4] mariadb: update auth_pam handling With INSTALL_PAMDIR undefined some items necessary for the auth_pam module aren't built. This adds the define so that configuration and shared object become available. This commit also tightens up the installation of the SUID tool. The directory it is copied into gets created on the build host already with u=rwx,g=rx,o=, so it cannot be accessed on target, except by root. The post-install script then changes group ownership of the directory to the "mariadb" group only if the directory is really a directory and owned by "root:root". Signed-off-by: Sebastian Kemper --- utils/mariadb/Makefile | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/utils/mariadb/Makefile b/utils/mariadb/Makefile index 5d5e1629e..9610b62c3 100644 --- a/utils/mariadb/Makefile +++ b/utils/mariadb/Makefile @@ -366,6 +366,7 @@ CMAKE_OPTIONS += \ -DINSTALL_MANDIR=share/man \ -DINSTALL_MYSQLSHAREDIR=share/mariadb \ -DINSTALL_MYSQLTESTDIR="" \ + -DINSTALL_PAMDIR="/lib/security" \ -DINSTALL_PLUGINDIR=lib/mariadb/plugin \ -DINSTALL_SBINDIR=bin \ -DINSTALL_SCRIPTDIR=bin \ @@ -544,8 +545,18 @@ This package provides the $(1) plugin. $(INSTALL_DIR) $$(1)$(PLUGIN_DIR) $(call Package/mariadb/install/plugin,$$(1),$(1)) ifeq ($(1),auth_pam) - $(CP) $(PKG_INSTALL_DIR)$(PLUGIN_DIR)/auth_pam_tool_dir \ - $$(1)$(PLUGIN_DIR) + $(INSTALL_DIR) -m0750 $$(1)$(PLUGIN_DIR)/auth_pam_tool_dir + $(INSTALL_SUID) \ + $(PKG_INSTALL_DIR)$(PLUGIN_DIR)/auth_pam_tool_dir/auth_pam_tool \ + $$(1)$(PLUGIN_DIR)/auth_pam_tool_dir + $(INSTALL_DIR) $$(1)/etc/security + $(INSTALL_DATA) \ + $(PKG_INSTALL_DIR)/etc/security/user_map.conf \ + $$(1)/etc/security + $(INSTALL_DIR) $$(1)/lib/security + $(INSTALL_DATA) \ + $(PKG_INSTALL_DIR)/lib/security/pam_user_map.so \ + $$(1)/lib/security endif ifeq ($(1),ha_spider) $(INSTALL_DIR) $$(1)$(SHARE_DIR) @@ -556,11 +567,18 @@ endif $$(eval $$(call BuildPackage,mariadb-server-plugin-$(subst _,-,$(1)))) endef +# Directory "auth_pam_tool_dir" is installed with '-m0750' above and +# contains SUID binary "auth_pam_tool". Below post-install script +# changes the group of "auth_pam_tool_dir" to mariadb, so user mariadb +# can access the folder (and the SUID binary). The script only changes +# the group if the directory is currently owned by "root:root". define Package/mariadb-server-plugin-auth-pam/postinst #!/bin/sh if [ -z "$${IPKG_INSTROOT}" ]; then - chown root:mariadb /usr/lib/mariadb/plugin/auth_pam_tool_dir > /dev/null 2>&1 - chmod 0750 /usr/lib/mariadb/plugin/auth_pam_tool_dir > /dev/null 2>&1 + dir="/usr/lib/mariadb/plugin/auth_pam_tool_dir" + if ! [ -L "$$dir" ] && [ -d "$$dir" ] && [ -O "$$dir" ] && [ -G "$$dir" ]; then + chown :mariadb "$$dir" + fi fi exit 0 endef From a61c97203f509d626667f1d031450932ecd650eb Mon Sep 17 00:00:00 2001 From: Sebastian Kemper Date: Mon, 11 May 2020 22:38:42 +0200 Subject: [PATCH 3/4] mariadb: move mysql_upgrade to the client package It's really a client. It connects to the running server as a client, to upgrade the DBs. And it depends on both mysql and mysqlcheck. Signed-off-by: Sebastian Kemper --- utils/mariadb/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/mariadb/Makefile b/utils/mariadb/Makefile index 9610b62c3..f117cf5ba 100644 --- a/utils/mariadb/Makefile +++ b/utils/mariadb/Makefile @@ -116,6 +116,7 @@ plugin-wsrep_info := PLUGIN_WSREP_INFO MARIADB_CLIENT := \ mysql \ + mysql_upgrade \ mysqlcheck MARIADB_CLIENT_EXTRA := \ @@ -133,7 +134,6 @@ MARIADB_SERVER := \ innochecksum \ my_print_defaults \ mysql_install_db \ - mysql_upgrade \ mysqld MARIADB_SERVER_EXTRA := \ From fa6ea0b137df501d742ec053b0af4861f69b03df Mon Sep 17 00:00:00 2001 From: Sebastian Kemper Date: Mon, 11 May 2020 22:55:24 +0200 Subject: [PATCH 4/4] mariadb: switch init to mysqld_safe and mysqladmin mysqld_safe is the recommended way to start the server on non-systemd systems ([1]). For instance, it has a crash detection with auto-restart function, can update ulimits, setup core files, set the niceness of the server etc. It looks like it could also be helpful when trying to set up clusters. It's maintained upstream and adding it means we don't need to add these features into our init script. mysqld_safe is a script itself, so it's added to conffiles in case users want to edit it. It can't be run under procd, so the init script is converted to a normal System V type. To stop the server and to reload the privileges tables mysqladmin is used. To that end mysqladmin is moved into the server package. While changing the init script, the Debian init script was used for ideas. It wasn't copied verbatim and adapted a bit here and there. Thanks to whoever wrote it! This commit removes the support for starting the service as a user other than "mariadb". This makes the init script simpler. If anybody wants to play around with the user then it's up to them to fix the permissions. [1] https://mariadb.com/kb/en/mysqld_safe/ Signed-off-by: Sebastian Kemper --- utils/mariadb/Makefile | 12 +- utils/mariadb/files/mysqld.config | 6 +- utils/mariadb/files/mysqld.init | 182 +++++++++--------- .../190-replace-hostname-in-mysqld_safe.patch | 29 +++ 4 files changed, 126 insertions(+), 103 deletions(-) create mode 100644 utils/mariadb/patches/190-replace-hostname-in-mysqld_safe.patch diff --git a/utils/mariadb/Makefile b/utils/mariadb/Makefile index f117cf5ba..1d54b84a5 100644 --- a/utils/mariadb/Makefile +++ b/utils/mariadb/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=mariadb PKG_VERSION:=10.4.12 -PKG_RELEASE:=2 +PKG_RELEASE:=3 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL := \ @@ -123,7 +123,6 @@ MARIADB_CLIENT_EXTRA := \ mysql_find_rows \ mysql_waitpid \ mysqlaccess \ - mysqladmin \ mysqldump \ mysqlimport \ mysqlshow \ @@ -134,7 +133,9 @@ MARIADB_SERVER := \ innochecksum \ my_print_defaults \ mysql_install_db \ - mysqld + mysqladmin \ + mysqld \ + mysqld_safe MARIADB_SERVER_EXTRA := \ aria_chk \ @@ -156,6 +157,7 @@ MARIADB_SERVER_EXTRA := \ mysql_tzinfo_to_sql \ mysqlbinlog \ mysqld_multi \ + mysqld_safe_helper \ mysqldumpslow \ mysqlhotcopy \ perror \ @@ -272,6 +274,10 @@ define Package/mariadb-server PROVIDES:=mysql-server endef +define Package/mariadb-server/conffiles +/usr/bin/mysqld_safe +endef + define Package/mariadb-server/description $(call Package/mariadb/description/Default) diff --git a/utils/mariadb/files/mysqld.config b/utils/mariadb/files/mysqld.config index 1bfcde6c5..1e866e1ec 100644 --- a/utils/mariadb/files/mysqld.config +++ b/utils/mariadb/files/mysqld.config @@ -1,7 +1,5 @@ config mysqld 'general' - option enabled '0' - option log_stderr '1' - option log_stdout '1' - option options '' + option enabled '0' # 0 - disabled, 1 - enabled + option options '--syslog' # Options passed to mysqld_safe diff --git a/utils/mariadb/files/mysqld.init b/utils/mariadb/files/mysqld.init index 284e00aaa..a1e6a44b1 100644 --- a/utils/mariadb/files/mysqld.init +++ b/utils/mariadb/files/mysqld.init @@ -4,48 +4,71 @@ START=95 STOP=10 -USE_PROCD=1 - -#PROCD_DEBUG=1 - NAME=mysqld LOGGER="/usr/bin/logger -p user.err -s -t $NAME --" -COMMAND=/usr/bin/$NAME + +MYSQLADMIN=/usr/bin/mysqladmin +MYSQLD=/usr/bin/$NAME +MYSQLDSAFE=/usr/bin/mysqld_safe + +# mysqladmin likes to read /root/.my.cnf which could cause issues. +export HOME=/etc/mysql + +# Safeguard (relative paths, core dumps...) +cd / mysqld_get_param() { - $COMMAND --print-defaults \ + $MYSQLD --print-defaults \ | tr " " "\n" \ | grep -- "--$1" \ | tail -n 1 \ | cut -d= -f2 } -start_service() { - local conf=/etc/mysql/my.cnf - local dir - local user - local group - - local logfile - - local datadir - local logdir=/var/log/mysql - local rundir=/var/run/mysqld - local tmpdir - - local enabled - local log_stderr - local log_stdout - local options - - local hint="please fix your server configuration in /etc/mysql/" - - if [ ! -x $COMMAND ]; then - $LOGGER $COMMAND is missing - exit 1 +# Checks if a server is running and accessible. +# +# check_alive insists on a pingable server +# check_dead also fails if there is a lost mysqld in the process list +# +# Usage: boolean mysqld_status [check_alive|check_dead] +mysqld_status() { + if $MYSQLADMIN ping >/dev/null 2>&1; then + ping_alive=1 + else + ping_alive=0 fi + ps_alive=0 + pidfile=$(mysqld_get_param pid-file) + if [ -f "$pidfile" ] && kill -0 $(cat "$pidfile") >/dev/null 2>&1; then + ps_alive=1 + fi + + if { [ "$1" = check_alive ] && [ $ping_alive = 1 ]; } || \ + { [ "$1" = check_dead ] && [ $ping_alive = 0 ] \ + && [ $ps_alive = 0 ]; } + then + return 0 # EXIT_SUCCESS + else + return 1 # EXIT_FAILURE + fi +} + +start() { + conf=/etc/mysql/my.cnf + logdir=/var/log/mysql + rundir=/var/run/mysqld + + hint="please fix your server configuration in /etc/mysql/" + + for i in $MYSQLD $MYSQLADMIN $MYSQLDSAFE; do + if [ ! -x $i ]; then + $LOGGER $i is missing + exit 1 + fi + done + if [ ! -r $conf ]; then $LOGGER $conf cannot be read exit 1 @@ -59,15 +82,10 @@ start_service() { exit 1 fi - config_get_bool log_stderr general log_stderr 1 - config_get_bool log_stdout general log_stdout 1 - config_get options general options datadir=$(mysqld_get_param datadir) - logfile=$(mysqld_get_param general_log_file) tmpdir=$(mysqld_get_param tmpdir) - user=$(mysqld_get_param user) if [ -z "$datadir" ]; then $LOGGER datadir is not set @@ -81,76 +99,48 @@ start_service() { exit 1 fi - if [ -z "$user" ]; then - $LOGGER user is not set - $LOGGER $hint - exit 1 - fi - - user_exists "$user" || { - $LOGGER user \""$user"\" does not exist - $LOGGER $hint - exit 1 - } - - group=$(id -g -n "$user") - - group_exists "$group" || { - $LOGGER group \""$group"\" does not exist - $LOGGER user \""$user"\" not configured correctly - exit 1 - } - - [ -n "$logfile" ] && logdir=$(dirname "$logfile") - - # do not touch directories that already exist - # posix shell does not support arrays, hence using awk - awk \ - -v user="$user" \ - -v group="$group" \ - -v a="$datadir" \ - -v b="$logdir" \ - -v c="$rundir" \ - -v d="$tmpdir" \ - ' - BEGIN { - dir[0]=a - dir[1]=b - dir[2]=c - dir[3]=d - for (x in dir) { - if (system("test ! -e \"" dir[x] "\"" )) { - delete dir[x] - } - } - for (x in dir) { - system("mkdir -p \"" dir[x] "\"" ) - system("chmod 750 \"" dir[x] "\"" ) - system("chown \"" user "\":\"" group "\" \"" dir[x] "\"" ) - } - } - ' - if [ ! -f "$datadir/mysql/tables_priv.MAD" ]; then - local args="--force" - local basedir=$(mysqld_get_param basedir) + args="--force" + basedir=$(mysqld_get_param basedir) [ -n "$basedir" ] && args="$args --basedir=$basedir" $LOGGER Cannot detect privileges table. You might need to run - $LOGGER \'mysql_install_db $args\' + $LOGGER \'mysql_install_db "$args"\' $LOGGER to initialize the system tables. exit 1 fi - procd_open_instance + # Start daemon + if mysqld_status check_alive; then + $LOGGER already running + else + for i in $logdir $rundir; do + opts="-m 0750" + if ! [ -e $i ]; then + # $rundir needs to be accessible for + # clients + if [ $i = $rundir ]; then + opts= + fi + mkdir -p $opts $i + [ -d $i ] && chown mariadb:mariadb $i + fi + done - procd_set_param command $COMMAND $options - - # forward stderr to logd - procd_set_param stderr $log_stderr - # same for stdout - procd_set_param stdout $log_stdout - - procd_close_instance + $MYSQLDSAFE $options >/dev/null 2>&1 & + fi } +stop() { + if ! mysqld_status check_dead; then + $MYSQLADMIN shutdown + fi +} + +reload() { + if mysqld_status check_alive; then + $MYSQLADMIN reload + else + $LOGGER not running + fi +} diff --git a/utils/mariadb/patches/190-replace-hostname-in-mysqld_safe.patch b/utils/mariadb/patches/190-replace-hostname-in-mysqld_safe.patch new file mode 100644 index 000000000..6371628e0 --- /dev/null +++ b/utils/mariadb/patches/190-replace-hostname-in-mysqld_safe.patch @@ -0,0 +1,29 @@ +--- a/scripts/mysqld_safe.sh ++++ b/scripts/mysqld_safe.sh +@@ -242,7 +242,7 @@ wsrep_recover_position() { + return 1 + fi + +- local wr_pidfile="$DATADIR/"`@HOSTNAME@`"-recover.pid" ++ local wr_pidfile="$DATADIR/"$(uci get 'system.@system[0].hostname')"-recover.pid" + + local wr_options="--disable-log-error --pid-file='$wr_pidfile'" + +@@ -673,7 +673,7 @@ then + * ) err_log="$DATADIR/$err_log" ;; + esac + else +- err_log=$DATADIR/`@HOSTNAME@`.err ++ err_log=$DATADIR/$(uci get 'system.@system[0].hostname').err + fi + fi + +@@ -752,7 +752,7 @@ fi + + if test -z "$pid_file" + then +- pid_file="`@HOSTNAME@`.pid" ++ pid_file="$(uci get 'system.@system[0].hostname').pid" + fi + # MariaDB wants pid file without datadir + append_arg_to_args "--pid-file=$pid_file"