Bug 39045

Summary: mod_python makes Apache crash when used with mod_auth_ldap
Product: Apache httpd-2 Reporter: Emmanuel Blot <emmanuel.blot>
Component: mod_authn_ldapAssignee: Apache HTTPD Bugs Mailing List <bugs>
Status: RESOLVED FIXED    
Severity: major CC: francois.pesce
Priority: P2 Keywords: FixedInTrunk, PatchAvailable
Version: 2.0.55   
Target Milestone: ---   
Hardware: All   
OS: Linux   
Attachments: Patch to avoid NULL value for env in mod_auth_ldap

Description Emmanuel Blot 2006-03-21 11:23:42 UTC
Initial bug report:
http://projects.edgewall.com/trac/ticket/2901

Environment:
 * Linux 2.6, Debian testing
 * modpython (reproduced with 3.1.3 (debian) and 3.2.8 (custom build))
 * python (reproduced with 2.3.5 (debian) and 2.4.2 (custom build))
 * LDAP authentication support (mod_auth_ldap)
 * Apache2 using the "prefork" engine

Note:
 * PHP5 and MySQL were used on the server, and as I read (mailing list) that
PHP5 and ModPython may conflict is some rare cases, I disabled the PHP module in
the server config, but the same crashes kept occuring under the same conditions.

When authentication is performed (againt a LDAP directory) in a Python web
application context (Trac, see URL), the Apache server doesn't reply to the web
browser request as it dies. The Apache2 log message shows the following:

"child pid <n> exit signal Segmentation fault (11)"

The root cause seems to be the LDAP authentication module:
It defines an extra environment variable AUTHENTICATE_UID, which may takes an
invalid (null ?) value.

This value is retrieved in modpython/apache.py:build_cgi_env(req) and added to
the CGI environment variable.

When this dictionnary/hash table is duplicated using environ.duplicate() Python
call, the server thread crashes.

When the duplicate() method attempts to duplicate the value of the
AUTHENTICATE_UID key, it produces an invalid call which ends up in calling the
libc strlen() function with an invalid parameter, and eventually crashes the
current Apache thread.

The same crash occurs whenever the value (environ['AUTHENTICATE_UID']) is
accessed from the dictionnary.

Using GDB to run the Apache server, the backtrace shows the following:

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread -1215211840 (LWP 31344)]
0xb7a781e3 in strlen () from /lib/tls/libc.so.6

#0  0xb7a781e3 in strlen () from /lib/tls/libc.so.6
#1  0xb7777ec5 in PyString_FromString () from /usr/lib/libpython2.3.so.1.0
#2  0xb78324e9 in MpTable_New () from /usr/lib/apache2/modules/mod_python.so
#3  0xb774704a in PyObject_GetItem () from /usr/lib/libpython2.3.so.1.0
#4  0xb776f922 in PyDict_Merge () from /usr/lib/libpython2.3.so.1.0
#5  0xb776fa2d in PyDict_Update () from /usr/lib/libpython2.3.so.1.0
#6  0xb776fa64 in PyDict_Update () from /usr/lib/libpython2.3.so.1.0
#7  0xb77aa9d9 in _PyEval_SliceIndex () from /usr/lib/libpython2.3.so.1.0
#8  0xb77ab646 in PyEval_EvalCodeEx () from /usr/lib/libpython2.3.so.1.0
#9  0xb775ef5a in PyFunction_SetClosure () from /usr/lib/libpython2.3.so.1.0
#10 0xb7744bb7 in PyObject_Call () from /usr/lib/libpython2.3.so.1.0
#11 0xb774c106 in PyMethod_New () from /usr/lib/libpython2.3.so.1.0
#12 0xb7744bb7 in PyObject_Call () from /usr/lib/libpython2.3.so.1.0
#13 0xb77829ae in _PyObject_SlotCompare () from /usr/lib/libpython2.3.so.1.0
#14 0xb7780075 in PyType_IsSubtype () from /usr/lib/libpython2.3.so.1.0
#15 0xb7744bb7 in PyObject_Call () from /usr/lib/libpython2.3.so.1.0
#16 0xb77a74c1 in _PyEval_SliceIndex () from /usr/lib/libpython2.3.so.1.0
#17 0xb77aa906 in _PyEval_SliceIndex () from /usr/lib/libpython2.3.so.1.0
#18 0xb77ab646 in PyEval_EvalCodeEx () from /usr/lib/libpython2.3.so.1.0
#19 0xb775ef5a in PyFunction_SetClosure () from /usr/lib/libpython2.3.so.1.0
#20 0xb7744bb7 in PyObject_Call () from /usr/lib/libpython2.3.so.1.0
#21 0xb774c106 in PyMethod_New () from /usr/lib/libpython2.3.so.1.0
#22 0xb7744bb7 in PyObject_Call () from /usr/lib/libpython2.3.so.1.0
#23 0xb774886e in PyObject_CallMethod () from /usr/lib/libpython2.3.so.1.0
#24 0xb7837c58 in python_cleanup () from /usr/lib/apache2/modules/mod_python.so
#25 0xb7839359 in python_cleanup () from /usr/lib/apache2/modules/mod_python.so
#26 0x08079045 in ap_run_handler ()
#27 0x08079481 in ap_invoke_handler ()
#28 0x0806a558 in ap_process_request ()
#29 0x08065218 in _start ()
Comment 1 Francois Pesce 2006-03-28 03:33:59 UTC
Created attachment 17997 [details]
Patch to avoid NULL value for env in mod_auth_ldap

If the problem comes from a NULL value in AUTHENTICATE_* environment variable,
as you said, this little patch may fix it.
Comment 2 William A. Rowe Jr. 2006-03-28 03:47:31 UTC
Never reassign bugs off the notification lists please.  Add yourself as a cc,
or simply use the additional-comment-from key to search for your own incidents :)
Comment 3 Emmanuel Blot 2007-03-09 14:54:05 UTC
Any update about this issue?
Comment 4 Nick Kew 2007-03-09 16:20:25 UTC
(In reply to comment #3)
> Any update about this issue?

The bug seems to be in mod_python rather than apache (whose documentation
doesn't AFAICS promise any such environment variables).

Having said that, the patch looks fine.  The drawback is, it fixes just one
instance of the underlying bug.

(this is a quick reaction to your question, and ICBW).
Comment 5 Nick Kew 2008-09-08 07:45:23 UTC
Any reason for the pstrdup in your patch?  Surely no consumer is going to write to memory returned from an env var?
Comment 6 Francois Pesce 2008-09-08 16:25:56 UTC
Probably because I've been too much bothered of memory leaks in other open source projects where a function heterogeneously and randomly returns const char OR allocated result, that made me unable to know when to deallocate or not.
Feel free to change that if you want.

I know some (not all) of the subtleties and differences from pools allocation in comparison to "classic" allocation function, but I've decided to keep an homogeneous allocation type to this result.

And vals[i] is usualy allocated via apr_pstrdup().

Feel free to change it if you prefer.
Comment 7 Nick Kew 2008-09-08 17:52:28 UTC
modified patch committed in r693328
Comment 8 Stefan Fritsch 2012-02-26 16:38:52 UTC
fixed in 2.4.1