platforms/drm: Fix potential stack corruption

If the file descriptor of the DRM device is greater than FD_SETSIZE, the
stack will be corrupted. However, it is highly unlikely that we ever hit
this case because DRM devices are opened at startup of kwin, so the file
descriptors should small.

In order to prevent the potential stack corruption, this change replaces
the usage of select() with poll().

Unlike select(), the api of poll() is much more sensible. Back 20 or so
years ago the main argument against poll() was that it's not implemented
by all platforms. But, nowadays, it's supported on all major platforms.
This commit is contained in:
Vlad Zahorodnii 2021-03-09 10:09:21 +02:00
parent fd68cf3ff4
commit b3e7031893

View file

@ -25,6 +25,7 @@
// system // system
#include <algorithm> #include <algorithm>
#include <errno.h> #include <errno.h>
#include <poll.h>
#include <unistd.h> #include <unistd.h>
// drm // drm
#include <xf86drm.h> #include <xf86drm.h>
@ -339,21 +340,21 @@ void DrmGpu::waitIdle()
if (idle) { if (idle) {
break; break;
} }
fd_set set; pollfd pfds[1];
FD_ZERO(&set); pfds[0].fd = m_fd;
FD_SET(m_fd, &set); pfds[0].events = POLLIN;
timeval timeout;
timeout.tv_sec = 30; const int ready = poll(pfds, 1, 30000);
timeout.tv_usec = 0; if (ready < 0) {
const int descriptorCount = select(m_fd + 1, &set, nullptr, nullptr, &timeout); if (errno != EINTR) {
if (descriptorCount < 0) { qCWarning(KWIN_DRM) << Q_FUNC_INFO << "poll() failed:" << strerror(errno);
qCWarning(KWIN_DRM) << "select() in DrmGpu::waitIdle failed:" << strerror(errno); break;
break; }
} else if (FD_ISSET(m_fd, &set)) { } else if (ready == 0) {
dispatchEvents();
} else {
qCWarning(KWIN_DRM) << "No drm events for gpu" << m_devNode << "within last 30 seconds"; qCWarning(KWIN_DRM) << "No drm events for gpu" << m_devNode << "within last 30 seconds";
break; break;
} else {
dispatchEvents();
} }
}; };
m_socketNotifier->setEnabled(true); m_socketNotifier->setEnabled(true);