From: tobias dot mueller at hostpoint dot ch
Operating system: ALL
PHP version: 5.6.25
Package: MySQL related
Bug Type: Feature/Change Request
Bug description:Problem when writing php extension which provides a mysql auth mehtod
Description:
------------
MySQL provides the concept of proxy authentication which allows it to
write a server side plugin to do specific authentication of a proxy
user.
To make this work a client plugin is required. PHP comes with builtin
authentication plugins for native auth, pam auth and sha256 auth.
I tried to write a new mysqlnd auth plugin for our custom mysql
authentication. The code looks something like in test-script below.
The functionality works so far. The extension can be loaded, it handles
the specific authentication well, but there is a segfault when php shuts
down.
When I run the test script in gdb, the segfault happens in this code:
mysqlnd_plugin_end_apply_func (pDest=<optimized out>)
at /home/tmueller/dev/php-5.6.24/ext/mysqlnd/mysqlnd_plugin.c:112
112 if (plugin_header->m.plugin_shutdown) {
(gdb) bt
#0 mysqlnd_plugin_end_apply_func (pDest=<optimized out>)
at /home/tmueller/dev/php-5.6.24/ext/mysqlnd/mysqlnd_plugin.c:112
When I set a breakpoint on that location, there is a segfault when
accessing member "m" of "plugin_header" struct. This happens because php
unloads my extension before unloading the mysqlnd extension and so
mysqlnd accesses a pointer which points to something that is not there
anymore.
When I set a breakpoint, the situation is like that:
Breakpoint 1, mysqlnd_plugin_end_apply_func (pDest=<optimized out>)
at /home/tmueller/dev/php-5.6.24/ext/mysqlnd/mysqlnd_plugin.c:112
112 if (plugin_header->m.plugin_shutdown) {
(gdb) p plugin_header
$9 = (struct st_mysqlnd_plugin_header *) 0x7ffff642b080
(gdb) p plugin_header->m
Cannot access memory at address 0x7ffff642b0c0
When I call "info sharedlibrary" in gdb in PHP_MINIT_FUNCTION of my
extension, the shared object is loaded:
Breakpoint 1, zm_activate_wtauth (type=1, module_number=29) at
/home/tmueller/dev/php-ext-wtauth/wtauth.c:111
warning: Source file is more recent than executable.
111 return SUCCESS;
(gdb) info sharedlibrary
From To Syms Read Shared Object
Library
0x00007ffff7ddaae0 0x00007ffff7df5490 Yes
/lib64/ld-linux-x86-64.so.2
0x00007ffff7bc2ad0 0x00007ffff7bd1eb9 Yes
/lib/x86_64-linux-gnu/libresolv.so.2
0x00007ffff78be610 0x00007ffff792d056 Yes
/lib/x86_64-linux-gnu/libm.so.6
0x00007ffff76b5ed0 0x00007ffff76b69ce Yes
/lib/x86_64-linux-gnu/libdl.so.2
0x00007ffff737b9d0 0x00007ffff746249e Yes (*)
/usr/lib/x86_64-linux-gnu/libxml2.so.2
0x00007ffff6fa8520 0x00007ffff70ed183 Yes
/lib/x86_64-linux-gnu/libc.so.6
0x00007ffff6d71e00 0x00007ffff6d81bf8 Yes (*)
/lib/x86_64-linux-gnu/libz.so.1
0x00007ffff6b500d0 0x00007ffff6b6424d Yes (*)
/lib/x86_64-linux-gnu/liblzma.so.5
0x00007ffff622a900 0x00007ffff622aa70 Yes
/home/tmueller/test-root/lib/php/extensions/no-debug-non-zts-20131226/wtauth.so
On line 112 of mysqlnd_plugin.c in mysqlnd_plugin_end_apply_func it is
not loaded anymore
warning: Temporarily disabling breakpoints for unloaded shared library
"/home/tmueller/test-root/lib/php/extensions/no-debug-non-zts-20131226/wtauth.so"
Breakpoint 2, mysqlnd_plugin_end_apply_func (pDest=<optimized out>)
at /home/tmueller/dev/php-5.6.24/ext/mysqlnd/mysqlnd_plugin.c:112
112 if (plugin_header->m.plugin_shutdown) {
(gdb) info sharedlibrary
From To Syms Read Shared Object
Library
0x00007ffff7ddaae0 0x00007ffff7df5490 Yes
/lib64/ld-linux-x86-64.so.2
0x00007ffff7bc2ad0 0x00007ffff7bd1eb9 Yes
/lib/x86_64-linux-gnu/libresolv.so.2
0x00007ffff78be610 0x00007ffff792d056 Yes
/lib/x86_64-linux-gnu/libm.so.6
0x00007ffff76b5ed0 0x00007ffff76b69ce Yes
/lib/x86_64-linux-gnu/libdl.so.2
0x00007ffff737b9d0 0x00007ffff746249e Yes (*)
/usr/lib/x86_64-linux-gnu/libxml2.so.2
0x00007ffff6fa8520 0x00007ffff70ed183 Yes
/lib/x86_64-linux-gnu/libc.so.6
0x00007ffff6d71e00 0x00007ffff6d81bf8 Yes (*)
/lib/x86_64-linux-gnu/libz.so.1
0x00007ffff6b500d0 0x00007ffff6b6424d Yes (*)
/lib/x86_64-linux-gnu/liblzma.so.5
In our opinion there are two ways to solve the problem:
1) Unregister the plugin in PHP_MSHUTDOWN_FUNCTION method of the
extension
This solution currently is not possible because the
mysqlnd_plugin_end_apply_func function does not appear in a header file
and can not be used by our extension.
2) Load mysqlnd code before our extension but unload our extension
after unloading mysqlnd
This is to my knowledge not possible because php always unloads the
extensions in reverse order as they were loaded.
Test script:
---------------
static zend_uchar *
mysqlnd_test_authorization_get_auth_data(struct
st_mysqlnd_authentication_plugin * self,
size_t * auth_data_len,
MYSQLND_CONN_DATA * conn, const char * const user, const char
* const passwd,
const size_t passwd_len, zend_uchar * auth_plugin_data, size_t
auth_plugin_data_len,
const MYSQLND_OPTIONS * const options,
const MYSQLND_NET_OPTIONS * const net_options,
unsigned long mysql_flags
TSRMLS_DC)
{
// stuff her
}
static struct st_mysqlnd_authentication_plugin
mysqlnd_test_authorization_plugin =
{
{
MYSQLND_PLUGIN_API_VERSION,
"auth_plugin_test_authorization",
MYSQLND_VERSION_ID,
MYSQLND_VERSION,
"PHP License 3.01",
"Author",
{
NULL, /* no statistics , will be filled later if there are some */
NULL, /* no statistics */
},
{
NULL
}
},
{/* methods */
mysqlnd_test_authorization_get_auth_data
}
};
void
test_auth_register_authentication_plugins(TSRMLS_D)
{
TSRMLS_FETCH();
mysqlnd_plugin_register_ex((struct st_mysqlnd_plugin_header *)
&mysqlnd_test_authorization_plugin.plugin_header TSRMLS_CC);
}
PHP_MINIT_FUNCTION(testauth)
{
test_auth_register_authentication_plugins(TSRMLS_C);
return SUCCESS;
}
PHP_MSHUTDOWN_FUNCTION(testauth)
{
// What to do here
return SUCCESS;
}
PHP_RINIT_FUNCTION(testauth)
{
return SUCCESS;
}
--
Edit bug report at https://bugs.php.net/bug.php?id=72919&edit=1
--
Try a snapshot (PHP 5.4): https://bugs.php.net/fix.php?id=72919&r=trysnapshot54
Try a snapshot (PHP 5.5): https://bugs.php.net/fix.php?id=72919&r=trysnapshot55
Try a snapshot (trunk): https://bugs.php.net/fix.php?id=72919&r=trysnapshottrunk
Fixed in SVN: https://bugs.php.net/fix.php?id=72919&r=fixed
Fixed in release: https://bugs.php.net/fix.php?id=72919&r=alreadyfixed
Need backtrace: https://bugs.php.net/fix.php?id=72919&r=needtrace
Need Reproduce Script: https://bugs.php.net/fix.php?id=72919&r=needscript
Try newer version: https://bugs.php.net/fix.php?id=72919&r=oldversion
Not developer issue: https://bugs.php.net/fix.php?id=72919&r=support
Expected behavior: https://bugs.php.net/fix.php?id=72919&r=notwrong
Not enough info: https://bugs.php.net/fix.php?id=72919&r=notenoughinfo
Submitted twice: https://bugs.php.net/fix.php?id=72919&r=submittedtwice
register_globals: https://bugs.php.net/fix.php?id=72919&r=globals
PHP 4 support discontinued: https://bugs.php.net/fix.php?id=72919&r=php4
Daylight Savings: https://bugs.php.net/fix.php?id=72919&r=dst
IIS Stability: https://bugs.php.net/fix.php?id=72919&r=isapi
Install GNU Sed: https://bugs.php.net/fix.php?id=72919&r=gnused
Floating point limitations: https://bugs.php.net/fix.php?id=72919&r=float
No Zend Extensions: https://bugs.php.net/fix.php?id=72919&r=nozend
MySQL Configuration Error: https://bugs.php.net/fix.php?id=72919&r=mysqlcfg