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/
prev 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).