linux-api.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Michael Kerrisk (man-pages)" <mtk.manpages-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
To: Matthew Wilcox <willy-wEGCiKHe2LqWVfeAwA7xHQ@public.gmane.org>,
	linux-api-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Cc: mtk.manpages-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org,
	linux-fsdevel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	Carlos O'Donell <carlos-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
Subject: Re: select fails to verify all file descriptors are valid
Date: Fri, 24 Mar 2017 15:40:49 +0100	[thread overview]
Message-ID: <85d50ac0-3bf0-0e2c-4a89-dfffa54c4f4d@gmail.com> (raw)
In-Reply-To: <20170314161138.GC4033-PfSpb0PWhxZc2C7mugBRk2EX/6BAtgUQ@public.gmane.org>

Hi Matthew,

On 03/14/2017 05:11 PM, Matthew Wilcox wrote:
> 
> Quoting the manpage:
> 
>        int select(int nfds, fd_set *readfds, fd_set *writefds,
>                   fd_set *exceptfds, struct timeval *timeout);
> 
>        nfds  is the highest-numbered file descriptor in any of the three sets,
>        plus 1.
> 
>        EBADF  An  invalid file descriptor was given in one of the sets.  (Per‐
>               haps a file descriptor that was already closed, or one on  which
>               an error has occurred.)
> 
> That's not quite how Linux behaves.  We only check the fd_set up to the
> maximum number of fds allocated to this task:
> 
>         rcu_read_lock();
>         fdt = files_fdtable(current->files);
>         max_fds = fdt->max_fds;
>         rcu_read_unlock();
>         if (n > max_fds)
>                 n = max_fds;
> 
> (then we copy in up to 'n' bits worth of bitmaps).
>
> It is pretty straightforward to demonstrate that Linux doesn't check:
> 
> int main(void)
> {
> 	int ret;
> 	struct timeval tv = { };
> 	fd_set fds;
> 	FD_ZERO(&fds);
> 	FD_SETFD(FD_SETSIZE - 1, &fds);
> 	ret = select(FD_SETSIZE, &fds, NULL, NULL, &tv);
> 	assert(ret == -1 && errno == EBADF);
> 	return 0;
> }
> 
> Linux has behaved this way since 2.6.12, and I can't be bothered to get
> out the historical git trees to find out what happened before 2005.

Looking back, this behavior seems to have been present at least as far 
back as 2.4.0:

        if (n > current->files->max_fdset)
                n = current->files->max_fdset;

My reading on the 2.2.0 source suggests this odd behavior did not 
occur there.

> So ... if I change this behaviour by checking all the file descriptors, I
> do stand a chance of breaking an application.  On the other hand, that
> application could already have been broken by the shell deciding to open
> a really high file descriptor (I'm looking at you, bash), which the program
> then inherits.

I'm not sure that bash's FD 255 oddity is a problem here, since the 
close-on-exec flag is set on that FD.

> Worth fixing this bug?  Worth documenting this bug, at least?

Certainly worth documenting. Fixing? I'm less sure. But, Carlos does
have a point about POSIX...

I've updated the man page to say:

       nfds  should be set to the highest-numbered file descriptor in any
       of the three sets, plus 1.  The indicated file descriptors in each
       set are checked, up to this limit (but see BUGS).

       ...

       EBADF  An  invalid  file  descriptor was given in one of the sets.
              (Perhaps a file descriptor that was already closed, or  one
              on which an error has occurred.)  However, see BUGS.
       ...

   BUGS
       According  to  POSIX,  select()  should  check  all specified file
       descriptors in the three file descriptor sets,  up  to  the  limit
       nfds-1.   However,  the  current  implementation  ignores any file
       descriptor in these sets that is greater  than  the  maximum  file
       descriptor  number that the process currently has open.  According
       to POSIX, any such file descriptor that is specified in one of the
       sets should result in the error EBADF.

Cheers,

Michael

> --
> To unsubscribe from this list: send the line "unsubscribe linux-api" in
> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 


-- 
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
Linux/UNIX System Programming Training: http://man7.org/training/

      parent reply	other threads:[~2017-03-24 14:40 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-03-14 16:11 select fails to verify all file descriptors are valid Matthew Wilcox
2017-03-15  5:34 ` Carlos O'Donell
     [not found]   ` <4859e5e8-4cc1-626c-3294-e5f529fe41d3-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2017-03-24 14:41     ` Michael Kerrisk (man-pages)
     [not found] ` <20170314161138.GC4033-PfSpb0PWhxZc2C7mugBRk2EX/6BAtgUQ@public.gmane.org>
2017-03-24 14:40   ` Michael Kerrisk (man-pages) [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=85d50ac0-3bf0-0e2c-4a89-dfffa54c4f4d@gmail.com \
    --to=mtk.manpages-re5jqeeqqe8avxtiumwx3w@public.gmane.org \
    --cc=carlos-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org \
    --cc=linux-api-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=linux-fsdevel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=willy-wEGCiKHe2LqWVfeAwA7xHQ@public.gmane.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).