diff options
| author | Iman Seyed <ImanDevel@gmail.com> | 2025-08-07 12:15:28 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-08-07 18:15:28 +0200 |
| commit | afbd8796859775a50687daacb254cdd1ba22328f (patch) | |
| tree | 02886f352205dfb9fca8aa9140b716959f2d70ad /src/config/ConfigWatcher.cpp | |
| parent | 6a1baa89b1652a8096b261712307e4474d36b4fc (diff) | |
configWatcher: fix inotify event reading buffer size (#11337)
Read full variable-length inotify_event structure instead of just the
fixed-size header. The previous code only read sizeof(inotify_event)
bytes, missing the trailing name field, which could cause truncated
events and undefined behavior.
Diffstat (limited to 'src/config/ConfigWatcher.cpp')
| -rw-r--r-- | src/config/ConfigWatcher.cpp | 35 |
1 files changed, 26 insertions, 9 deletions
diff --git a/src/config/ConfigWatcher.cpp b/src/config/ConfigWatcher.cpp index e5db1e86..ecbee205 100644 --- a/src/config/ConfigWatcher.cpp +++ b/src/config/ConfigWatcher.cpp @@ -65,17 +65,34 @@ void CConfigWatcher::setOnChange(const std::function<void(const SConfigWatchEven } void CConfigWatcher::onInotifyEvent() { - inotify_event ev; - while (read(m_inotifyFd.get(), &ev, sizeof(ev)) > 0) { - const auto WD = std::ranges::find_if(m_watches.begin(), m_watches.end(), [wd = ev.wd](const auto& e) { return e.wd == wd; }); + constexpr size_t BUFFER_SIZE = sizeof(inotify_event) + NAME_MAX + 1; + alignas(inotify_event) std::array<char, BUFFER_SIZE> buffer = {}; + const ssize_t bytesRead = read(m_inotifyFd.get(), buffer.data(), buffer.size()); + if (bytesRead <= 0) + return; + + for (size_t offset = 0; offset < (size_t)bytesRead;) { + const auto* ev = (const inotify_event*)(buffer.data() + offset); - if (WD == m_watches.end()) { - Debug::log(ERR, "CConfigWatcher: got an event for wd {} which we don't have?!", ev.wd); - return; + if (offset + sizeof(inotify_event) > (size_t)bytesRead) { + Debug::log(ERR, "CConfigWatcher: malformed inotify event, truncated header"); + break; } - m_watchCallback(SConfigWatchEvent{ - .file = WD->file, - }); + if (offset + sizeof(inotify_event) + ev->len > (size_t)(bytesRead)) { + Debug::log(ERR, "CConfigWatcher: malformed inotify event, truncated name field"); + break; + } + + const auto WD = std::ranges::find_if(m_watches, [wd = ev->wd](const auto& e) { return e.wd == wd; }); + + if (WD == m_watches.end()) + Debug::log(ERR, "CConfigWatcher: got an event for wd {} which we don't have?!", ev->wd); + else + m_watchCallback(SConfigWatchEvent{ + .file = WD->file, + }); + + offset += sizeof(inotify_event) + ev->len; } } |
