Bug #21723 Should be able to dump core after setuid() under Linux
Submitted: 18 Aug 2006 16:37 Modified: 14 May 2018 13:11
Reporter: Dean Ellis Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server: Options Severity:S4 (Feature request)
Version:5.0, 5.7.11 OS:Linux (Linux)
Assigned to: CPU Architecture:Any
Tags: bfsm_2007_05_31, Contribution

[18 Aug 2006 16:37] Dean Ellis
Description:
In many cases, binaries can no longer dump core after calling setuid().  Under Linux it is possible to re-enable this with a system call.

How to repeat:
n/a

Suggested fix:
===== mysqld.cc 1.565 vs edited =====
--- 1.565/sql/mysqld.cc 2006-08-18 11:34:13 -05:00
+++ edited/mysqld.cc    2006-08-18 11:32:44 -05:00
@@ -64,6 +64,10 @@
 #define ONE_THREAD
 #endif
 
+#ifdef __linux__
+#include <sys/prctl.h>
+#endif
+
 #ifdef HAVE_purify
 #define IF_PURIFY(A,B) (A)
 #else
@@ -1362,6 +1366,10 @@
     sql_perror("setuid");
     unireg_abort(1);
   }
+#ifdef __linux__
+  /* inform kernel that process is dumpable */
+  prctl(PR_SET_DUMPABLE,1,0,0,0);
+#endif /* __linux__ */
 #endif
 }
[18 Aug 2006 20:38] Domas Mituzas
This seems to be more a bug than feature request - --core-file functionality is broken if dumpable flag is not reset after setuid().
[5 Sep 2006 13:42] Sergei Golubchik
I'd rather use HAVE_SYS_PRCTL_H or HAVE_PRCTL instead of __linux__
[5 Sep 2006 13:54] Dean Ellis
Sure.  Should probably also move this to the OPT_WANT_CORE test or to write_core() or similar (only do it if core-file option was specified).
[7 Sep 2006 9:20] Michal Marek
The patch attached to bug#21361 contains a configure check and calls prctl()
only of --core-file is given: http://bugs.mysql.com/file.php?id=4063
[1 Jun 2007 14:34] Sergei Golubchik
no need for a special configure check, it's enough to add sys/prctl.h to AC_CHECK_HEADERS() rule in configure.in. The code becomes:

+#ifdef HAVE_SYS_PRCTL_H
+#include <sys/prctl.h>
+#endif
...
+#ifdef PR_SET_DUMPABLE
+  if (test_flags & TEST_CORE_ON_SIGNAL)
+  {
+    prctl(PR_SET_DUMPABLE, 1);
+  }
+#endif

otherwise ok
[14 Jun 2007 18:25] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/28795

ChangeSet@1.2479, 2007-06-14 14:24:59-04:00, cmiller@zippy.cornsilk.net +2 -0
  Bug#21723: Should be able to dump core after setuid() under Linux
  
  In many cases, binaries can no longer dump core after calling setuid().
  
  Where the PR_SET_DUMPABLE macro is set, use the prctl() system call 
  to tell the kernel that it's allowed to dump the core of the server.
[16 Jun 2007 4:50] Bugs System
Pushed into 5.0.44
[16 Jun 2007 4:51] Bugs System
Pushed into 5.1.20-beta
[18 Jun 2007 15:58] Paul DuBois
Noted in 5.0.44, 5.1.20 changelogs.

Linux binaries were unable to dump core after executing a setuid()
call.
[30 Sep 2009 9:34] Yoshinori Matsunobu
Hi!

In 5.1, prctl() is called *before* setuid/setgid() so it doesn't work. Please fix. 

----------
  if ((user_info= check_user(mysqld_user)))
  {
#if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT)
    if (locked_in_memory) // getuid() == 0 here
      set_effective_user(user_info);
    else
#endif
      set_user(mysqld_user, user_info);
  }
----------

prctl() is called by check_user(), setuid()/setgid() are by set_user(), but prctl() should be called after set_user().
[10 Mar 2010 11:36] Mark Robson
This affects us on 5.1 as well, it is difficult to get it to dump core (a UDF which calls prctl() appears to be the current proposed solution)
[11 Mar 2010 4:19] John Smith
Unable to get produce a core dump as a user "mysql" running:

Ubuntu 8.04.4 LTS
MySQL 5.1.36

Editing /etc/init.d/mysql   and setting user=root  allows a core dump to be created.

How to repeat:

1) set user=mysql

$ ulimit -c unlimited

[mysqld]
core-file

$/etc/init.d/mysql restart

killall -11 mysqld

[ no dump file produced ]

1) set user=root

$/etc/init.d/mysql restart

killall -11 mysqld

core.9447  [ core dump produced ]

Side notes:
---------

/etc/security/limits.conf was configured both as

* hard core 0 
* soft core 0

and

* hard core unlimited
* soft core unlimited

and 

core-file-size = 0
core-file-size = unlimited

were all tried in multiple combinations.  I was not able to get user=mysql to produce a dump.
[11 Mar 2010 17:09] John Smith
Confirmed for 5.0.75-0ubuntu10.3-log
[24 May 2016 4:27] Roel Van de Paar
Status: Open ?
[24 May 2016 11:23] Andrii Nikitin
The problem verified with following steps in source build of 5.7.11 on Oracle Linux 7 :
1. Setup core configuration (as root):
mkdir /tmp/corefiles
chmod 777 /tmp/corefiles
echo "/tmp/corefiles/core" > /proc/sys/kernel/core_pattern
echo "1" > /proc/sys/kernel/core_uses_pid

2. Create my.cnf with only two lines:

[mysqld]
core-file

3.
Initialize two datadir - one for current OS user and second for 'mysql' user:

[root sql]# mkdir /data1
[root sql]# mkdir /data2
[root sql]# chmod 777 /data1
[root sql]# chmod 777 /data2

[anikitin sql]$ ./mysqld --defaults-file=../my.cnf --initialize-insecure --basedir=.. --datadir=/data1
[anikitin sql]$ sudo ./mysqld --defaults-file=../my.cnf --initialize-insecure --basedir=.. --datadir=/data2 --user=mysql 

4. 
Start instances and make sure that second one did change user from root:
[anikitin sql]$ ./mysqld --defaults-file=../my.cnf --basedir=.. --datadir=/data1 --socket=/data1/mysql.sock &
[anikitin sql]$ sudo ./mysqld --defaults-file=../my.cnf --basedir=.. --datadir=/data2 --socket=/data2/mysql.sock --user=mysql --port=3307 &

[root sql]# top -cbn1 | grep mysqld
 5046 anikitin  20   0 2448716 175196   6584 S   0.0  1.1   0:00.22 ./mysqld --defaults-file=../my.cnf --basedir=.. --datadir=/data1 --socket=/data1/mysql.sock
 5136 mysql     20   0 2450800 176440   6488 S   0.0  1.1   0:00.20 ./mysqld --defaults-file=../my.cnf --basedir=.. --datadir=/data2 --socket=/data2/mysql.sock --user=mys+

5.
Make sure size of core file is not limited for the processes:
[anikitin sql]$ cat /proc/5406/limits | grep core
Max core file size        unlimited            unlimited            bytes

[anikitin sql]$ cat /proc/5136/limits | grep core
Max core file size        unlimited            unlimited            bytes

6. 
Attempt to kill the processes and observe that only first one did generate core dump:
[root sql]# kill -11 5136
[root sql]# kill -11 5046
[root sql]# ls -la /tmp/corefiles/
total 1091288
drwxrwxrwx.  2 root     root             84 May 24 12:10 .
drwxrwxrwt. 33 root     root           4096 May 24 12:10 ..
-rw-------.  1 anikitin anikitin 1253367808 May 24 12:10 core.5046

Conclusion:
Since core file was generated only for first instance - the bug is not fixed. Putting to 'Verified'.

Bonus:
Retry the same with suid_dumpable=2  - and core file gets generated:
[root sql]# echo 2 > /proc/sys/fs/suid_dumpable

[anikitin sql]$ sudo ./mysqld --defaults-file=../my.cnf --basedir=.. --datadir=/data2 --socket=/data2/mysql.sock --user=mysql --port=3307 &

[root sql]# top -cbn1 | grep mysqld
 6409 mysql     20   0 2450800 171448   6524 S   0.0  1.0   0:00.21 ./mysqld --defaults-file=../my.cnf --basedir=.. --datadir=/data2 --socket=/data2/mysql.+
[root sql]# kill -11 6409
[root@anikitin7 sql]# ls -la /tmp/corefiles/
total 1358016
drwxrwxrwx.  2 root     root            100 May 24 13:04 .
drwxrwxrwt. 34 root     root           4096 May 24 13:04 ..
-rw-------.  1 anikitin anikitin 1253367808 May 24 12:10 core.5046
-rw-------.  1 root     mysql    1253367808 May 24 13:04 core.6409

Final conclusion:
While the bug is formally not fixed - documentation states "There might be additional restrictions or limitations." 
So, considering well known in community workaround with 'suid_dumpable' - I am leaving this as 'Verified' 'Feature request'.
[1 Jun 2016 0:36] Mark Callaghan
FB MySQL has the fix. People I trust claim upstream MySQL is still broken.
https://github.com/facebook/mysql-5.6/commit/ebb204ce3bf20734e3e5a7cfb8006bbf9bebe8cc
[4 Jun 2016 9:59] Andrii Nikitin
Unfortunately I am not allowed to verify the bug if I don't have exact steps which demonstrate that the problem really exists. 
E.g. more details about environment where mentioned workaround doesn't help or explanation why mentioned workaround is a bad practice.
[30 Apr 2018 17:27] Paul DuBois
This bug was fixed in 8.0 by Bug#90642.
[14 May 2018 12:54] Tor Didriksen
Posted by developer:
 
Fixed by patch for:
https://bugs.mysql.com/bug.php?id=90642
[14 May 2018 13:11] Paul DuBois
Posted by developer:
 
Fixed in 8.0.12.

Linux binaries were unable to dump core after executing a setuid()
call.