Commit 262e19c2 authored by Yury Selivanov's avatar Yury Selivanov

Issue #27759: Fix selectors incorrectly retain invalid file descriptors.

(Backported to 3.4 as this bug might be exploited to for DoS)
parent d97d4fb6
...@@ -399,7 +399,11 @@ if hasattr(select, 'epoll'): ...@@ -399,7 +399,11 @@ if hasattr(select, 'epoll'):
epoll_events |= select.EPOLLIN epoll_events |= select.EPOLLIN
if events & EVENT_WRITE: if events & EVENT_WRITE:
epoll_events |= select.EPOLLOUT epoll_events |= select.EPOLLOUT
self._epoll.register(key.fd, epoll_events) try:
self._epoll.register(key.fd, epoll_events)
except BaseException:
super().unregister(fileobj)
raise
return key return key
def unregister(self, fileobj): def unregister(self, fileobj):
...@@ -465,14 +469,18 @@ if hasattr(select, 'kqueue'): ...@@ -465,14 +469,18 @@ if hasattr(select, 'kqueue'):
def register(self, fileobj, events, data=None): def register(self, fileobj, events, data=None):
key = super().register(fileobj, events, data) key = super().register(fileobj, events, data)
if events & EVENT_READ: try:
kev = select.kevent(key.fd, select.KQ_FILTER_READ, if events & EVENT_READ:
select.KQ_EV_ADD) kev = select.kevent(key.fd, select.KQ_FILTER_READ,
self._kqueue.control([kev], 0, 0) select.KQ_EV_ADD)
if events & EVENT_WRITE: self._kqueue.control([kev], 0, 0)
kev = select.kevent(key.fd, select.KQ_FILTER_WRITE, if events & EVENT_WRITE:
select.KQ_EV_ADD) kev = select.kevent(key.fd, select.KQ_FILTER_WRITE,
self._kqueue.control([kev], 0, 0) select.KQ_EV_ADD)
self._kqueue.control([kev], 0, 0)
except BaseException:
super().unregister(fileobj)
raise
return key return key
def unregister(self, fileobj): def unregister(self, fileobj):
......
...@@ -5,6 +5,7 @@ import selectors ...@@ -5,6 +5,7 @@ import selectors
import signal import signal
import socket import socket
import sys import sys
import tempfile
from test import support from test import support
from time import sleep from time import sleep
import unittest import unittest
...@@ -447,6 +448,16 @@ class EpollSelectorTestCase(BaseSelectorTestCase, ScalableSelectorMixIn): ...@@ -447,6 +448,16 @@ class EpollSelectorTestCase(BaseSelectorTestCase, ScalableSelectorMixIn):
SELECTOR = getattr(selectors, 'EpollSelector', None) SELECTOR = getattr(selectors, 'EpollSelector', None)
def test_register_file(self):
# epoll(7) returns EPERM when given a file to watch
s = self.SELECTOR()
with tempfile.NamedTemporaryFile() as f:
with self.assertRaises(IOError):
s.register(f, selectors.EVENT_READ)
# the SelectorKey has been removed
with self.assertRaises(KeyError):
s.get_key(f)
@unittest.skipUnless(hasattr(selectors, 'KqueueSelector'), @unittest.skipUnless(hasattr(selectors, 'KqueueSelector'),
"Test needs selectors.KqueueSelector)") "Test needs selectors.KqueueSelector)")
...@@ -454,6 +465,18 @@ class KqueueSelectorTestCase(BaseSelectorTestCase, ScalableSelectorMixIn): ...@@ -454,6 +465,18 @@ class KqueueSelectorTestCase(BaseSelectorTestCase, ScalableSelectorMixIn):
SELECTOR = getattr(selectors, 'KqueueSelector', None) SELECTOR = getattr(selectors, 'KqueueSelector', None)
def test_register_bad_fd(self):
# a file descriptor that's been closed should raise an OSError
# with EBADF
s = self.SELECTOR()
bad_f = support.make_bad_fd()
with self.assertRaises(OSError) as cm:
s.register(bad_f, selectors.EVENT_READ)
self.assertEqual(cm.exception.errno, errno.EBADF)
# the SelectorKey has been removed
with self.assertRaises(KeyError):
s.get_key(bad_f)
def test_main(): def test_main():
tests = [DefaultSelectorTestCase, SelectSelectorTestCase, tests = [DefaultSelectorTestCase, SelectSelectorTestCase,
......
...@@ -29,6 +29,9 @@ Library ...@@ -29,6 +29,9 @@ Library
HTTP_PROXY variable when REQUEST_METHOD environment is set, which indicates HTTP_PROXY variable when REQUEST_METHOD environment is set, which indicates
that the script is in CGI mode. that the script is in CGI mode.
- Issue #27759: Fix selectors incorrectly retain invalid file descriptors.
Patch by Mark Williams.
Tests Tests
----- -----
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment