Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:99813 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 7306 invoked from network); 7 Jul 2017 20:06:49 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 7 Jul 2017 20:06:49 -0000 Authentication-Results: pb1.pair.com smtp.mail=php@list.imperialat.at; spf=pass; sender-id=pass Authentication-Results: pb1.pair.com header.from=php@list.imperialat.at; sender-id=pass Received-SPF: pass (pb1.pair.com: domain list.imperialat.at designates 80.101.55.235 as permitted sender) X-PHP-List-Original-Sender: php@list.imperialat.at X-Host-Fingerprint: 80.101.55.235 mail.imperialat.at Received: from [80.101.55.235] ([80.101.55.235:55786] helo=mail.imperialat.at) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id CC/A3-47109-6D9EF595 for ; Fri, 07 Jul 2017 16:06:47 -0400 Received: from mail.imperialat.at (localhost [127.0.0.1]) by mail.imperialat.at (OpenSMTPD) with ESMTP id 03200ff6; Fri, 7 Jul 2017 22:06:43 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d= list.imperialat.at; h=subject:to:cc:references:from:message-id :date:mime-version:in-reply-to:content-type :content-transfer-encoding; s=deathstar; bh=nPOfcP1C2Gh6j9mfpr3J ukcdopOjgIoQeN791RcfzZQ=; b=fKO5xPXz99yTGv13bOHUqd+as85+TeeAUEVp ygQQhRJT3Zu7LuI/AmMpk4CfhYd2MieNzeSRsPlpdfw0ZCRLcfbdl/iq4w0hir9G ry477+VU0fePoWgILC2e+XWlkYGB1WgxWQWsYFxTDv3J97KW6XkhY/eZzSwOkH3W Xij6w0VZcTeONjUdfnbHJz0M42g+856WQrJe4L/XDjydAfcN7OA1aJGGJZsUHcdx W25TAhCghxsTdA2ayPC+KsGxEeZeDSxRhMueIJTpomsj14+puUJ039EXay6HAbBP jGrObyKVvrYVsE9g5Fvy9/6t5e/lfDmwvv9A2claxONDSlTLPQ== Received: from harrypotter.imperialat.at (192.168.153.157 [192.168.153.157]) by mail.imperialat.at (OpenSMTPD) with ESMTPSA id b96891a8 (TLSv1.2:ECDHE-RSA-CHACHA20-POLY1305:256:NO); Fri, 7 Jul 2017 22:06:43 +0200 (CEST) To: Sara Golemon Cc: Niklas Keller , Bob Weinand , Kalle Sommer Nielsen , Internals References: <105535b4-a629-b2e4-c5e9-a75ff565b054@list.imperialat.at> <0b2f0634-e8af-4e93-5cd4-3471d968cb2c@list.imperialat.at> Message-ID: <3cdf9d19-a0f9-e4bf-f243-8ba501e60d76@list.imperialat.at> Date: Fri, 7 Jul 2017 22:06:42 +0200 User-Agent: Mozilla/5.0 (X11; OpenBSD amd64; rv:52.0) Gecko/20100101 Thunderbird/52.2.1 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8 Content-Language: en-GB Content-Transfer-Encoding: 7bit Subject: Re: [PHP-DEV] Getting fd from stream From: php@list.imperialat.at (Martijn van Duren) On 07/07/17 18:03, Sara Golemon wrote >> The point is, regardless of unix - or tcp sockets, they still have an >> underlying file descriptor, which I need to specify to the child, so >> that they can start using it. Ergo, I need to find a way to export this >> from the stream into PHP. >> > You misunderstand, I'm not saying to create a unix socket and try to > pass that open pair to the child. I'm saying listen on a unix domain > socket on the file system and tell the children what the path is. > They can all individually then open streams to the parent using the > path. That would be an extremely ugly solution. You would create overhead for 1, and 2, you leave open the possibility that an arbitrary application (bound to the filesystem permissions) allows to connect to it during the time the socket is listening. See [0] for what can go wrong with a similar solutions. > > Psuedo code: > // parent > $mysocket = 'unix://tmp/parent.sock'; > $server = stream_socket_server($mysocket); > spawn_child('child_proc --sock='.escapeshellarg($mysocket)); > $child = stream_socket_accept($server); > var_dump(fgets($child)); // string (8) "Hi mom!\n" > > // child > $parentssocket = parseCliArg('sock'); > $stream = stream_socket_client($parentssocket); > fwrite($stream, "Hi mom!\n"); > > > Then the children can each report their own listening sockets to the > parent and the parent can provide a lookup for siblings to find each > other and allow them to open sockets to each other. > > Trying to pass a meaningless number to the child that it can't do > anything with isn't going to work. That's the whole point. They're not meaningless numbers, they're the actual references that the kernel exposes to the process for file access: $ cd /tmp $ cat test.php $ cat test.c #include #include #include int main(int argc, char *argv[]) { extern char *optarg; int ch; int fd = -1; int readbytes; char buf[sizeof("hello world")]; while ((ch = getopt(argc, argv, "i:")) != -1) { switch(ch) { case 'i': fd = atoi(optarg); break; default: fprintf(stderr, "wrong parameter\n"); exit(1); } } readbytes = read(fd, buf, sizeof(buf)); buf[readbytes] = '\0'; printf("read: %s\n", buf); } $ gcc ./test.c -o test && php ./test.php read: hello world $ cat test.c #include #include #include #include #include #include int main(int argc, char *argv[]) { int sp[2]; char *fd; extern int errno; socketpair(AF_UNIX, SOCK_STREAM, 0, sp); switch(fork()) { case -1: exit(1); case 0: close(sp[1]); asprintf(&fd, "%d", sp[0]); execl("/usr/bin/env", "/usr/bin/env", "php", "/tmp/test2.php", "-i", fd, NULL); default: close(sp[0]); write(sp[1], "hello world", sizeof("hello world")); } } $ cat test2.php $arg) { switch($opt) { case "i": $fd = fopen("php://fd/" . $arg, "r"); break; default: trigger_error("wrong parameter", E_USER_ERROR); } } $buf = fread($fd, 11); echo "read: " . $buf . "\n"; $ gcc ./test2.c -o ./test2 && ./test2 read: hello world Don't mind the crummy C here, it's for illustration purposes only. As you can see, these "meaningless numbers" allow me to connect two applications written in two completely different languages without setting up any external listening system. The problem here is that for test.php I had to hardcode the value 3 because I don't know how to retrieve it from $sp[0]. This only works in a default shell where only stdin, stdout and stderr (fd0, fd1 and fd2) are set. The kernel allocates the next free fd, which happens to have number 3. As soon as I would execute it like: php ./test.php < ./test.c it would fail, because fd3 would be taken by a handle to test.c and $sp[0] would be allocated on 4. > -Sara > [0] https://legalhackers.com/videos/MySQL-MariaDB-PerconaDB-PrivEsc-Race-CVE-2016-6663-5616-6664-5617-Exploits.html