php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #16638 Mkdir fails under safe mode
Submitted: 2002-04-16 12:40 UTC Modified: 2002-07-13 00:45 UTC
Votes:3
Avg. Score:4.3 ± 0.9
Reproduced:3 of 3 (100.0%)
Same Version:1 (33.3%)
Same OS:1 (33.3%)
From: byg at cf1 dot ru Assigned:
Status: Closed Package: Scripting Engine problem
PHP Version: 4.2.0 OS: Linux
Private report: No CVE-ID:
 [2002-04-16 12:40 UTC] byg at cf1 dot ru
Unable to create directory by mkdir PHP function when PHP runs under safe mode.
The following command fails:
if (!mkdir("$PHP_DOCUMENT_ROOT/$path", 0770))when $path has a trailing slash.

There is two possible solutions.
Both shown below and can also be found at
http://www.cf1.ru/~byg/patch/php/safe_mode.c.patch
http://www.cf1.ru/~byg/patch/php/mkdir_get_rid_trailing_slashes.patch
or
ftp://ftp.cf1.ru/pub/patches/php/

1) change php_checkuid in main/safe_mode.c 
2) change mkdir handler in ext/standard/file.c

1st patch:
=================================================
--- main/safe_mode.c.orig       Thu Apr  4 13:58:00 2002
+++ main/safe_mode.c    Tue Apr 16 12:29:53 2002
@@ -49,7 +49,7 @@
        int ret, nofile=0;
        long uid=0L, gid=0L, duid=0L, dgid=0L;
        char path[MAXPATHLEN];
-       char *s;
+       char *s, *anchor;
        TSRMLS_FETCH();

        if (!filename) {
@@ -105,19 +105,42 @@
                                *s = '\0';
                }
        } else { /* CHECKUID_ALLOW_ONLY_DIR */
-               s = strrchr(filename, DEFAULT_SLASH);
-
-               if (s == filename) {
-                       /* root dir */
-                       path[0] = DEFAULT_SLASH;
-                       path[1] = '\0';
-               } else if (s) {
-                       *s = '\0';
+               /* look for a trail slash --byg */
+               s = (char *) strrchr(filename, DEFAULT_SLASH);
+               /* if s points s is either equal to or less than filename, NULL as last resort (never s>filename) */
+               if ((filename + strlen(filename) - 1) > s)
+               {
+                   if (s)
+                   { /* path like /a/b or a/b, skip tail */
+                       *s='\0';
                        VCWD_REALPATH(filename, path);
                        *s = DEFAULT_SLASH;
-               } else {
+                   }
+                   else
+                   { /* trivial path like aaa */
                        VCWD_GETCWD(path, MAXPATHLEN);
-               }
+                   }
+               }
+               else
+               {
+                   /* get rid contiguous trailing slashes if any */
+                   while( s>filename && *(s-1) == DEFAULT_SLASH)
+                       --s;
+                   if (s > filename)
+                   { /* mark current position then look for the next slash group */
+                       anchor = s; *s = '\0'; s = (char*) strrchr(filename, '/');
+                       if (s) *s = '\0'; /* path was either /a/b/// */
+                       VCWD_REALPATH(filename, path); /* or just a/// */
+                       *anchor = DEFAULT_SLASH; /* restore slashes */
+                       if (s) *s = DEFAULT_SLASH;
+                   }
+                   /* rare case - root dir */
+                   else
+                   {
+                       path[0] = DEFAULT_SLASH;
+                       path[1] = '\0';
+                   }
+               }
        } /* end CHECKUID_ALLOW_ONLY_DIR */
       if (mode != CHECKUID_ALLOW_ONLY_FILE) {
==================================================
2nd patch:
==================================================
 --- ext/standard/file.c.orig    Tue Apr 16 22:34:55 2002
+++ ext/standard/file.c Tue Apr 16 23:19:29 2002
@@ -1454,10 +1454,21 @@
 {
        int dir_len, ret;
        mode_t mode = 0777;
-       char *dir;
+       char *dir, *s;
 
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &dir, &dir_len, &mode) == FAILURE) {
                return;
+       }
+
+       /* get rid trailing slashes if any --byg */
+       if (dir) {
+           s = dir + strlen(dir) - 1;
+           if (*s == DEFAULT_SLASH) {
+               while((*(s-1) == DEFAULT_SLASH) && (s > dir))
+                   --s;
+               if (s > dir)
+                   *(s) = '\0';
+           }
        }
 
        if (PG(safe_mode) &&(!php_checkuid(dir, NULL, CHECKUID_ALLOW_ONLY_DIR))) {

        if (mode != CHECKUID_ALLOW_ONLY_FILE) {
=====================================================

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2002-07-13 00:45 UTC] sniper@php.net
This bug has been fixed in CVS. You can grab a snapshot of the
CVS version at http://snaps.php.net/. In case this was a documentation 
problem, the fix will show up soon at http://www.php.net/manual/.
In case this was a PHP.net website problem, the change will show
up on the PHP.net site and on the mirror sites.
Thank you for the report, and for helping us make PHP better.


 
PHP Copyright © 2001-2014 The PHP Group
All rights reserved.
Last updated: Fri Apr 18 00:01:21 2014 UTC