[MDEV-4068] rpm scriptlet chown command dangerous Created: 2013-01-20 Updated: 2013-03-07 Resolved: 2013-03-07 |
|
| Status: | Closed |
| Project: | MariaDB Server |
| Component/s: | None |
| Affects Version/s: | 10.0.0, 5.5.28a |
| Fix Version/s: | 10.0.2, 5.5.30 |
| Type: | Bug | Priority: | Critical |
| Reporter: | Kevin Quinn | Assignee: | Sergei Golubchik |
| Resolution: | Fixed | Votes: | 0 |
| Labels: | packaging | ||
| Environment: |
CentOS 5 , and CentOS 6 |
||
| Description |
|
If a machine where MariaDB server RPM is installed contains my.cnf with values that are not valid for the current version of the server, the installation process fails to detect correct values of basedir and datadir, ends up with datadir=/ and changes ownership of the entire system to mysql:mysql. For details about the fragment of the post-install script see the original description below. It can especially easily happen on a downgrade, but crossgrade and even upgrade can cause it too, if the problematic value was either deprecated and removed, or just became invalid due to different server build options or configuration (e.g. different character sets). Reproducible on MariaDB 5.5.28a and 10.0.0. Installation of 5.1-5.3 doesn't seem to have the disastrous effect, and neither does MySQL 5.5.29. My suggestion is to check whether mysqld help produced any results for basedir and datadir, and if not, abort further process since the installation obviously doesn't work as expected. Please also consider a request for an additional sanity check in the comment. ====================== Original descriptionThe MariaDB-Server RPM appears to contain a flawed method of determining mysql 'datadir' path. This is in the post-install scriptlet packaged in the RPM for both the centos5 and centos6 versions, and both 64bit and 32bit packages. Relevant part of the post-installation shell scriptlet:
In my testing, the initial shell array, $mysql_dirs is empty when that command is run. Thus mysql_datadir="/" This is dangerous because the subsequent use of the variable is:
On the centos6 server, moving /etc/my.cnf to /etc/my.cnf.TMP ahead of time, makes the initial population of $mysql_dirs[@] to be correct. (not sure why yet) On the centos5 server it's the same deal, however, moving the my.cnf causes the array to populate, but it still produces incorrect path values:
I don't have a suggestion at the moment for how to fix, although I believe there must be a better way to find the mysql datadir than the current implementation. I hope this is the right place to submit this bug. I marked it critical because chowning the entire filesystem mysql:mysql recursively is fairly catasthropic. |
| Comments |
| Comment by Kevin Quinn [ 2013-01-20 ] | |
|
Never used Jira, sorry about the code format above. This is what that should have looked like: The MariaDB-Server RPM appears to contain a flawed method of determining mysql 'datadir' path. This is in the post-install scriptlet packaged in the RPM for both the centos5 and centos6 versions, and both 64bit and 32bit packages. Relevant part of the post-installation shell scriptlet: mysql_dirs=(`/usr/sbin/mysqld --verbose --help 2>/dev/null|sed -ne 's/^(basedir|datadir)[[:space:]](.)$/\2/p'`)
In my testing, the initial shell array, $mysql_dirs is empty when that command is run. Thus mysql_datadir="/" This is dangerous because the subsequent use of the variable is: chown -R mysql:mysql $mysql_datadir On the centos6 server, moving /etc/my.cnf to /etc/my.cnf.TMP ahead of time, makes the initial population of $mysql_dirs[@] to be correct. (not sure why yet) On the centos5 server it's the same deal, however, moving the my.cnf causes the array to populate, but it still produces incorrect path values: mysql_dirs[0] => . I don't have a suggestion at the moment for how to fix, although I believe there must be a better way to find the mysql datadir than the current implementation. I hope this is the right place to submit this bug. I marked it critical because chowning the entire filesystem mysql:mysql recursively is fairly catasthropic. | |
| Comment by Elena Stepanova [ 2013-01-20 ] | |
|
No worries, we can always fix the formatting. But just so you know, your guess about
was right, but it only works in the description, not in comments. | |
| Comment by Elena Stepanova [ 2013-01-20 ] | |
|
Hi Kevin, Could you please attach my.cnf which causes the described problem? Thanks. | |
| Comment by Sergei Golubchik [ 2013-01-20 ] | |
|
Also, run, manually, "mysqld --help --verbose" and see the values of the datadir and basedir variables. | |
| Comment by Elena Stepanova [ 2013-01-20 ] | |
|
I figured a scenario when the whole story adds up and is still realistic. The only way for this command to return an EMPTY result is that /usr/sbin/mysqld fails to print help at all, otherwise there would have been something, even if it's only empty lines. For the test I had set character-set-server to an invalid value on purpose, but it could have been unintentional: character sets do change, and a previous server might have had one which the new server doesn't. So I think it cannot be considered just misconfiguration. I suppose a simple way to fix this is to check that the command above returned results; if it didn't, something definitely went wrong, and installation should be aborted. Reproducible on MariaDB 5.5.28a and 10.0.0. | |
| Comment by Kevin Quinn [ 2013-01-20 ] | |
|
Hello, You are quick to respond. I appreciate it. It appears you are correct. When I did my cursory testing I left in place the redirection of STDERR to the bitbucket, so I didn't notice this: root@server # /usr/sbin/mysqld --verbose --help So obviously it sends nothing to stdout, and simply produces an error message if my.cnf has errant values ( or likely a number of other scenarios could cause this ) I agree on aborting installation on failure to produce results to STDOUT from the mysqld --verbose --help command. Perhaps also, an additional paranoid sanity check on the value of mysql_dir . If it's "/", abort. Here's why: On this centos5 box, observe the output when my.cnf is moved: mv /etc/my.cnf /etc/my.cnf.tmp So perhaps incidentally, we would end up with the same result I believe. Not sure if it would be chown -R mysql:mysql "/" or chown -R mysql:mysql "/.", but I believe the results would be the same. Note that the my.cnf on this centos5 machine I simply copied from the centos6 machine for testing. It has all kinds of errant values because it was for a mysql running innodb tables, and probably different versions of mysql, etc.. If it would help, I can produce the output of whatever you would like from both machines, but I can't do that now. I will have access to both of them later. If you provide a list of everything you would like me to run, I can. I'm not sure if it matters, but this is a cpanel box, as is the centos6 one. Let me know what you need from me. | |
| Comment by Kevin Quinn [ 2013-01-20 ] | |
|
Actually, I will not be able to run commands on the original centos6 machine. But I can run anything on the centos5 box. Regardless, let me know what, if anything I can do to help. Thanks again for looking into this! | |
| Comment by Elena Stepanova [ 2013-01-20 ] | |
|
The story with centos5 is different. After you move out the problematic my.cnf, the initial problem is gone, and there are apparently other my.cnf files which affect the outcome. Also, there is some contradiction. Earlier you said that you were getting mysql_dirs[0] => . Which means mysqld returned basedir . and datadir as / The first pair of values is completely weird, I can't think of another way to get it but set them manually in the config file. Then, if the values were set manually, I don't think there is much we can – or even should – do. After all, you do it as root, so you get what you want. If the values were produced automatically, we should find out how it happened at the first place. So, for starters, please check the default locations of my.cnf on that box. One of them probably has a file where these values set explicitly. If you find the "guilty" file, and you suspect it was generated automatically, please attach it. Or better still, please create another bug report and attach it there, since the problem is different. Thanks. | |
| Comment by Jean Weisbuch [ 2013-01-20 ] | |
|
Adding a simple test to check that both values are not empty or only containing a . or a / would still be safer even if it should never happen in normal usecases. | |
| Comment by Elena Stepanova [ 2013-01-20 ] | |
|
Also, this error is strange and again makes the story unclear Unknown suffix 'A' used for variable 'concurrent-insert' (value 'ALWAYS') Could you please double-check which version you are trying to install, and which version ends up in /usr/sbin/mysqld ? It's a 5.1-based version error, 5.5.28 should have no problem with ALWAYS. | |
| Comment by Kevin Quinn [ 2013-01-21 ] | |
|
Elena, You are correct on the contradiction. I was trying to make things simple when i posted: mysql_dirs[0] => . IS INCORRECT / Inverted. My fault. Sorry, I was trying to make things clear, and I switched the two. Here is the command and output: root@server # /usr/sbin/mysqld --verbose --help | egrep '(basedir|datadir)' 130120 20:42:30 [ERROR] Aborting -b, --basedir=name Path to installation directory. All paths are usually So basedir == / I'm sorry for the confusion. Please tell me exactly what to run on this centos5 machine and I will provide exact output. -kevin | |
| Comment by Elena Stepanova [ 2013-01-21 ] | |
|
I suggest
Thanks. | |
| Comment by Kevin Quinn [ 2013-01-21 ] | |
|
root@server # ls -la /etc/my.cnf.* root@server # mysql --help | grep cnf | |
| Comment by Elena Stepanova [ 2013-01-21 ] | |
|
Did you have a chance to check the version of /usr/sbin/mysqld as mentioned earlier? | |
| Comment by Kevin Quinn [ 2013-01-21 ] | |
|
Elena, root@server # /usr/sbin/mysqld --version Hm. I've somehow let myself get confused about the datadir / basedir issue, which appears to have nothing to do with the RPM. Sorry for causing confusion about the 2nd issue. If so, it would appear there is only one issue: Checking if: /usr/sbin/mysqld --verbose --help returns error and if so abort installation. I believe you already addressed this, so I suppose this can be wrapped up. Thanks | |
| Comment by Michael Widenius [ 2013-02-11 ] | |
|
One root of the problem is that the script is using mysqld --help --verbose to get the options. The reason is that this may fail if there are some wrong commands/variables in my.cnf A better way is to use 'my_print_defaults mysqld mariadb server client-server'. This is what scripts like mysqld_safe uses. We could of course also add a check that the values are reasonable.
| |
| Comment by Sergei Golubchik [ 2013-03-06 ] | |
|
elenst so shall I push that? | |
| Comment by Elena Stepanova [ 2013-03-06 ] | |
|
Yes, please. I'll test an RPM from buildbot when it's baked. (I tried to imitate buildbot by patching manually and building my own RPM on CentOS 5, same way buildbot does, using "cmake . -DBUILD_CONFIG=mysql_release -DRPM=centos5", but it turned out not that easy as it requires a higher version of cmake than CentOS 5 has) | |
| Comment by Elena Stepanova [ 2013-03-06 ] | |
|
Checked a manual RPM build on Fedora 17 64-bit, made from 5.5-serg revno 3685, source package prepared by buildbot (could not use an RPM baked by buildbot since it's not in archives [yet]). 1) Installation of the package with broken my.cnf didn't cause the previous disaster. It still fails, of course (DB initialization doesn't work since mysqld cannot start), but the problem is fixable after installation by re-running mysql_install_db manually. One thing that comes to mind with these tests is that it's probably not right when yum installation exits with code 0 even although something went very wrong on the way; so, it's easy to miss the problem, and then it's very confusing when the fresh MariaDB installation turns out to be broken. | |
| Comment by Sergei Golubchik [ 2013-03-07 ] | |
|
pushed in 5.5 |