php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #10656 shmop_open permissions incorrect for writing
Submitted: 2001-05-03 22:55 UTC Modified: 2002-01-09 03:24 UTC
From: phpdev at utopianit dot com Assigned:
Status: Closed Package: Semaphore related
PHP Version: 4.0.5 OS: FreeBSD 4.3 (i386)
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: phpdev at utopianit dot com
New email:
PHP Version: OS:

 

 [2001-05-03 22:55 UTC] phpdev at utopianit dot com
Basically, the shmop_open function does not allow for writing to shared memory if pre-allocated memory is opened using the ACCESS (rather than CREATE) mode. This was found when using the shmop functions for fast interprocess communication between a number of php cgi scripts. The solution to this bug was to create another mode, WRITE (w) that uses IPC_R & IPC_W shm flags.

To reproduce the problem:-

# ** BEFORE fix modifications are made **
# ** change to php cgi directory and run server command (C) in one telnet session then run client command (A) in another. Client cannot write!
echo '<? $id = shmop_open(0xff00, "c", 777, 1000); print "Server:  Got ID\n"; shmop_write($id, "Hello", 0); sleep(5); $in = shmop_read($id, 0,5); print "Server:  Got \"$in\" back from client!\n"; ?>' | ./php -q &
echo '<? $id = shmop_open(0xff00, "a", 0,0); print "ClientA: Got ID: $id\n"; $in = shmop_read($id, 0,5); print "ClientA: Got \"$in\" from server!\n"; $bytes = shmop_write($id, $text = "aMode", 0); print "ClientA: Wrote $text to server! ($bytes bytes)\n"; sleep(12); print "\n\n"; ?>' | ./php -q

# ** shmop_open in ACCESS mode does not allow writing to shared memory!
# ** So, I created a WRITE ("w") mode to allow writing and left ACCESS ("a") mode as read_only.

# ** AFTER fix modifications are made **
# ** change to php cgi directory and run server command (C) in one telnet session then run new client command (W) in another. Client can now write.
echo '<? $id = shmop_open(0xff00, "c", 777, 1000); print "Server:  Got ID\n"; shmop_write($id, "Hello", 0); sleep(5); $in = shmop_read($id, 0,5); print "Server:  Got \"$in\" back from client!\n"; ?>' | ./php -q &
echo '<? $id = shmop_open(0xff00, "w", 0,0); print "ClientW: Got ID: $id\n"; $in = shmop_read($id, 0,5); print "ClientW: Got \"$in\" from server!\n"; $bytes = shmop_write($id, $text = "wMode", 0); print "ClientW: Wrote $text to server! ($bytes bytes)\n"; sleep(12); print "\n\n"; ?>' | ./php -q

# ** Modifications required for bug fix, include changing ext/shmop.c

Existing /ext/shmop.c [shmop_open()]:

	/* {{{ proto int shmop_open (int key, int flags, int mode, int size)
	   gets and attaches a shared memory segment */
	PHP_FUNCTION(shmop_open)
	{
...
	        if (memchr((*flags)->value.str.val, 'a', (*flags)->value.str.len)) {
	                shmflg = SHM_RDONLY;
	                shmop->shmflg |= IPC_EXCL;
	        }
	        else if (memchr((*flags)->value.str.val, 'c', (*flags)->value.str.len)) {
	                shmop->shmflg |= IPC_CREAT;
	                shmop->size = (*size)->value.lval;
	        }
	        else {
	                php_error(E_WARNING, "shmopen: access mode invalid");
	                efree(shmop);
	                RETURN_FALSE;
	        }
	
	        shmop->shmid = shmget(shmop->key, shmop->size, shmop->shmflg);
	        if (shmop->shmid == -1) {
	                php_error(E_WARNING, "shmopen: can't get the block");
	                efree(shmop);
	                RETURN_FALSE;
	        }
...
	}
	/* }}} */

Corrected /ext/shmop.c [shmop_open()]:

	/* {{{ proto int shmop_open (int key, int flags, int mode, int size)
	   gets and attaches a shared memory segment */
	PHP_FUNCTION(shmop_open)
	{
...
	        if (memchr((*flags)->value.str.val, 'a', (*flags)->value.str.len)) {
	                shmflg = SHM_RDONLY;
	                shmop->shmflg |= IPC_EXCL;
	        }
	        else if (memchr((*flags)->value.str.val, 'c', (*flags)->value.str.len)) {
	                shmop->shmflg |= IPC_CREAT;
	                shmop->size = (*size)->value.lval;
	        }
	        else if (memchr((*flags)->value.str.val, 'w', (*flags)->value.str.len)) {
	                shmop->shmflg |= IPC_R;
	                shmop->shmflg |= IPC_EXCL;
	                shmop->shmflg |= IPC_W;
	        }
	        else {
	                php_error(E_WARNING, "shmopen: access mode invalid");
	                efree(shmop);
	                RETURN_FALSE;
	        }
...
	}
	/* }}} */
	
# * Configuration lines for php_4.0.5.tar.gz compiling
./configure "--enable-memory-limit=yes" "--enable-sockets" "--with-openssl" "--enable-shmop" "--enable-debug=no" "--enable-xml" "--enable-ftp" "--with-config-file-path=/etc" "--with-mysql=/usr/local/" "--with-sybase=/usr/local/freetds/" "--enable-dba=yes" "--with-gdbm=/usr/local/" "--with-mhash=/usr/local/" "--with-curl=/usr/local/" "--with-zlib=/usr/local/" "--with-gd=/usr/local/"
# Search/replace required for freetds implementation
perl -pi -e 's/dbopen/tdsdbopen/g; s/(DBSETLCHARSET)/\/\/$1/g;' ext/sybase/php_sybase_db.c

# * PHP.ini not considered relevant to this bug report.

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2002-01-09 03:24 UTC] yohgaki@php.net
Supposed to be fixed in CVS.
Please submit bug if you find any problem.


 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sun Dec 22 11:01:30 2024 UTC