httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Ed Korthof>
Subject [PATCH] workaround for stat problem on RedHat 5.1/5.2
Date Wed, 12 May 1999 16:34:45 GMT
Hi --

A JServ user turned some something which appears to be a bug in RedHat's
stat.  It doesn't show up when mod_rewrite isn't enabled, and it only
affects URIs for which there is no matching file. 

On RedHat 5.1/5.2, with a file which doesn't exist, stat returns -1, and
sets errno to ENOENT. Unfortunately, it leaves r->finfo in an inconsistent
state; r->finfo.st_mode appears to contain garbage (an address of some
sort, most likely).  Sometimes it leaves r->finfo.st_mode set to a value
for which all of S_ISDIR(), S_ISLNK(), and S_ISREG() return false; 
sometimes it doesn't (this depends on the text of the program -- if that
changes, the value will change).  If all of those return false, then
check_safe_path (in http_request.c) returns 403, and that's the HTTP
return code. 

This is a problem in general for modules which answer URIs for files which
doesn't exist, and it's a problem for JServ in particular.  We advise
people to configure their Apache so that /servlets/foo is transformed into
a request for the servlet named foo ... where /servlets/ doesn't exist as
a directory.

I'm pretty sure this behavior is a bug in glibc's stat; the following
simple program demonstrates it:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>

void main() {
    char *filename = "missing file";
    struct stat finfo;
    finfo.st_mode = 0;
    fprintf(stderr, "stat returned: %d\n", stat(filename, &finfo));
    fprintf(stderr, "finfo.st_mode = %d\n", finfo.st_mode);

And sample output on RedHat 5.1:
stat returned: -1

Should mod_rewrite really be copying the URI to r->filename in
hook_uri2file?  Here's the comment which made me wonder:

329  /*
330   * Are we dealing with a file? If not, we can (hopefuly) safely assume we
331   * have a handler that doesn't require one, but for safety's sake, and so
332   * we have something find_types() can get something out of, fake one. But
333   * don't run through the directory entries.
334   */
336  if (r->filename == NULL) {
337      r->filename = ap_pstrdup(r->pool, r->uri);
338      r->finfo.st_mode = 0;   /* Not really a file... */
339      r->per_dir_config = per_dir_defaults;
341      return OK;
342  }

Anyway, the following patch does solve the problem I'm seeing; but I'm not
sure it's very reasonable for non-linux servers.  It might make sense to
wrap it in an appropriate preprocessor define ... but I'm not sure which
versions of linux display this problem.

--- http_request.c      1999/04/20 23:38:44     1.147
+++ http_request.c      1999/05/12 01:59:42
@@ -267,6 +267,9 @@
 #if defined(ENOENT) && defined(ENOTDIR)
         else if (errno == ENOENT || errno == ENOTDIR) {
+            if (errno == ENOENT)
+                r->finfo.st_mode = 0;
             last_cp = cp;
             while (--cp > path && *cp != '/')

thanks --


View raw message