diff options
author | Gustavo Lopes <glopes@nebm.ist.utl.pt> | 2013-07-16 00:03:00 +0200 |
---|---|---|
committer | Gustavo Lopes <glopes@nebm.ist.utl.pt> | 2013-07-16 00:03:00 +0200 |
commit | 2443df37fd1e4999091881d3ad12c6e7e03dbfab (patch) | |
tree | 1e10d715aed595e233d64444062a58e5aaca19a3 | |
parent | fb91fc6e2c6a8c6f96aa71f968efe9f712d9cc82 (diff) | |
parent | ceecfaff5ac793d50426ae051fd4bec932d23bb1 (diff) | |
download | php-git-2443df37fd1e4999091881d3ad12c6e7e03dbfab.tar.gz |
Merge branch 'PHP-5.5'
* PHP-5.5:
NEWS for 710150c and e2744f1
socket: support unix paths in the abstract namespace
socket: fix bug #65260 (SCM_RIGHTS)
-rw-r--r-- | ext/sockets/conversions.c | 37 | ||||
-rw-r--r-- | ext/sockets/sockets.c | 21 | ||||
-rw-r--r-- | ext/sockets/tests/socket_abstract_path.phpt | 44 | ||||
-rw-r--r-- | ext/sockets/tests/socket_abstract_path_sendmsg.phpt | 40 | ||||
-rw-r--r-- | ext/sockets/tests/socket_cmsg_rights.phpt | 1 |
5 files changed, 130 insertions, 13 deletions
diff --git a/ext/sockets/conversions.c b/ext/sockets/conversions.c index ea1c95201f..ed55ed52fa 100644 --- a/ext/sockets/conversions.c +++ b/ext/sockets/conversions.c @@ -98,8 +98,8 @@ typedef struct { } field_descriptor; #define KEY_FILL_SOCKADDR "fill_sockaddr" -#define KEY_RECVMSG_RET "recvmsg_ret" -#define KEY_CMSG_LEN "cmsg_len" +#define KEY_RECVMSG_RET "recvmsg_ret" +#define KEY_CMSG_LEN "cmsg_len" const struct key_value empty_key_value_list[] = {{0}}; @@ -223,6 +223,7 @@ static unsigned from_array_iterate(const zval *arr, char buf[sizeof("element #4294967295")]; char *bufp = buf; + /* Note i starts at 1, not 0! */ for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(arr), &pos), i = 1; !ctx->err.has_error && zend_hash_get_current_data_ex(Z_ARRVAL_P(arr), (void **)&elem, &pos) == SUCCESS; @@ -666,6 +667,13 @@ static void from_zval_write_sun_path(const zval *path, char *sockaddr_un_c, ser_ path = &lzval; } + /* code in this file relies on the path being nul terminated, even though + * this is not required, at least on linux for abstract paths. It also + * assumes that the path is not empty */ + if (Z_STRLEN_P(path) == 0) { + do_from_zval_err(ctx, "%s", "the path is cannot be empty"); + return; + } if (Z_STRLEN_P(path) >= sizeof(saddr->sun_path)) { do_from_zval_err(ctx, "the path is too long, the maximum permitted " "length is %ld", sizeof(saddr->sun_path) - 1); @@ -767,10 +775,22 @@ static void from_zval_write_sockaddr_aux(const zval *container, return; } *sockaddr_ptr = accounted_ecalloc(1, sizeof(struct sockaddr_un), ctx); - *sockaddr_len = sizeof(struct sockaddr_un); if (fill_sockaddr) { + struct sockaddr_un *sock_un = (struct sockaddr_un*)*sockaddr_ptr; + from_zval_write_sockaddr_un(container, (char*)*sockaddr_ptr, ctx); (*sockaddr_ptr)->sa_family = AF_UNIX; + + /* calculating length is more complicated here. Giving the size of + * struct sockaddr_un here and relying on the nul termination of + * sun_path does not work for paths in the abstract namespace. Note + * that we always assume the path is not empty and nul terminated */ + *sockaddr_len = offsetof(struct sockaddr_un, sun_path) + + (sock_un->sun_path[0] == '\0' + ? (1 + strlen(&sock_un->sun_path[1])) + : strlen(sock_un->sun_path)); + } else { + *sockaddr_len = sizeof(struct sockaddr_un); } break; @@ -869,7 +889,14 @@ static void from_zval_write_control(const zval *arr, } if (entry->calc_space) { - data_len = entry->calc_space(arr, ctx); + zval **data_elem; + /* arr must be an array at this point */ + if (zend_hash_find(Z_ARRVAL_P(arr), "data", sizeof("data"), + (void**)&data_elem) == FAILURE) { + do_from_zval_err(ctx, "cmsghdr should have a 'data' element here"); + return; + } + data_len = entry->calc_space(*data_elem, ctx); if (ctx->err.has_error) { return; } @@ -1370,7 +1397,7 @@ static void from_zval_write_fd_array_aux(zval **elem, unsigned i, void **args, s return; } - if (php_stream_cast(stream, PHP_STREAM_AS_FD, (void **)&iarr[i], + if (php_stream_cast(stream, PHP_STREAM_AS_FD, (void **)&iarr[i - 1], REPORT_ERRORS) == FAILURE) { do_from_zval_err(ctx, "cast stream to file descriptor failed"); return; diff --git a/ext/sockets/sockets.c b/ext/sockets/sockets.c index 801af0a4dd..b226d94715 100644 --- a/ext/sockets/sockets.c +++ b/ext/sockets/sockets.c @@ -1479,7 +1479,7 @@ PHP_FUNCTION(socket_strerror) PHP_FUNCTION(socket_bind) { zval *arg1; - php_sockaddr_storage sa_storage; + php_sockaddr_storage sa_storage = {0}; struct sockaddr *sock_type = (struct sockaddr*) &sa_storage; php_socket *php_sock; char *addr; @@ -1497,10 +1497,19 @@ PHP_FUNCTION(socket_bind) case AF_UNIX: { struct sockaddr_un *sa = (struct sockaddr_un *) sock_type; - memset(sa, 0, sizeof(sa_storage)); + sa->sun_family = AF_UNIX; - snprintf(sa->sun_path, 108, "%s", addr); - retval = bind(php_sock->bsd_socket, (struct sockaddr *) sa, SUN_LEN(sa)); + + if (addr_len >= sizeof(sa->sun_path)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "Invalid path: too long (maximum size is %d)", + (int)sizeof(sa->sun_path) - 1); + RETURN_FALSE; + } + memcpy(&sa->sun_path, addr, addr_len); + + retval = bind(php_sock->bsd_socket, (struct sockaddr *) sa, + offsetof(struct sockaddr_un, sun_path) + addr_len); break; } @@ -1508,8 +1517,6 @@ PHP_FUNCTION(socket_bind) { struct sockaddr_in *sa = (struct sockaddr_in *) sock_type; - memset(sa, 0, sizeof(sa_storage)); /* Apparently, Mac OSX needs this */ - sa->sin_family = AF_INET; sa->sin_port = htons((unsigned short) port); @@ -1525,8 +1532,6 @@ PHP_FUNCTION(socket_bind) { struct sockaddr_in6 *sa = (struct sockaddr_in6 *) sock_type; - memset(sa, 0, sizeof(sa_storage)); /* Apparently, Mac OSX needs this */ - sa->sin6_family = AF_INET6; sa->sin6_port = htons((unsigned short) port); diff --git a/ext/sockets/tests/socket_abstract_path.phpt b/ext/sockets/tests/socket_abstract_path.phpt new file mode 100644 index 0000000000..816e5c11bb --- /dev/null +++ b/ext/sockets/tests/socket_abstract_path.phpt @@ -0,0 +1,44 @@ +--TEST-- +Support for paths in the abstract namespace (bind, connect) +--SKIPIF-- +<?php +if (!extension_loaded('sockets')) + die('skip sockets extension not available.'); + +if (PHP_OS != 'Linux') { + die('skip For Linux only'); +} +?> +--FILE-- +<?php +include __DIR__."/mcast_helpers.php.inc"; + +$path = "\x00/foo_bar"; + +echo "creating server socket\n"; +$servers = socket_create(AF_UNIX, SOCK_STREAM, 0) or die("err"); +socket_bind($servers, $path) or die("Could not bind"); +socket_listen($servers) or die("Could not listen"); +socket_set_nonblock($servers) or die("Could not put in non-blocking mode"); + +echo "creating client socket\n"; +$clients = socket_create(AF_UNIX, SOCK_STREAM, 0) or die("err"); +socket_connect($clients, $path) or die("Error connecting"); + +$conns = socket_accept($servers) or die("Could not accept connection"); + +$r = socket_sendmsg($clients, [ + //"name" => [ "addr" => $path, ], + "iov" => ["test ", "thing", "\n"], +], 0); +var_dump($r); +checktimeout($conns, 500); + +if (!socket_recv($conns, $buf, 20, 0)) die("recv"); +print_r($buf); +?> +--EXPECTF-- +creating server socket +creating client socket +int(11) +test thing diff --git a/ext/sockets/tests/socket_abstract_path_sendmsg.phpt b/ext/sockets/tests/socket_abstract_path_sendmsg.phpt new file mode 100644 index 0000000000..5a9275a26b --- /dev/null +++ b/ext/sockets/tests/socket_abstract_path_sendmsg.phpt @@ -0,0 +1,40 @@ +--TEST-- +Support for paths in the abstract namespace (bind, sendmsg, recvmsg) +--SKIPIF-- +<?php +if (!extension_loaded('sockets')) + die('skip sockets extension not available.'); + +if (PHP_OS != 'Linux') { + die('skip For Linux only'); +} +?> +--FILE-- +<?php +include __DIR__."/mcast_helpers.php.inc"; + +$path = "\x00/bar_foo"; + +echo "creating send socket\n"; +$sends1 = socket_create(AF_UNIX, SOCK_DGRAM, 0) or die("err"); +socket_set_nonblock($sends1) or die("Could not put in non-blocking mode"); + +echo "creating receive socket\n"; +$s = socket_create(AF_UNIX, SOCK_DGRAM, 0) or die("err"); +socket_bind($s, $path) or die("err"); + +$r = socket_sendmsg($sends1, [ + "name" => [ "path" => $path], + "iov" => ["test ", "thing", "\n"], +], 0); +var_dump($r); +checktimeout($s, 500); + +if (!socket_recv($s, $buf, 20, 0)) die("recv"); +print_r($buf); +?> +--EXPECTF-- +creating send socket +creating receive socket +int(11) +test thing diff --git a/ext/sockets/tests/socket_cmsg_rights.phpt b/ext/sockets/tests/socket_cmsg_rights.phpt index 8290f03880..8c1734a568 100644 --- a/ext/sockets/tests/socket_cmsg_rights.phpt +++ b/ext/sockets/tests/socket_cmsg_rights.phpt @@ -84,6 +84,7 @@ Array [0] => Resource id #%d [1] => Resource id #%d [2] => Resource id #%d + [3] => Resource id #%d ) ) |