1 /* auditd-dispatch.c --
2 * Copyright 2005-07,2013 Red Hat Inc., Durham, North Carolina.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 * Steve Grubb <sgrubb@redhat.com>
21 * Junji Kanemaru <junji.kanemaru@linuon.com>
35 #include "auditd-dispatch.h"
37 /* This is the communications channel between auditd & the dispatcher */
38 static int disp_pipe[2] = {-1, -1};
40 static int n_errs = 0;
41 #define REPORT_LIMIT 10
43 int dispatcher_pid(void)
48 void dispatcher_reaped(void)
50 audit_msg(LOG_INFO, "dispatcher %d reaped\n", pid);
52 shutdown_dispatcher();
55 /* set_flags: to set flags to file desc */
56 static int set_flags(int fn, int flags)
60 if ((fl = fcntl(fn, F_GETFL, 0)) < 0) {
61 audit_msg(LOG_ERR, "fcntl failed. Cannot get flags (%s)\n",
68 return fcntl(fn, F_SETFL, fl);
71 /* This function returns 1 on error & 0 on success */
72 int init_dispatcher(const struct daemon_conf *config)
76 if (config->dispatcher == NULL)
79 if (socketpair(AF_UNIX, SOCK_STREAM, 0, disp_pipe)) {
80 audit_msg(LOG_ERR, "Failed creating disp_pipe");
84 /* Make both disp_pipe non-blocking */
85 if (config->qos == QOS_NON_BLOCKING) {
86 if (set_flags(disp_pipe[0], O_NONBLOCK) < 0 ||
87 set_flags(disp_pipe[1], O_NONBLOCK) < 0) {
88 audit_msg(LOG_ERR, "Failed to set O_NONBLOCK flag");
97 dup2(disp_pipe[0], 0);
100 sigfillset (&sa.sa_mask);
101 sigprocmask (SIG_UNBLOCK, &sa.sa_mask, 0);
103 execl(config->dispatcher, config->dispatcher, NULL);
104 audit_msg(LOG_ERR, "exec() failed");
113 /* Avoid leaking this */
114 if (fcntl(disp_pipe[1], F_SETFD, FD_CLOEXEC) < 0) {
116 "Failed to set FD_CLOEXEC flag");
119 audit_msg(LOG_INFO, "Started dispatcher: %s pid: %u",
120 config->dispatcher, pid);
127 void shutdown_dispatcher(void)
133 // if not in time, send sigkill
137 if (disp_pipe[0] >= 0) {
141 if (disp_pipe[1] >= 0) {
147 void reconfigure_dispatcher(const struct daemon_conf *config)
149 // signal child or start it so it can see if config changed
153 init_dispatcher(config);
156 /* Returns -1 on err, 0 on success, and 1 if eagain occurred and not an err */
157 int dispatch_event(const struct audit_reply *rep, int is_err)
161 struct audit_dispatcher_header hdr;
163 if (disp_pipe[1] == -1)
166 // Don't send reconfig or rotate as they are purely internal to daemon
167 if (rep->type == AUDIT_DAEMON_RECONFIG ||
168 rep->type == AUDIT_DAEMON_ROTATE)
171 hdr.ver = AUDISP_PROTOCOL_VER; /* Hard-coded to current protocol */
172 hdr.hlen = sizeof(struct audit_dispatcher_header);
173 hdr.type = rep->type;
176 vec[0].iov_base = (void*)&hdr;
177 vec[0].iov_len = sizeof(hdr);
178 vec[1].iov_base = (void*)rep->message;
179 vec[1].iov_len = rep->len;
182 rc = writev(disp_pipe[1], vec, 2);
183 } while (rc < 0 && errno == EAGAIN && count++ < 8);
185 // close pipe if no child or peer has been lost
187 if (errno == EPIPE) {
188 shutdown_dispatcher();
190 } else if (errno == EAGAIN && !is_err) {
193 if (n_errs <= REPORT_LIMIT) {
195 "dispatch err (%s) event lost",
196 errno == EAGAIN ? "pipe full" :
200 if (n_errs == REPORT_LIMIT) {
202 "dispatch error reporting limit"
203 " reached - ending report"