[MDEV-12310] openat(<directory>, ...O_EXEC) fails on Illumos / Solaris. Created: 2017-03-20 Updated: 2017-04-28 Resolved: 2017-04-25 |
|
| Status: | Closed |
| Project: | MariaDB Server |
| Component/s: | Server |
| Affects Version/s: | 10.1.22 |
| Fix Version/s: | 5.5.56, 10.1.23, 10.0.31 |
| Type: | Bug | Priority: | Major |
| Reporter: | Andy | Assignee: | Sergei Golubchik |
| Resolution: | Fixed | Votes: | 0 |
| Labels: | None | ||
| Environment: |
OmniOS r151020 - Illumos derivative. |
||
| Issue Links: |
|
||||||||
| Description |
|
MariaDB fails to start with error:
This is due to openat() being called on a directory with the O_EXEC flag set. The man page for openat() on these platforms specifies that:
and returns:
Trace shows that this is occurring:
My MariaDB files are under /data/mariadb/ — the parent directory is being opened with O_EXEC hence the failure. The last working version that I've tried is 10.1.19 |
| Comments |
| Comment by Andy [ 2017-03-20 ] | ||||||||||||||||||||||||||||||||||
|
Tried this quick patch and I can confirm that my server now works. This isn't the proper fix, just a quick test - the semantics of the various operating systems need taking into account.
| ||||||||||||||||||||||||||||||||||
| Comment by Andy [ 2017-03-23 ] | ||||||||||||||||||||||||||||||||||
|
I've done some reading around on this and it seems that O_PATH is Linux specific whereas O_SEARCH/O_EXEC are defined by POSIX. They are almost equivalent except that when opening a symlink with O_NOFOLLOW:
These are the results of running a simple test program using my_open_parent_dir_nosymlinks() on Linux and illumos where the illumos variant is using O_SEARCH: Linux:
illumos (same directory structure):
I don't have access to *BSD at present but I would expect the use of O_EXEC|O_NOFOLLOW to follow POSIX and therefore behave as O_SEARCH does on illumos. Which behaviour is really wanted here? The POSIX result seems better from my limited understanding of the code where this is used (still reading...) [1] https://sourceware.org/ml/libc-alpha/2013-08/msg00016.html | ||||||||||||||||||||||||||||||||||
| Comment by Sergei Golubchik [ 2017-03-23 ] | ||||||||||||||||||||||||||||||||||
|
We don't care what behavior of these two will be, this code doesn't rely on linux specific O_PATH|O_NOFOLLOW. What I need is openat() to fail if there's a symlink involved. On linux it'll open a symlink, and it will fail on the next openat(), because symlink is not a directory, and symlink's fd cannot be used as a first argument for openat(). With POSIX behavior it'll fail right away. Which is just fine too. The logic of my_open_parent_dir_nosymlinks() is as follows — the path argument comes from realpath(), there must be no symlinks in it. If a symlink is found, it means someone replaced a path component with a symlink between realpath() and my_open_parent_dir_nosymlinks() calls, clearly an attempt to exploit a TOCTOU race condition. | ||||||||||||||||||||||||||||||||||
| Comment by Andy [ 2017-03-23 ] | ||||||||||||||||||||||||||||||||||
|
Thanks for the explanation. It would seem that you should use O_SEARCH if available, O_EXEC if not and fallback to O_PATH, although the *BSD behaviour falls into 'undefined' as per POSIX. | ||||||||||||||||||||||||||||||||||
| Comment by Andy [ 2017-03-24 ] | ||||||||||||||||||||||||||||||||||
|
Here's my updated local patch:
|