Bug #74357 [Ver]: lchown fails to change ownership of symlink with ZTS

[email protected]
Newsgroups php.bugs
Message-ID <[email protected]>
Edit report at https://bugs.php.net/bug.php?id=74357&edit=1

 ID:                 74357
 Updated by:         [email protected]
 Reported by:        msaladna at apisnetworks dot com
 Summary:            lchown fails to change ownership of symlink with ZTS
 Status:             Verified
 Type:               Bug
 Package:            Filesystem function related
 Operating System:   CentOS 7.3
 PHP Version:        7.4.23
-Assigned To:        
+Assigned To:        bukka
 Block user comment: N
 Private report:     N

 New Comment:

So this is really a bug in ZTS. The reason is that virtual_chown calls:

if (virtual_file_ex(&new_state, filename, NULL, CWD_REALPATH)) {

The problem is that this calls tsrm_realpath_r which resolves the simlink in 

		if (save && S_ISLNK(st.st_mode)) {
			if (++(*ll) > LINK_MAX || (j = (size_t)php_sys_readlink(tmp, path, MAXPATHLEN)) == (size_t)-1) {
				/* too many links or broken symlinks */
				free_alloca(tmp, use_heap);
				return (size_t)-1;
			}
			path[j] = 0;
			if (IS_ABSOLUTE_PATH(path, j)) {
				j = tsrm_realpath_r(path, 1, j, ll, t, use_realpath, is_dir, &directory);
				if (j == (size_t)-1) {
					free_alloca(tmp, use_heap);
					return (size_t)-1;
				}
			} else {
				if (i + j >= MAXPATHLEN-1) {
					free_alloca(tmp, use_heap);
					return (size_t)-1; /* buffer overflow */
				}
				memmove(path+i, path, j+1);
				memcpy(path, tmp, i-1);
				path[i-1] = DEFAULT_SLASH;
				j = tsrm_realpath_r(path, start, i + j, ll, t, use_realpath, is_dir, &directory);
				if (j == (size_t)-1) {
					free_alloca(tmp, use_heap);
					return (size_t)-1;
				}
			}
			if (link_is_dir) {
				*link_is_dir = directory;
			}
		}


Currently it seems that it does not get resolved only for CWD_EXPAND but not 100% sure if it's safe. Anyway I created https://github.com/php/php-src/pull/20626 so it will be checked there.


Previous Comments:
------------------------------------------------------------------------
[2024-07-13 09:12:29] ewverb654 at gmail dot com

This information is really helpful for who really needs this. I hope you will many more write post like this. (https://github.com)(https://www.mgh-patientgateway.com)

------------------------------------------------------------------------
[2021-09-10 14:40:05] [email protected]

I can confirm the reported behavior (PHP-7.4).  It is apparently
not related to the realpath cache, since disabling the cache in
the first place doesn't make a difference.

------------------------------------------------------------------------
[2021-09-09 16:26:25] msaladna at apisnetworks dot com

Problem still persists. Sample code amended for clarity:

<?php
   echo "TS: ", PHP_ZTS, " ", PHP_VERSION, "\n";
   echo posix_getuid(), ":", posix_geteuid(), "\n";
   is_link("foo") && unlink("foo");
   symlink("/tmp", "foo");
   lchown("foo", 99);
   clearstatcache(true);
   var_dump(lstat("foo")['uid']);
?>

This is on a CentOS 7/PHP 7.4 machine.

TS: 1 7.4.23
0:0
int(0)

And on a Rocky Linux (CentOS 8)/PHP 8 machine:

TS: 1 8.0.6
0:0
int(0)

------------------------------------------------------------------------
[2021-09-09 12:20:04] [email protected]

What is the output of the following script:

<?php
   echo "TS: ", PHP_ZTS, "\n";
   is_link("foo") && unlink("foo");
   symlink("/tmp", "foo");
   lchown("foo", 99);
   clearstatcache(true);
   var_dump(lstat("foo")['uid']);
?>

And please check with any of the actively supported PHP
versions[1]?

[1] <https://www.php.net/supported-versions.php>

------------------------------------------------------------------------
[2017-04-01 04:07:34] msaladna at apisnetworks dot com

Description:
------------
Compiling PHP with ZTS affects performance of lchown and lchgrp. 

PHP CLI compiled without ZTS:

./configure --disable-all

ZTS is above + '--enable-maintainer-zts'

Test script:
---------------
<?php
   echo "TS: ", PHP_ZTS, "\n";
   is_link("foo") && unlink("foo");
   symlink("/tmp", "foo");
   lchown("foo", 99);
   var_dump(lstat("foo")['uid']);
?>

Expected result:
----------------
TS: 1
int(99)

Actual result:
--------------
TS: 1
int(0)


------------------------------------------------------------------------



--
Edit this bug report at https://bugs.php.net/bug.php?id=74357&edit=1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.