Bug 229381

Summary: reads to /dev/audit aren't interruptible
Product: Base System Reporter: Alan Somers <asomers>
Component: binAssignee: Alan Somers <asomers>
Status: Closed FIXED    
Severity: Affects Some People CC: aniketp, cem, driesm, gnn, rwatson
Priority: --- Flags: asomers: mfc-stable11+
asomers: mfc-stable10+
Version: CURRENT   
Hardware: Any   
OS: Any   

Description Alan Somers freebsd_committer freebsd_triage 2018-06-28 04:16:14 UTC
auditd(8) assumes that read(2)s of /dev/audit are interruptible by signals.  It relies on these reads being interrupted by SIGCHLD, SIGTERM, and SIGHUP.  However, reads of this device aren't actually interruptible.  I don't know why, because audit_read _looks_ like it's doing the right thing.

Symptoms:
1) Sending SIGTERM to auditd doesn't kill it right away; you might send SIGTERM and then send a trigger with auditon(2).
2) Same with SIGHUP
3) Zombie child processes don't get reaped until auditd receives a trigger sent by auditon.  This includes children created by expiring audit trails at auditd startup.
Comment 1 Conrad Meyer freebsd_committer freebsd_triage 2018-06-28 05:38:12 UTC
Experimentally, TERM and HUP interrupt reads from /dev/audit, but not SIGCHLD:

$ sudo cat /dev/audit >/dev/null &
$ sudo pkill -HUP cat

etc.
Comment 2 Alan Somers freebsd_committer freebsd_triage 2018-06-28 06:01:32 UTC
I figured it out.  The signal handler code is helpfully restarting the syscall for me.  read(2) is actually returning to userland, but not to the stack from whence I called it.  I need to use sigaction without SA_RESTART or siginterrupt to fix it.  As is, auditd is using plain signal(), which automatically includes SA_RESTART.
Comment 3 Alan Somers freebsd_committer freebsd_triage 2018-06-28 15:11:36 UTC
Upstream bug: https://github.com/openbsm/openbsm/issues/34
Comment 4 commit-hook freebsd_committer freebsd_triage 2018-07-03 17:37:49 UTC
A commit references this bug:

Author: asomers
Date: Tue Jul  3 17:37:17 UTC 2018
New revision: 335899
URL: https://svnweb.freebsd.org/changeset/base/335899

Log:
  auditd(8): register signal handlers interrutibly

  auditd_wait_for_events() relies on read(2) being interrupted by signals,
  but it registers signal handlers with signal(3), which sets SA_RESTART.
  That breaks asynchronous signal handling. It means that signals don't
  actually get handled until after an audit(8) trigger is received.
  Symptoms include:

  * Sending SIGTERM to auditd doesn't kill it right away; you must send
    SIGTERM and then send a trigger with auditon(2).
  * Same with SIGHUP
  * Zombie child processes don't get reaped until auditd receives a trigger
    sent by auditon. This includes children created by expiring audit trails
    at auditd startup.

  Fix by using sigaction(2) instead of signal(3).

  Cherry pick https://github.com/openbsm/openbsm/commit/d060887

  PR:		229381
  Reviewed by:	cem
  Obtained from:	OpenBSM
  MFC after:	2 weeks
  Differential Revision:	https://github.com/openbsm/openbsm/pull/36

Changes:
  head/contrib/openbsm/bin/auditd/auditd.c
Comment 5 Alan Somers freebsd_committer freebsd_triage 2018-07-10 21:51:45 UTC
*** Bug 229580 has been marked as a duplicate of this bug. ***
Comment 6 Dries Michiels freebsd_committer freebsd_triage 2018-08-03 12:00:36 UTC
Hello,

Is this commit going to be backported to 11-STABLE?
I'm still dealing with this on my system. :)

Thanks
Comment 7 Alan Somers freebsd_committer freebsd_triage 2018-08-03 13:33:50 UTC
Yes, I'll merge it to stable/11.
Comment 8 commit-hook freebsd_committer freebsd_triage 2018-08-03 14:03:58 UTC
A commit references this bug:

Author: asomers
Date: Fri Aug  3 14:03:51 UTC 2018
New revision: 337241
URL: https://svnweb.freebsd.org/changeset/base/337241

Log:
  MFC r335899:

  auditd(8): register signal handlers interrutibly

  auditd_wait_for_events() relies on read(2) being interrupted by signals,
  but it registers signal handlers with signal(3), which sets SA_RESTART.
  That breaks asynchronous signal handling. It means that signals don't
  actually get handled until after an audit(8) trigger is received.
  Symptoms include:

  * Sending SIGTERM to auditd doesn't kill it right away; you must send
    SIGTERM and then send a trigger with auditon(2).
  * Same with SIGHUP
  * Zombie child processes don't get reaped until auditd receives a trigger
    sent by auditon. This includes children created by expiring audit trails
    at auditd startup.

  Fix by using sigaction(2) instead of signal(3).

  Cherry pick https://github.com/openbsm/openbsm/commit/d060887

  PR:		229381
  Reviewed by:	cem
  Obtained from:	OpenBSM
  Differential Revision:	https://github.com/openbsm/openbsm/pull/36

Changes:
_U  stable/11/
  stable/11/contrib/openbsm/bin/auditd/auditd.c
Comment 9 commit-hook freebsd_committer freebsd_triage 2018-08-03 14:37:51 UTC
A commit references this bug:

Author: asomers
Date: Fri Aug  3 14:37:23 UTC 2018
New revision: 337257
URL: https://svnweb.freebsd.org/changeset/base/337257

Log:
  MFC r335899:

  auditd(8): register signal handlers interrutibly

  auditd_wait_for_events() relies on read(2) being interrupted by signals,
  but it registers signal handlers with signal(3), which sets SA_RESTART.
  That breaks asynchronous signal handling. It means that signals don't
  actually get handled until after an audit(8) trigger is received.
  Symptoms include:

  * Sending SIGTERM to auditd doesn't kill it right away; you must send
    SIGTERM and then send a trigger with auditon(2).
  * Same with SIGHUP
  * Zombie child processes don't get reaped until auditd receives a trigger
    sent by auditon. This includes children created by expiring audit trails
    at auditd startup.

  Fix by using sigaction(2) instead of signal(3).

  Cherry pick https://github.com/openbsm/openbsm/commit/d060887

  PR:		229381
  Reviewed by:	cem
  Obtained from:	OpenBSM
  Differential Revision:	https://github.com/openbsm/openbsm/pull/36

Changes:
_U  stable/10/
  stable/10/contrib/openbsm/bin/auditd/auditd.c