Wednesday, September 21, 2011

Apache segfaults when PHP runs LDAP functions

I've been spending some time at work compiling a web stack to update the old, unsupported, and unmaintained Solaris webstack/coolstack software. It consists of the latest stable releases of Apache's httpd, MySQL, PHP, Python, and phpMyAdmin, compiled from source, to include all of their dependencies. One specific requirement here is that the various LDAP modules work. Many of our customers use this to authenticate users against a master directory on the network. I've encountered a problem.

I have a test script that pulls my own user information from our LDAP server. If I run this through the CLI PHP parser, it successfully and correctly gathers my information. If I hit that page up through Apache, httpd throws a segmentation fault. Even if I set Apache's LogLevel directive to 'debug', I get no information aobut *why* it segfaults. The only relevant output is as follows:

[Wed Sep 21 13:23:06 2011] [notice] child pid 6928 exit signal Segmentation fault (11) [Wed Sep 21 13:23:06 2011] [info] removed PID file /opt/utsawebstack/apache2/logs/httpd.pid (pid=6923) [Wed Sep 21 13:23:06 2011] [notice] caught SIGTERM, shutting down

The segfault *only* happens when LDAP functions are called from PHP. ldap_connect(), for example, fails. Other pages render fine through Apache.

Google hasn't been much help. The closest I've come to a solution is a patch for PHP version 4.4.4 — a version of PHP known to be buggy and unusable — and the patch no longer applies.

For the sake of detail, here are the configure strings for the relevant software (taken from a working build script, hence the variable names):

  • Berkeley DB (a dependency of OpenLDAP):
  • ../dist/configure --prefix=$BUILDBASE/lib
  • OpenLDAP (client only):
  • ./configure --prefix=$BUILDBASE/lib/ --disable-slapd --disable-slurpd
  • httpd:
  • ./configure --prefix=$BUILDBASE/apache2 --with-ldap --enable-authnz-ldap=shared --enable-ldap=shared --enable-headers=shared --enable-mime-magic=shared --enable-proxy=shared --enable-rewrite=shared --enable-mods-shared --enable-ssl=shared --with-z=$BUILDBASE/lib
  • PHP
  • ./configure --prefix=$BUILDBASE/php --with-apxs2=$BUILDBASE/apache2/bin/apxs --with-zlib=$BUILDBASE/lib --with-curl=$BUILDBASE/lib --with-iconv=$BUILDBASE/lib --enable-calendar --with-mysql=mysqlnd --with-mysqli=mysqlnd --enable-sockets --enable-zip --with-pear -with-mcrypt=$BUILDBASE/lib --enable-mbstring --with-ldap=$BUILDBASE/lib

Level of Difficulty: Solaris 10

Other Things I Know:

  • It's probably not a compiler problem. I'm using the latest version of make to do all of the compiling, and it's using GCC 3.4.3. And besides, most of this code requires GCC. Using the Sun/Oracle compiler would likely cause problems and failure.
  • It's not an architecture thing. I have compiled this and reproduced the problem on i386 and sparc hardware.
  • Since PHP and Apache are both compiled against the version of OpenLDAP that gets compiled first (see config string above), both are heavily reliant upon the ldap.conf file associated with it. Perhaps this is obvious to most, but I had wrongly assumed for some reason that Apache was the only thing using that. For what it's worth, that file is properly written.

Who has any idea what's going on here? Anybody?

FOUND A SOLUTION

The problem basically boils down to this:

I wrongly assumed that the --with-ldap configure argument would accept a directory to look in for the OpenLDAP libs (f/ex, --with-ldap=/opt/webstack/lib). It does not. Instead, I needed to throw in the --with-ldap argument with no directory attached to it along with --with-ldap-libs=/my/openldap/lib/dir and --with-ldap-include=/my/openldap/include/dir. Problem solved.