diff -Naur php-4.3.10/main/safe_mode.c php-4.3.10-patched/main/safe_mode.c --- php-4.3.10/main/safe_mode.c 2004-12-02 00:37:59.000000000 +0200 +++ php-4.3.10-patched/main/safe_mode.c 2004-12-29 03:25:51.000000000 +0200 @@ -14,6 +14,8 @@ +----------------------------------------------------------------------+ | Author: Rasmus Lerdorf | +----------------------------------------------------------------------+ + | Applied patch by Anton Titov http://titov.net/safemodepatch | + +----------------------------------------------------------------------+ */ /* $Id: safe_mode.c,v 1.51.2.5 2004/12/01 22:37:59 sesser Exp $ */ @@ -46,11 +48,11 @@ PHPAPI int php_checkuid_ex(const char *filename, char *fopen_mode, int mode, int flags) { - struct stat sb; - int ret, nofile=0; + struct stat sb, sb2; + int ret, usegid, scriptuid, serveruid, scriptgid, nofile=0; long uid=0L, gid=0L, duid=0L, dgid=0L; - char path[MAXPATHLEN]; - char *s, filenamecopy[MAXPATHLEN]; + char path[MAXPATHLEN], path2[MAXPATHLEN]; + char *s, *s2, filenamecopy[MAXPATHLEN]; php_stream_wrapper *wrapper = NULL; TSRMLS_FETCH(); @@ -58,6 +60,13 @@ return 0; /* path must be provided */ } + scriptuid=php_getuid(); + serveruid=getuid(); + + if (usegid=PG(safe_mode_gid)){ // yes, it's correct + scriptgid=php_getgid(); + } + if (strlcpy(filenamecopy, filename, MAXPATHLEN)>=MAXPATHLEN) { return 0; } @@ -101,11 +110,33 @@ } else { uid = sb.st_uid; gid = sb.st_gid; - if (uid == php_getuid()) { + if (uid == scriptuid) { return 1; - } else if (PG(safe_mode_gid) && gid == php_getgid()) { + } else if (usegid && gid == scriptgid) { return 1; } + strlcpy(path2, path, MAXPATHLEN); + while (uid==serveruid){ + if (!(s2 = strrchr(path2, DEFAULT_SLASH))) + break; + if (s2==path2) + break; + *s2='\0'; + ret = VCWD_STAT(path2, &sb2); + if (ret < 0) + break; // no need to throw error, as we can access the file itself + else { + uid = sb2.st_uid; + gid = sb2.st_gid; + } + } + if (uid==scriptuid) + return 1; + else if (usegid && gid == scriptgid) + return 1; + // restore uid & gid for error message + uid = sb.st_uid; + gid = sb.st_gid; } /* Trim off filename */ @@ -147,11 +178,33 @@ } duid = sb.st_uid; dgid = sb.st_gid; - if (duid == php_getuid()) { + if (duid == scriptuid) { return 1; - } else if (PG(safe_mode_gid) && dgid == php_getgid()) { + } else if (usegid && dgid == scriptgid) { return 1; } else { + strlcpy(path2, path, MAXPATHLEN); + while (duid==serveruid){ + if (!(s2 = strrchr(path2, DEFAULT_SLASH))) + break; + if (s2==path2) + break; + *s2='\0'; + ret = VCWD_STAT(path2, &sb2); + if (ret < 0) + break; + else { + duid = sb2.st_uid; + dgid = sb2.st_gid; + } + } + if (duid==scriptuid) + return 1; + else if (usegid && dgid==scriptgid) + return 1; + duid = sb.st_uid; + dgid = sb.st_gid; + TSRMLS_FETCH(); if (SG(rfc1867_uploaded_files)) {