Bug #69121 [Opn->Ver]: Segfault in get_current_user when script owner is not in passwd

From: Date: Wed, 25 Feb 2015 22:46:04 +0000
Subject: Bug #69121 [Opn->Ver]: Segfault in get_current_user when script owner is not in passwd
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-190950@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=69121&edit=1 ID: 69121 Updated by: requinix@php.net Reported by: dan at syneto dot net Summary: Segfault in get_current_user when script owner is not in passwd -Status: Open +Status: Verified Type: Bug Package: Reproducible crash PHP Version: 5.6.6 Block user comment: N Private report: N New Comment: On Ubuntu 14.04 x64, getpwuid_r behaves the same way: returns 0 with result=NULL, but my PHP doesn't crash so it's probably using the getpwuid fallback. Compare php_get_current_user [1] with posix_getpwuid [2] which has ret = getpwuid_r(uid, &_pw, pwbuf, pwbuflen, &retpwptr); if (ret || retpwptr == NULL) { POSIX_G(last_error) = ret; efree(pwbuf); RETURN_FALSE; } I certainly wouldn't call myself a C dev, but #include <sys/types.h> #include <pwd.h> #include <stdio.h> #include <stdlib.h> #include <errno.h> int main(int argc, char* argv[]) { int ret; uid_t uid; struct passwd pwd; char* buf; size_t buflen; struct passwd* result; if (argc != 2) { printf("usage: %s uid\n", argv[0]); return 0; } uid = atoi(argv[1]); printf("uid=%d\n", uid); buf = (char*)malloc(100 * sizeof(char)); buflen = 99; result = NULL; ret = getpwuid_r(uid, &pwd, buf, buflen, &result); printf("ret=%d\n", ret); printf("errno=%d\n", errno); if (ret != 0) goto end; printf("result=%p\n", result); if (result == NULL) goto end; printf("pwd=%p\n", &pwd); printf("pwd.pw_name=%s\n", pwd.pw_name); printf("pwd.pw_passwd=%s\n", pwd.pw_passwd); printf("pwd.pw_uid=%d\n", pwd.pw_uid); printf("pwd.pw_gid=%d\n", pwd.pw_gid); printf("pwd.pw_gecos=%s\n", pwd.pw_gecos); printf("pwd.pw_dir=%s\n", pwd.pw_dir); printf("pwd.pw_shell=%s\n", pwd.pw_shell); printf("buf=%s\n", buf); end: free(buf); return 0; } which produces (eg,) uid=9999 ret=0 errno=0 result=(nil) [1] https://github.com/php/php-src/blob/4629f8978e86aa20e6254e7282e6c5a4fb26796c/main/main.c#L1258 [2] https://github.com/php/php-src/blob/4629f8978e86aa20e6254e7282e6c5a4fb26796c/ext/posix/posix.c#L1157 Previous Comments: ------------------------------------------------------------------------ [2015-02-25 21:10:31] dan at syneto dot net Description: ------------ This is a bug in function php_get_current_user (main.c) when compiling in a standards compliant environment on Illumos or Solaris based systems. It might also be happening on Linux or other Unix systems that follow the below semantics of getpwuid. This is the relevant section from the getpwnam_r() manual from Illumos: === (illumos) man getpwuid_r === ... The standard-conforming functions getpwnam_r() and getpwuid_r() can return 0 even on an error, particularly in the case where the requested entry is not found. The application needs to check the return value and that the pwd pointer is non-null. Otherwise, an error value is returned to indicate the error. ... The same issue is pointed to by the equivalent section on Linux systems: === (linux) man getpwuid_r === ... If no matching password record was found, these functions return 0 and store NULL in *result ... When running the test script, make sure you are root and able to run sudo to change its owner to a non-existent UID using: $ sudo chown 31415 get_current_user.php You will not need to run the script as root. Just make sure its owner UID does not exist in /etc/passwd. I also attached a patch that properly checks for a NULL result. Test script: --------------- === First code: <?php echo "Owner: " . get_current_user() . "\n"; === Second code: <?php array_fill(5, 6, 'banana'); echo "Owner: " . get_current_user() . "\n"; Expected result: ---------------- === First code output: Owner: === Second code output: Owner: Actual result: -------------- === First code output: Owner: d�� === Second code output: Segmentation Fault (core dumped) admin@vmbox-desk:/tmp/test$ pstack core core 'core' of 8560: php ./get_current_user.php fffffd7fff130474 strlen () + 14 000000000065df1b zif_get_current_user () + 2b 000000000072eb91 dtrace_execute_internal () + 91 00000000007f6e21 zend_do_fcall_common_helper_SPEC () + 661 000000000077d51b execute_ex () + 4b 000000000072ea6b dtrace_execute_ex () + 13b 00000000007442b2 zend_execute_scripts () + 1d2 00000000006d03af php_execute_script () + 1ef 00000000007f92cc do_cli () + 12bc 00000000008092aa main () + 63a 00000000004d8a7c _start () + 6c ------------------------------------------------------------------------ -- Edit this bug report at https://bugs.php.net/bug.php?id=69121&edit=1

« previous php.bugs (#190950) next »