Skip to content

fix: close the read end of piped logs in every child - #3676

Open
fzipi wants to merge 1 commit into
owasp-modsecurity:v2/masterfrom
fzipi:v2/issue-2822-piped-log-read-fd
Open

fzipi wants to merge 1 commit into
owasp-modsecurity:v2/masterfrom
fzipi:v2/issue-2822-piped-log-read-fd

Conversation

@fzipi

@fzipi fzipi commented Oct 13, 2026

Copy link
Copy Markdown
Collaborator

What

SecAuditLog, SecAuditLog2 and SecGuardianLog open their |program pipes with ap_open_piped_log() while the configuration is read. The read ends of those pipes are now remembered (apache2/apache2_config.c) and closed from the child_init hook (apache2/mod_security2.c), which is what httpd does for its own piped logs in ap_logs_child_init().

Why

httpd keeps a list of piped-log read ends to close in every child, but that list is reset by a cleanup on the plog pool, which runs after the configuration (and therefore after our directives) has been read. So every worker inherits the read end of ModSecurity's pipes. A worker that holds the read end of a pipe never gets EPIPE when the logger process is gone, and once the pipe buffer is full it blocks in write() for ever; that is the hang during graceful restart reported in #2822 (backtrace in sec_auditlog_write).

Tests

Verified in a Debian bookworm container (apache2 2.4.62, prefork) with SecAuditLog "|/usr/bin/rotatelogs ...", listing which processes hold the pipe rotatelogs reads from:

untouched v2/master
  pid 2013 (apache2, parent)  fds 4 5
  pid 2014 (rotatelogs)       fd  0
  pid 2016 (apache2, worker)  fds 4 5     <- read end still open in the worker
  pid 2017 (apache2, worker)  fds 4 5

this branch
  pid 2013 (apache2, parent)  fds 4 5     (parent keeps it to respawn the logger)
  pid 2014 (rotatelogs)       fd  0
  pid 2016 (apache2, worker)  fd  5       <- write end only
  pid 2017 (apache2, worker)  fd  5

Requests, kill -9 of rotatelogs and a graceful restart behave the same on both (the hang itself needs a full pipe buffer in an old-generation worker, which this short test does not drive). No regression test: the harness has no way to inspect worker file descriptors.

References

Fixes #2822

🤖 Generated with Claude Code

SecAuditLog, SecAuditLog2 and SecGuardianLog open their "|program"
pipes with ap_open_piped_log() while the configuration is read. httpd
closes the read end of its own piped logs in each child
(ap_logs_child_init), but that list is rebuilt after the configuration
pool is cleared, so the read ends opened by ModSecurity stay open in
every worker. A worker holding the read end of a pipe never gets EPIPE
when the logger process dies, and after a graceful restart it blocks in
write() for ever, which is the hang reported in owasp-modsecurity#2822.

The read ends are now remembered when the pipes are opened and closed
from the child_init hook, mirroring what httpd does for its own logs.

Fixes owasp-modsecurity#2822

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0181jBv5JdNQviwDzfnkf1Gy
@coderabbitai

coderabbitai Bot commented Oct 13, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 3ffe3cfa-2cae-4469-b9e3-927b80fbdb2a

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

@sonarqubecloud

Copy link
Copy Markdown

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant