Skip to content

in_winevtlog: fix crash when all channels are missing and ignore_missing_channels is enabled - #12318

Open
lecaros wants to merge 2 commits into
masterfrom
lecaros-fix-winevtlog-empty-channels-crash
Open

in_winevtlog: fix crash when all channels are missing and ignore_missing_channels is enabled#12318
lecaros wants to merge 2 commits into
masterfrom
lecaros-fix-winevtlog-empty-channels-crash

Conversation

@lecaros

@lecaros lecaros commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

When a winevtlog input has ignore_missing_channels: true and every
configured channel of the instance fails to subscribe (e.g. a single-channel
instance whose channel does not exist on the host), winevtlog_open_all()
frees the channel list and returns NULL. in_winevtlog_init() tolerates the
NULL when the option is set but still registers the collector, so the first
collection cycle iterates a NULL list (mk_list_foreach dereferences
head->next) and the whole process crashes with an access violation. The
shutdown path (in_winevtlog_exit()winevtlog_close_all(NULL)) crashes
the same way. Running as a Windows service with recovery enabled turns this
into a silent crash/restart loop.

Note: This fix and part of the analysis was done using Fable.

Fixes #12315

Changes:

  • winevtlog_open_all(): when ignore_missing_channels is enabled and no
    channel could be subscribed, return the empty list instead of NULL so
    collect/exit iterate it safely (collecting nothing), which is what the
    option promises.
  • winevtlog_close_all(): NULL guard (protects the exit path).
  • in_winevtlog_collect(): NULL guard on ctx->active_channel (defense in
    depth).
  • New runtime tests tests/runtime/in_winevtlog.c (registered under
    FLB_IN_WINEVTLOG, so they only build on Windows):
    • all_channels_missing_ignored — regression test for this crash: start
      with only a missing channel, survive collect cycles, stop cleanly.
      Crashes the test binary without the fix.
    • multiple_missing_channels_ignored — several missing channels.
    • mixed_channels_ignored — existing (Application) + missing channel
      keeps working (previously-working case, no regression).
    • missing_channel_fails_without_ignore — without the option, init still
      fails as documented.

Behavior without the option is unchanged; the mixed existing+missing case is
unchanged. Only the "option enabled and all channels of the instance
missing" case changes: from a process crash to an idle input.


Enter [N/A] in the box, if an item is not applicable to your change.

Testing
Before we can approve your change; please submit the following in a comment:

  • Example configuration file for the change
service:
  flush: 1
  log_level: debug

pipeline:
  inputs:
    - name: winevtlog
      channels: NonExistentChannel
      ignore_missing_channels: true

  outputs:
    - name: stdout
      match: '*'

Without this patch the process dies with an access violation (exit code
0xC0000005) on the first collection cycle (~1s after start) and also on
shutdown/hot-reload. With the patch it keeps running, collecting nothing
from that instance, and shuts down cleanly. Control case
(channels: Application,NonExistentChannel) behaves the same before and
after the patch.

  • Debug log output from testing the change
debug

C:\support\>C:\dev\fluent-bit\build\bin\fluent-bit.exe -c repro-crash.yml
Fluent Bit v5.1.1
* Copyright (C) 2015-2026 The Fluent Bit Authors
* Fluent Bit is a CNCF graduated project under the Fluent organization
* https://fluentbit.io

______ _                  _    ______ _ _           _____  __
|  ___| |                | |   | ___ (_) |         |  ___|/  |
| |_  | |_   _  ___ _ __ | |_  | |_/ /_| |_  __   _|___ \ `| |
|  _| | | | | |/ _ \ '_ \| __| | ___ \ | __| \ \ / /   \ \ | |
| |   | | |_| |  __/ | | | |_  | |_/ / | |_   \ V //\__/ /_| |_
\_|   |_|\__,_|\___|_| |_|\__| \____/|_|\__|   \_/ \____(_)___/


[2026/08/20 19:12:10.049] [ info] [fluent bit] version=5.1.1, commit=cc313d7204, pid=6780
[2026/08/20 19:12:10.053] [ info] [storage] ver=1.5.4, type=memory, sync=normal, checksum=off, max_chunks_up=128
[2026/08/20 19:12:10.053] [ info] [simd    ] SSE2
[2026/08/20 19:12:10.053] [ info] [cmetrics] version=2.2.1
[2026/08/20 19:12:10.053] [ info] [ctraces ] version=0.7.1
[2026/08/20 19:12:10.055] [ info] [input:winevtlog:winevtlog.0] initializing
[2026/08/20 19:12:10.055] [ info] [input:winevtlog:winevtlog.0] storage_strategy='memory' (memory only)
[2026/08/20 19:12:10.057] [error] [input:winevtlog:winevtlog.0] cannot subscribe 'NonExistentChannel' (15007)
[2026/08/20 19:12:10.067] [ info] [sp] stream processor started
[2026/08/20 19:12:10.072] [ info] [engine] Shutdown Grace Period=5, Shutdown Input Grace Period=2
[2026/08/20 19:12:10.081] [ info] [output:stdout:stdout.0] worker #0 started
[2026/08/20 19:18:50] [engine] caught signal (SIGINT)
[2026/08/20 19:18:50.829] [ warn] [engine] service will shutdown in max 5 seconds
[2026/08/20 19:18:50.829] [ info] [engine] pausing all inputs..
[2026/08/20 19:18:50.829] [ info] [input] pausing winevtlog.0
[2026/08/20 19:18:51.851] [ info] [engine] service has stopped (0 pending tasks)
[2026/08/20 19:18:51.851] [ info] [input] pausing winevtlog.0
[2026/08/20 19:18:51.851] [ info] [output:stdout:stdout.0] thread worker #0 stopping...
[2026/08/20 19:18:51.852] [ info] [output:stdout:stdout.0] thread worker #0 stopped

  • [N/A] Attached Valgrind output that shows no leaks or memory corruption was found

    Valgrind is not available on Windows and in_winevtlog is a Windows-only
    plugin (FLB_IN_WINEVTLOG is set only in cmake/windows-setup.cmake).
    The change removes a NULL dereference and frees nothing new; the empty
    list returned by winevtlog_open_all() is released by the existing
    winevtlog_close_all() call in in_winevtlog_exit().

If this is a change to packaging of containers or native binaries then please confirm it works for all targets.

  • [N/A] Run local packaging test showing all targets (including any new ones) build.
  • [N/A] Set ok-package-test label to test for all targets (requires maintainer to do).

Documentation

  • [N/A] Documentation required for this feature

    No new options or behavior beyond making ignore_missing_channels work
    as already documented when all channels of an instance are missing.

Backporting

  • Backport to latest stable release.

    Requested: this is a crash-loop fix for a released, documented option;
    a separate PR against the current stable branch can follow once this is
    approved.


Fluent Bit is licensed under Apache 2.0, by submitting this pull request I understand that this code will be released under the terms of that license.

Summary by CodeRabbit

  • Bug Fixes

    • Improved handling when configured Windows Event Log channels are missing.
    • Prevented collection failures when all requested channels are unavailable and missing channels are allowed.
    • Ensured mixed available and unavailable channels continue operating correctly.
    • Preserved startup failure behavior when missing channels are not allowed.
  • Tests

    • Added runtime coverage for missing-channel scenarios across multiple collection cycles.

When ignore_missing_channels is enabled and every channel of an input
instance fails to subscribe (e.g. a single configured channel that does
not exist on the host), winevtlog_open_all() freed the channel list and
returned NULL. The plugin tolerated the NULL on init and kept running
with ctx->active_channel == NULL, so the first collection cycle
dereferenced a NULL pointer inside mk_list_foreach() and crashed the
whole process with no log output. The same NULL list was also passed
to winevtlog_close_all() on exit/reload.

Return the empty list instead when missing channels are tolerated, so
collect/exit iterate it safely, and add NULL guards to
in_winevtlog_collect() and winevtlog_close_all() as defense in depth.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: lecaros <lecaros@chronosphere.io>
@coderabbitai

coderabbitai Bot commented Aug 20, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 84987220-0b04-441b-9249-e382976bc204

📥 Commits

Reviewing files that changed from the base of the PR and between 4d23b15 and ad6cc24.

📒 Files selected for processing (4)
  • plugins/in_winevtlog/in_winevtlog.c
  • plugins/in_winevtlog/winevtlog.c
  • tests/runtime/CMakeLists.txt
  • tests/runtime/in_winevtlog.c

Included review availability: Your plan provides up to 8 included reviews per hour; 7 remain after this review.


📝 Walkthrough

Walkthrough

The winevtlog input now safely handles instances where all configured channels are missing. Collection and shutdown guard empty or null channel lists. Windows runtime tests cover tolerated missing channels, mixed channels, repeated collection, shutdown, and strict failure handling.

Changes

Winevtlog empty-channel handling

Layer / File(s) Summary
Handle empty channel lists
plugins/in_winevtlog/winevtlog.c, plugins/in_winevtlog/in_winevtlog.c
winevtlog_open_all returns an empty list when missing channels are ignored. Collection and shutdown return safely for null channel lists.
Validate missing-channel behavior
tests/runtime/CMakeLists.txt, tests/runtime/in_winevtlog.c
Windows runtime tests cover missing and mixed channels, repeated collection cycles, clean shutdown, and failure when missing channels are not ignored.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk: ⚪ Minimal · up to ad6cc

The change safely handles missing winevtlog channels without changing documented behavior for other configurations; no actionable merge-blocking risk remains beyond normal checks and review.

Suggested reviewers: cosmo0920

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 71.43% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 7 functions across 3 files. (1 skipped: 1 unsupported.) Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The changes address issue #12315 by preventing NULL dereferences, preserving tolerated missing-channel behavior, and adding relevant Windows runtime tests.
Out of Scope Changes check ✅ Passed The changes are limited to the winevtlog fix, related cleanup guards, test registration, and focused runtime coverage.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the crash fix for missing channels when ignore_missing_channels is enabled.
✨ Finishing Touches 💡 2
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch lecaros-fix-winevtlog-empty-channels-crash

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ad6cc24389

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +447 to +449
if (!ctx->active_channel) {
return 0;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Fail initialization on non-channel open errors

When ignore_missing_channels is true and winevtlog_open_all() returns NULL for a reason other than an absent channel—for example, query_for_channel() returns -1 for a malformed structured event_query—the unchanged initialization path still accepts that NULL. This guard then makes the collector return forever, so Fluent Bit reports a successful startup while silently ingesting no events. Since the tolerated all-missing case is now represented by a non-NULL empty list, treat a NULL result as fatal during initialization rather than swallowing it here.

Useful? React with 👍 / 👎.

…annels

Add runtime tests for the winevtlog input (Windows-only build):

- all channels of the instance missing with ignore_missing_channels
  The engine must start, survive collection cycles and stop
  cleanly (regression test for the NULL active_channel crash)
- multiple missing channels in one instance
- mixed existing ('Application') and missing channels
- missing channel without ignore_missing_channels keeps failing
  initialization

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: lecaros <lecaros@chronosphere.io>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

in_winevtlog: process crashes (NULL dereference) when ignore_missing_channels is enabled and all channels of an instance are missing

1 participant