Req #72919 [Opn->Csd]: Problem when writing php extension which provides a mysql auth mehtod
Edit report at https://bugs.php.net/bug.php?id=72919&edit=1
ID: 72919
Updated by: cmb@php.net
Reported by: tobias dot mueller at hostpoint dot ch
Summary: Problem when writing php extension which provides a
mysql auth mehtod
-Status: Open
+Status: Closed
Type: Feature/Change Request
Package: MySQL related
Operating System: ALL
PHP Version: 5.6.25
-Assigned To:
+Assigned To: cmb
Block user comment: N
Private report: N
New Comment:
This bug tracker is not a support forum. If this is still an
issue for, please write to the internals mailing list[1].
[1] <https://www.php.net/mailing-lists.php#internals>
Previous Comments:
------------------------------------------------------------------------
[2020-02-23 12:19:35] isundill at gmail dot com
Hello,
I had the same issue, and I solved the issue allocating the struct with malloc and freeing it in
PHP_MSHUTDOWN_FUNCTION the second time the shutdown is called (it will be called the second time by
the mysqlnd_plugin_end_apply_func function).
It's really not beautiful, but at least it doesn't leak nor cause segmentation fault.
isundil
------------------------------------------------------------------------
[2016-08-22 09:47:49] tobias dot mueller at hostpoint dot ch
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 this bug report at https://bugs.php.net/bug.php?id=72919&edit=1
Thread (3 messages)