On Fri, Dec 02, 2016 at 08:41:21AM +0100, Samuel Thibault wrote:
> About the port leak in select discussed on IRC, I checked history a bit,
> this (000ef460744786571f51604e6de631b7168e239a):
> 
> -      if (d[i].type)
> +      if (d[i].type & ~SELECT_ERROR)
>         __mach_port_destroy (__mach_task_self (), d[i].reply_port);
> 
> was added when handling EBADF , for which there is no reply port to
> destroy. Then I added this (099f8d2b7ecedc4f6fc895d2c35912f995289c24):

Indeed, so type != 0 doesn't imply port creation.

> I guess we could simply do this:
> 
>       for (i = firstfd; i <= lastfd; ++i)
> -             if (d[i].type & ~SELECT_ERROR)
> +             if (d[i].type & SELECT_ERROR)
> +               {
> +                 d[i].reply_port = MACH_PORT_NULL;
> +             }
>             else
>                 {
>                   int type = d[i].type;
>                   d[i].reply_port = __mach_reply_port ();
> 
> as well as in the error case of __io_select_request, and then just check
> against MACH_PORT_NULL before destroy.

So the condition would look like

if (d[i].type && (d[i].reply_port != MACH_PORT_NULL))

I agree.

In the mean time, I've built libc packages that partially fix the issue
(there will still be spurious destruction attempts on EBADF, which could
destroy a legitimate right) but the leak is so severe I found it useful.

If you want those, add

deb http://ftp.sceen.net/debian sid main

to sources.list, and add the GPG key D50E6AD4 to APT.

-- 
Richard Braun

Reply via email to