Bug #10656: shmop_open permissions incorrect for writing
| From: | phpdev at utopianit dot com | Date: | Fri, 04 May 2001 02:55:44 +0000 |
| Subject: | Bug #10656: shmop_open permissions incorrect for writing | ||
| Groups: | php.dev | ||
| Request: | Send a blank email to php-dev+get-53768@lists.php.net to get a copy of this message | ||
From: phpdev@utopianit.com
IP Address: 203.48.38.170
Operating system: FreeBSD 4.3 (i386)
PHP version: 4.0.5
PHP Bug Type: Unknown/Other Function
Bug description: shmop_open permissions incorrect for writing
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.
--
Edit Bug report at: http://bugs.php.net/?id=10656&edit=1