Auditd reconfigure using SIGHUP
Bhagwat, Shriniketan Manjunath
shriniketan.bhagwat at hpe.com
Fri Jan 6 06:29:59 UTC 2017
Hi Steve,
Thanks for acknowledging the issue.
In my last email I missed mentioning the fix that I have implemented.
Issue 1) As you said, I have fixed it by replacing the ev_signal by ev_child as below.
struct ev_child sigchld_watcher;
ev_child_init (&sigchld_watcher, child_handler, 0, 0);
ev_child_start (EV_DEFAULT_ &sigchld_watcher);
static void child_handler(EV_P_ ev_child *w, int revents)
{
int pid;
if (w->rpid == dispatcher_pid()) {
dispatcher_reaped();
}
}
Issue 2) In auditd.c main(), child_handler is registered not immediately after init_dispatcher() is called. I have modified the audit to register ev_child immediately after init_dispatcher() as below. Or maybe before calling init_dispatcher(). This fixed issue 2 for me. Below extract is from documentation of libev for ev_child:
" It is permissible to install a child watcher after the child has been forked (which implies it might have already exited), as long as the event loop isn't entered (or is continued from a watcher), i.e., forking and then immediately registering a watcher for the child is fine, but forking and registering a watcher a few event loop iterations later or in the next callback invocation is not."
if (init_dispatcher(&config)) {
if (pidfile)
unlink(pidfile);
tell_parent(FAILURE);
return 1;
}
ev_child_init (&sigchld_watcher, child_handler, 0, 0);
ev_child_start (EV_DEFAULT_ &sigchld_watcher);
Issue 3) With the above fix for issue 2, I did not see the issue 3 getting occurred for me. This could be because shutdown_dispatcher() is called from dispatcher_reaped() where the status on the pipe is not checked.
Regards,
Ketan
-----Original Message-----
From: Steve Grubb [mailto:sgrubb at redhat.com]
Sent: Friday, January 06, 2017 4:12 AM
To: linux-audit at redhat.com
Cc: Bhagwat, Shriniketan Manjunath <shriniketan.bhagwat at hpe.com>
Subject: Re: Auditd reconfigure using SIGHUP
On Thursday, January 5, 2017 11:04:55 AM EST Bhagwat, Shriniketan Manjunath
wrote:
> Greetings,
>
> I was trying to reconfigure the Audit using SIGHUP and came across
> with below behavior of Audit. The audit version I am using is 2.3.6.
I have been able to reproduce the issue. I am still tracing through the problem. As best I can tell, there are at least 3 problems. 1) libev eating the signal - this will be fixed by defining EV_CHILD_ENABLE to 0. This will make all child interference go away; 2) on startup audispd detects no plugins and exits before auditd can register a handler in scenario 2 - this might be fixed with a sigaction handler until libev starts processing events; 3) pipe descriptors being invalid in audispd sometimes. This one is a mystery.
Still investigating. Thanks for reporting this.
-Steve
> Scenario 1: Starting auditd with active audispd plugin.
> 1. Activate the audispd plugin by setting active = yes in
> configuration file
> (example: /etc/audisp/plugins.d/syslog.conf) 2. Start the Auditd.
> Starting auditd will create the both Auditd and Audispd process. 3.
> Deactivate the audispd plugin by setting active = no in configuration
> file. 4. Reconfigure the Auditd by sending SIGHUP to Auditd (>> kill
> -SIGHUP <auditd_pid>). This reconfiguration stops the audispd process.
> 5. Activate the audispd plugin by setting active = yes in
> configuration file. 6. Reconfigure the Auditd by sending SIGHUP to
> Auditd. This should start the audispd process, however audispd process will not be started in this reconfiguration.
>
> Scenario2: Starting auditd with no active audispd plugin.
> 1. Start the Auditd. Starting auditd will create the only Auditd process.
> 2. Activate the audispd plugin by setting active = yes in
> configuration file. 3. Reconfigure the Auditd by sending SIGHUP to
> Auditd. This should start the audispd process, however in few cases
> audispd process will not be started in this reconfiguration. 4.
> Deactivate the audispd plugin by setting active = no in configuration
> file. 5. Reconfigure the Auditd by sending SIGHUP to Auditd. This reconfiguration stops the audispd process.
> 6. Activate the audispd plugin by setting active = yes in
> configuration file. 7. Reconfigure the Auditd by sending SIGHUP to
> Auditd. This should start the audispd process, however audispd process
> will not be started in this reconfiguration.
>
>
> As per the change log of audit version 2.3.2, below fix was made.
>
> Fix: In auditd, restart dispatcher on SIGHUP if it had previously
> exited
>
>
>
> I have analyzed Auditd code of version 2.3.6 and below is my observation.
>
> When the Auditd is started, it calls init_dispatcher() to start the Audispd.
> init_dispatcher() starts the Audispd and maintains its pid value in a
> global variable (auditd-dispatch.c). When the audispd is terminated,
> SIGCHLD handler of Auditd i.e child_handler() does the waitpid() to
> remove the child process from zombie state and calls
> dispatcher_reaped(), where this pid is set to zero. During reconfigure
> using SIGHUP,
> reconfigure_dispatcher() checks for this pid value. If pid is valid
> then, SIGHUP is sent to audispd otherwise init_dispatcher() is called
> to start the audispd.
>
>
> Auditd uses event loop ev_signal to track the child process (SIGCHLD).
> The event loop from libev also has child handler childcb() (in ev.c).
> This handler childcb() also does the waitpid(). When audispd
> terminates, libev's child handler is getting called first, waitpid()
> removes the audispd from zombie state. Then the control is passed to
> Auditd's child handler child_handler(). Since the audispd has been
> already removed from process stable, waitpid() call done in
> child_handler() will return ECHILD. Hence the dispatcher_reaped() is
> not getting called to make the internally maintained pid variable to
> zero. This results in subsequent SIGHUP set to Auditd end up in sending SIGHUP to non-existing audispd process.
>
> In case of step 3 of scenario 2: When the auditd is started without
> any active audispd plugin(step1), Auditd starts the audispd. However
> since there are no active plugins Audispd will get terminated. In this
> case
> shutdown_dispatcher() was called from dispatch_event() where pid value
> was set to zero. Hence the reconfiguration in step 3 started audispd
> process in my case.
>
> I have put traces in auditd code to validate the above behavior. This
> behavior is applicable for Audit version 2.6.4 as well. Is this
> behavior a known issue?
>
> Regards,
> Ketan
More information about the Linux-audit
mailing list