summaryrefslogtreecommitdiff
path: root/src/config/ConfigWatcher.cpp
diff options
context:
space:
mode:
authorIman Seyed <ImanDevel@gmail.com>2025-08-07 12:15:28 -0400
committerGitHub <noreply@github.com>2025-08-07 18:15:28 +0200
commitafbd8796859775a50687daacb254cdd1ba22328f (patch)
tree02886f352205dfb9fca8aa9140b716959f2d70ad /src/config/ConfigWatcher.cpp
parent6a1baa89b1652a8096b261712307e4474d36b4fc (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.cpp35
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;
}
}