Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

selectors incorrectly retain invalid file descriptors #71946

Closed
markrwilliams mannequin opened this issue Aug 14, 2016 · 10 comments
Closed

selectors incorrectly retain invalid file descriptors #71946

markrwilliams mannequin opened this issue Aug 14, 2016 · 10 comments

Comments

@markrwilliams
Copy link
Mannequin

markrwilliams mannequin commented Aug 14, 2016

BPO 27759
Nosy @gvanrossum, @vstinner, @1st1, @markrwilliams
PRs
  • [Do Not Merge] Convert Misc/NEWS so that it is managed by towncrier #552
  • Files
  • selectors.patch: selectors.patch
  • selectors.patch
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = None
    closed_at = <Date 2016-09-15.23:33:00.797>
    created_at = <Date 2016-08-14.00:26:49.084>
    labels = ['expert-asyncio']
    title = 'selectors incorrectly retain invalid file descriptors'
    updated_at = <Date 2017-03-31.16:36:37.640>
    user = 'https://github.com/markrwilliams'

    bugs.python.org fields:

    activity = <Date 2017-03-31.16:36:37.640>
    actor = 'dstufft'
    assignee = 'none'
    closed = True
    closed_date = <Date 2016-09-15.23:33:00.797>
    closer = 'yselivanov'
    components = ['asyncio']
    creation = <Date 2016-08-14.00:26:49.084>
    creator = 'Mark.Williams'
    dependencies = []
    files = ['44100', '44102']
    hgrepos = []
    issue_num = 27759
    keywords = ['patch']
    message_count = 10.0
    messages = ['272626', '272629', '272630', '272631', '272632', '272633', '272657', '276639', '276640', '278199']
    nosy_count = 5.0
    nosy_names = ['gvanrossum', 'vstinner', 'python-dev', 'yselivanov', 'Mark.Williams']
    pr_nums = ['552']
    priority = 'normal'
    resolution = 'fixed'
    stage = 'resolved'
    status = 'closed'
    superseder = None
    type = None
    url = 'https://bugs.python.org/issue27759'
    versions = ['Python 3.4', 'Python 3.5', 'Python 3.6']

    @markrwilliams
    Copy link
    Mannequin Author

    markrwilliams mannequin commented Aug 14, 2016

    Registering a file descriptor with EpollSelector.register that epoll(7) refuses results in the selector retaining a SelectorKey for that file descriptor, even though it's not monitored.

    The following program attempts to register a file on the filesystem with an EpollSelector. epoll_ctl(2) returns EPERM when given a such a file descriptor, so it shouldn't be registered with the selector, but it is registered.

    import selectors
    import tempfile
    import traceback
    
    sel = selectors.EpollSelector()
    
    with tempfile.TemporaryFile() as f:
        try:
            sel.register(f, selectors.EVENT_READ)
        except PermissionError:
            traceback.print_exc()
        print("This should have raised a KeyError:", sel.get_key(f))

    It produces this output on Pythons 3.4-3.6:

    Traceback (most recent call last):
      File "/tmp/sel.py", line 9, in <module>
        sel.register(f, selectors.EVENT_READ)
      File "/usr/lib/python3.4/selectors.py", line 402, in register
        self._epoll.register(key.fd, epoll_events)
    PermissionError: [Errno 1] Operation not permitted
    This should have raised a KeyError: SelectorKey(fileobj=<_io.BufferedRandom name=8>, fd=8, events=1, data=None)

    A similar problem exists with KqueueSelector. Consider the following program:

    import selectors
    import tempfile
    import traceback
    
    sel = selectors.KqueueSelector()
    
    f = tempfile.TemporaryFile()
    filedescriptor = f.fileno()
    f.close()

    try:
    sel.register(filedescriptor, selectors.EVENT_READ)
    except OSError:
    traceback.print_exc()

    print("This should have raised a KeyError:", sel.get_key(filedescriptor))

    In this case selectors._fileobj_to_fd doesn't detect that the integer file descriptor is closed.

    Note that _fileobj_to_fd should not be changed! Attempting to use, say, fcntl(fd, fcntl.GET_FD) to detect a closed file descriptor introduces a TOCTTOU bug. Another thread (or another process, if the file descriptor refers to a socket shared between two or more processes and one calls shutdown(2) on it) can change the state of the file descriptor between the time it's checked and the time it's registered. A new file might even be opened and given the previous file descriptor.

    The attached patch catches any exception raised by EpollSelector.register or KqueueSelector.register, removes the SelectorKey from BaseSelector's table, and then re-raises the exception.

    Note that I've included asyncio as an affected component, because asyncio wraps the selectors module.

    @markrwilliams markrwilliams mannequin added the topic-asyncio label Aug 14, 2016
    @gvanrossum
    Copy link
    Member

    Your patch doesn't apply cleanly to the 3.4 or 3.5 branches -- how did you generate it?

    @markrwilliams
    Copy link
    Mannequin Author

    markrwilliams mannequin commented Aug 14, 2016

    Whoops! I pulled from https://github.com/python/cpython and branched off of master. The previous commit was https://github.com/python/cpython/tree/043152b8da83105ff5cba88d4e6ef1d5c64b3602

    I can generate new patches using hg.python.org's 3.4 and 3.5 branches. Please stand by.

    @gvanrossum
    Copy link
    Member

    We only need 3.5; 3.4 is no longer supported.

    @gvanrossum
    Copy link
    Member

    Also don't spend more time on this, I found a way to apply the patch
    cleanly.

    @markrwilliams
    Copy link
    Mannequin Author

    markrwilliams mannequin commented Aug 14, 2016

    OK! Sorry for the trouble.

    On Sat, Aug 13, 2016 at 6:17 PM, Guido van Rossum <report@bugs.python.org>
    wrote:

    Guido van Rossum added the comment:

    Also don't spend more time on this, I found a way to apply the patch
    cleanly.

    ----------


    Python tracker <report@bugs.python.org>
    <http://bugs.python.org/issue27759\>


    @vstinner
    Copy link
    Member

    Regenerated patch to get a review button.

    @python-dev
    Copy link
    Mannequin

    python-dev mannequin commented Sep 15, 2016

    New changeset 8944fd09b9ca by Yury Selivanov in branch '3.5':
    Issue bpo-27759: Fix selectors incorrectly retain invalid file descriptors.
    https://hg.python.org/cpython/rev/8944fd09b9ca

    New changeset 08a75f380699 by Yury Selivanov in branch '3.6':
    Merge 3.5 (issue bpo-27759)
    https://hg.python.org/cpython/rev/08a75f380699

    New changeset ded64b96a4e7 by Yury Selivanov in branch 'default':
    Merge 3.6 (issue bpo-27759)
    https://hg.python.org/cpython/rev/ded64b96a4e7

    @1st1
    Copy link
    Member

    1st1 commented Sep 15, 2016

    I've fixed the remaining review comments & committed the patch. Thank you Mark!

    BTW, this also fixes http://bugs.python.org/issue27386.

    @1st1 1st1 closed this as completed Sep 15, 2016
    @python-dev
    Copy link
    Mannequin

    python-dev mannequin commented Oct 6, 2016

    New changeset 8cc1fca83fb8 by Yury Selivanov in branch '3.4':
    Issue bpo-27759: Fix selectors incorrectly retain invalid file descriptors.
    https://hg.python.org/cpython/rev/8cc1fca83fb8

    @ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Projects
    None yet
    Development

    No branches or pull requests

    3 participants