>Number:         2075
>Category:       suexec
>Synopsis:       suexec can't write log after failed exec & doesn't check 
>execute permission
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    apache
>State:          open
>Class:          sw-bug
>Submitter-Id:   apache
>Arrival-Date:   Fri Apr 17 22:30:01 PDT 1998
>Last-Modified:
>Originator:     [EMAIL PROTECTED]
>Organization:
apache
>Release:        1.2.6
>Environment:
uname -a gives:
Linux darkstar.pete.net 2.0.33 #3 Fri Feb 20 04:24:17 EST 1998 i586 unknown
This is a redhat 5.0 system, compiler is pgcc 1.0.2
>Description:
This is more of an annoyance than anything, but of all the checks suexec makes
before executing a cgi script, it nevers checks if the user has execute
permission for his own file.

This causes the exec call to fail, and suexec tries to log the failure. But it
closed the log file just before the exec attempt, and since it already dropped
root priviledges, it can't reopen the log file. Thus it bombs, and you get a
strange error in error_log.
>How-To-Repeat:
Setup apache with suexec, and try to access a cgi url that passes all of
suexec's security checks, i.e. under public_html directory, is a real file, not
group/world writeable, etc. but that does not have execute permission set, i.e.
0444.
>Fix:
This is how I patched suexec.c. First I added a check at the end for a set
S_IXUSR bit in prg_info.st_mode, and it exits with exit code of 121 and a nicer
message rather than a failed exec.

And second, to overcome the problem of logging when exec fails, Linux supports
the FD_CLOEXEC descriptor flags, which closes the descriptor when exec is
successfully called. When the log file is first opened, I try to set this flag.
I keep track of the success of this attempt in the static variable I added
close_before_exec. When we get to the exec() call, if FD_CLOEXEC was 
successfully
set, I flush the log and let exec() close it if it exec'd. Otherwise, I close 
the
file before exec() as is done in the original code. Thus the exec() cgi program
never gets the log file descriptor, but it lets suexec log an error if exec()
failed for some reason.

I hope this helps.

- Kris

--- apache_1.2.6/suexec.c       Fri Jan 30 09:45:44 1998
+++ suexec.c    Fri Apr 17 21:50:53 1998
@@ -80,6 +80,7 @@
 #include <grp.h>
 #include <time.h>
 #include <sys/stat.h>
+#include <fcntl.h>

 #if defined(PATH_MAX)
 #define AP_MAXPATH PATH_MAX
@@ -93,6 +94,7 @@

 extern char **environ;
 static FILE *log;
+static int close_before_exec;

 char *safe_env_lst[] =
 {
@@ -142,12 +144,23 @@
     time_t timevar;
     struct tm *lt;

-    if (!log)
+    if (!log) {
        if ((log = fopen(LOG_EXEC, "a")) == NULL) {
            fprintf(stderr, "failed to open log file\n");
            perror("fopen");
            exit(1);
+       } else {
+           int log_fd = fileno(log);
+           int fd_flags = fcntl (log_fd, F_GETFD, 0);
+
+           close_before_exec = 1;
+           if (fd_flags >= 0) {
+               fd_flags |= FD_CLOEXEC;
+               if (fcntl (log_fd, F_SETFD, fd_flags) >= 0)
+                   close_before_exec = 0;
+           }
        }
+    }

     time(&timevar);
     lt = localtime(&timevar);
@@ -463,6 +476,14 @@
        exit(120);
     }

+    /*
+     * Error out if the file is not executable by the owner.
+     */
+    if (!(prg_info.st_mode & S_IXUSR)) {
+       log_err("file is not executable by owner: (%s/%s)\n",cwd,cmd);
+       exit(121);
+    }
+
     clean_env();

     /*
@@ -470,9 +491,13 @@
      * mess with it.  If the exec fails, it will be reopened
      * automatically when log_err is called.
      */
-    fclose(log);
-    log = NULL;
-
+    if (close_before_exec) {
+       fclose(log);
+       log = NULL;
+    } else {
+       fflush(log);
+    }
+
     /*
      * Execute the command, replacing our image with its own.
      */
%0
>Audit-Trail:
>Unformatted:
[In order for any reply to be added to the PR database, ]
[you need to include <[EMAIL PROTECTED]> in the Cc line ]
[and leave the subject line UNCHANGED.  This is not done]
[automatically because of the potential for mail loops. ]



Reply via email to