The kernel/userspace boundary for logging signals to auditd is quite
crappy (to be polite) it is racy and doesn't send all the information
that might be nice to have. It's also built around binary data flying
back and forth with no way for userspace to know precisely what
information it is being given. We also don't currently know if the
signal info we got from the kernel is actually even for the signal we
are auditing. Onward:
This patch adds a new audit message AUDIT_SIG_INFO_VERS. This new
message sends data back and forth and at version one looks like
/* version then sig MUST be the first 2 fields of all sig_info versions */
struct audit_sig_info_ver1 {
__u32 version;
__u32 sig;
uid_t uid;
uid_t auid;
pid_t pid;
__u32 session;
char ctx[0];
};
This message MUST maintain binary compatability in the first 2 fields.
As long as version and signal don't move we can easily support arbitrary
new information across this boundary. Userspace can tell the kernel
what version of data it can support and the kernel can do the same.
Compatibility on both ends is done easily by casting the data to the
right version structure and then proceeding from there.
This is backwards compatible to current kernels and the only user
visible change will be that new signal messages will have the new
fields:
type=DAEMON_RESUME msg=audit(1208370239.512:8484): auditd signal from uid=-1 auid=0 ses=-1
pid=24063 subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
and there will be some SELINUX_ERR messages that selinux didn't know how
to handle the new audit message type.
New kernel + old auditd won't have anything changes.
New kernel + new auditd will be like above only uid and ses will be
filled out.
Comments?
---
diff -Naupr audit-1.7.orig/lib/libaudit.c audit-1.7/lib/libaudit.c
--- audit-1.7.orig/lib/libaudit.c 2008-03-24 13:46:19.000000000 -0400
+++ audit-1.7/lib/libaudit.c 2008-04-13 17:20:48.000000000 -0400
@@ -77,6 +77,9 @@ static const struct nv_list failure_acti
int audit_archadded hidden = 0;
int audit_syscalladded hidden = 0;
+/* set to highest version we know */
+int audit_signal_version = 1;
+
unsigned int audit_elf hidden = 0U;
static struct libaudit_conf config;
@@ -492,9 +495,32 @@ int audit_request_rules_list_data(int fd
return rc;
}
-int audit_request_signal_info(int fd)
+int audit_request_signal_info(int fd, int sig)
{
- int rc = audit_send(fd, AUDIT_SIGNAL_INFO, NULL, 0);
+ int rc = 0;
+
+ while (audit_signal_version) {
+ struct audit_sig_info_ver1 siginfo;
+
+ /*
+ * we should be safe to always send _ver1 to the kernel as long
+ * .version and .sig are always the first 2 entries in all
+ * future versions. These are the only 2 the kernel cares
+ * about getting from userspace.
+ */
+ siginfo.version = audit_signal_version;
+ siginfo.sig = sig;
+
+ rc = audit_send(fd, AUDIT_SIGNAL_INFO_VERS, &siginfo, sizeof(siginfo));
+ if (rc == -EINVAL || rc == -EPERM)
+ audit_signal_version--;
+ else
+ break;
+ }
+
+ if (!audit_signal_version)
+ rc = audit_send(fd, AUDIT_SIGNAL_INFO, NULL, 0);
+
if (rc < 0)
audit_msg(LOG_WARNING,
"Error sending signal_info request (%s)",
diff -Naupr audit-1.7.orig/lib/libaudit.h audit-1.7/lib/libaudit.h
--- audit-1.7.orig/lib/libaudit.h 2008-03-26 10:40:18.000000000 -0400
+++ audit-1.7/lib/libaudit.h 2008-04-13 17:20:48.000000000 -0400
@@ -373,11 +373,21 @@ struct audit_rule_data {
//
/* data structure for who signaled the audit daemon */
struct audit_sig_info {
- uid_t uid;
- pid_t pid;
+ uid_t uid;
+ pid_t pid;
char ctx[0];
};
+struct audit_sig_info_ver1 {
+ uint32_t version;
+ uint32_t sig;
+ uid_t uid;
+ uid_t auid;
+ pid_t pid;
+ uint32_t session;
+ char ctx[0];
+};
+
/* defines for audit subsystem */
#define MAX_AUDIT_MESSAGE_LENGTH 8970 // PATH_MAX*2+CONTEXT_SIZE*2+11+256+1
struct audit_message {
@@ -404,6 +414,7 @@ struct audit_reply {
const char *message;
struct nlmsgerr *error;
struct audit_sig_info *signal_info;
+ struct audit_sig_info_ver1 *signal_info_ver1;
struct daemon_conf *conf;
};
};
@@ -450,6 +461,10 @@ extern int audit_get_reply(int fd, stru
extern uid_t audit_getloginuid(void);
extern int audit_setloginuid(uid_t uid);
extern int audit_detect_machine(void);
+extern int audit_fill_siginfo(struct audit_reply *rep,
+ struct audit_sig_info_ver1 *sig_info,
+ char **ctx);
+
/* Translation functions */
extern int audit_name_to_field(const char *field);
@@ -487,7 +502,7 @@ extern int audit_set_backlog_limit(int
extern int audit_request_rules_list_data(int fd);
/* SIGNAL_INFO */
-extern int audit_request_signal_info(int fd);
+extern int audit_request_signal_info(int fd, int sig);
/* AUDIT_WATCH */
extern int audit_update_watch_perms(struct audit_rule_data *rule, int perms);
diff -Naupr audit-1.7.orig/lib/netlink.c audit-1.7/lib/netlink.c
--- audit-1.7.orig/lib/netlink.c 2008-02-29 15:39:01.000000000 -0500
+++ audit-1.7/lib/netlink.c 2008-04-13 17:20:48.000000000 -0400
@@ -147,6 +147,7 @@ static int adjust_reply(struct audit_rep
rep->message = NULL;
rep->error = NULL;
rep->signal_info = NULL;
+ rep->signal_info_ver1 = NULL;
rep->conf = NULL;
if (!NLMSG_OK(rep->nlh, (unsigned int)len)) {
if (len == sizeof(rep->msg)) {
@@ -187,6 +188,9 @@ static int adjust_reply(struct audit_rep
case AUDIT_SIGNAL_INFO:
rep->signal_info = NLMSG_DATA(rep->nlh);
break;
+ case AUDIT_SIGNAL_INFO_VERS:
+ rep->signal_info_ver1 = NLMSG_DATA(rep->nlh);
+ break;
}
return len;
}
diff -Naupr audit-1.7.orig/src/auditd.c audit-1.7/src/auditd.c
--- audit-1.7.orig/src/auditd.c 2008-04-09 11:07:43.000000000 -0400
+++ audit-1.7/src/auditd.c 2008-04-13 17:25:27.000000000 -0400
@@ -323,6 +323,135 @@ static void tell_parent(int status)
} while (rc < 0 && errno == EINTR);
}
+/* fiven a reply fill in the latest version of the signal version struct */
+int audit_fill_siginfo(struct audit_reply *rep, struct audit_sig_info_ver1 *sig_info,
+ char **ctx)
+{
+ int has_ver = (rep->type == AUDIT_SIGNAL_INFO_VERS);
+ int vers = has_ver ? rep->signal_info_ver1->version : 0;
+
+ sig_info->version = vers;
+
+ switch (vers) {
+ case 0:
+ sig_info->sig = 0;
+ sig_info->uid = -1;
+ sig_info->auid = rep->signal_info->uid;
+ sig_info->pid = rep->signal_info->pid;
+ sig_info->session = -1;
+ if (rep->len == sizeof(struct audit_sig_info) + NLMSG_HDRLEN)
+ *ctx = "?";
+ else
+ *ctx = &rep->signal_info->ctx[0];
+ break;
+ case 1:
+ sig_info->sig = rep->signal_info_ver1->sig;
+ sig_info->uid = rep->signal_info_ver1->uid;
+ sig_info->auid = rep->signal_info_ver1->auid;
+ sig_info->pid = rep->signal_info_ver1->pid;
+ sig_info->session = rep->signal_info_ver1->session;
+ if (rep->len == sizeof(struct audit_sig_info_ver1) + NLMSG_HDRLEN)
+ *ctx = "?";
+ else
+ *ctx = &rep->signal_info_ver1->ctx[0];
+ break;
+ default:
+ sig_info->sig = 0;
+ sig_info->uid = -1;
+ sig_info->auid = -1;
+ sig_info->pid = -1;
+ sig_info->session = -1;
+ *ctx = "?";
+ return -EINVAL;
+ };
+ return 0;
+}
+int audit_handle_term(int fd) {
+ /* Write message to log that we are going down */
+ int rc;
+ struct audit_reply trep;
+ char txt[MAX_AUDIT_MESSAGE_LENGTH];
+ /* always make max version... */
+ struct audit_sig_info_ver1 sig_info;
+ char *ctx;
+
+ /* FIXME shouldn't be 0..... */
+ rc = audit_request_signal_info(fd, SIGTERM);
+ if (rc < 0)
+ goto out;
+
+ rc = get_reply(fd, &trep, rc);
+ if (rc < 0)
+ goto out;
+
+ rc = audit_fill_siginfo(&trep, &sig_info, &ctx);
+ if (rc < 0)
+ goto out;
+
+ snprintf(txt, sizeof(txt), "auditd normal halt, sending uid=%d auid=%u "
+ "ses=%d pid=%u subj=%s res=success", sig_info.uid,
+ sig_info.auid, sig_info.session, sig_info.pid, ctx);
+
+ send_audit_event(AUDIT_DAEMON_END, txt);
+out:
+ if (rc < 0)
+ send_audit_event(AUDIT_DAEMON_END,
+ "auditd normal halt, sending auid=? pid=? subj=? res=success");
+ shutdown_dispatcher();
+}
+
+int audit_handle_signal_msg(struct auditd_reply_list **in_rep,
+ int *hup_info_requested, int *usr1_info_requested,
+ int *usr2_info_requested)
+{
+ char msg[MAX_AUDIT_MESSAGE_LENGTH];
+ int version;
+ char *subj = NULL;
+ struct auditd_reply_list *rep = *in_rep;
+ int rc;
+
+ /* make the latest version */
+ struct audit_sig_info_ver1 sig_info;
+
+ rc = audit_fill_siginfo(&rep->reply, &sig_info, &subj);
+ if (rc < 0)
+ return rc;
+
+ version = sig_info.version;
+
+ snprintf(msg, sizeof(msg), "auditd signal from uid=%d auid=%u ses=%d pid=%u
subj=%s",
+ sig_info.uid, sig_info.auid, sig_info.session, sig_info.pid, subj);
+
+ if (*hup_info_requested && ((version == 0) ||
+ (sig_info.sig == SIGHUP))) {
+ audit_msg(LOG_DEBUG, "HUP detected, starting config manager");
+ if (start_config_manager(rep))
+ send_audit_event(AUDIT_DAEMON_CONFIG, "auditd error getting hup info - no change,
signal from auid=? pid=? subj=? res=failed");
+ *in_rep = NULL;
+ *hup_info_requested = 0;
+ } else if (*usr1_info_requested && ((version == 0) ||
+ (sig_info.sig == SIGUSR1))) {
+ send_audit_event(AUDIT_DAEMON_ROTATE, msg);
+ *usr1_info_requested = 0;
+ } else if (*usr2_info_requested && ((version == 0) ||
+ (sig_info.sig == SIGUSR2))) {
+ resume_logging();
+ /* kernels which don't know .ver1 signal types don't know
+ * sigusr2 either so don't believe anything it tells us
+ */
+ if (version)
+ send_audit_event(AUDIT_DAEMON_RESUME, msg);
+ else
+ send_audit_event(AUDIT_DAEMON_RESUME,
+ "auditd signal from uid=? auid=? ses=? pid=? subj=?\n");
+ *usr2_info_requested = 0;
+ } else {
+ fprintf(stderr, "got signal:%d we didn't request!", sig_info.sig);
+ return -EINVAL;
+ }
+ return 0;
+}
+
int main(int argc, char *argv[])
{
struct sigaction sa;
@@ -330,6 +459,7 @@ int main(int argc, char *argv[])
struct auditd_reply_list *rep = NULL;
struct rlimit limit;
int hup_info_requested = 0, usr1_info_requested = 0;
+ int usr2_info_requested = 0;
int i;
int opt_foreground = 0, opt_allow_links = 0;
enum startup_state opt_startup = startup_enable;
@@ -608,35 +738,11 @@ int main(int argc, char *argv[])
case AUDIT_FIRST_DAEMON...AUDIT_LAST_DAEMON:
break;
case AUDIT_SIGNAL_INFO:
- if (hup_info_requested) {
- audit_msg(LOG_DEBUG,
- "HUP detected, starting config manager");
- if (start_config_manager(rep)) {
- send_audit_event(
- AUDIT_DAEMON_CONFIG,
- "auditd error getting hup info - no change,"
- " sending auid=? pid=? subj=? res=failed");
- }
- rep = NULL;
- hup_info_requested = 0;
- } else if(usr1_info_requested){
- char usr1[MAX_AUDIT_MESSAGE_LENGTH];
- if (rep->reply.len == 24) {
- snprintf(usr1,
- sizeof(usr1),
- "auditd sending auid=? pid=? subj=?");
- } else {
- snprintf(usr1,
- sizeof(usr1),
- "auditd sending auid=%u pid=%d subj=%s",
- rep->reply.signal_info->uid,
- rep->reply.signal_info->pid,
- rep->reply.signal_info->ctx);
- }
- send_audit_event(
- AUDIT_DAEMON_ROTATE,
- usr1);
- }
+ case AUDIT_SIGNAL_INFO_VERS:
+ audit_handle_signal_msg(&rep,
+ &hup_info_requested,
+ &usr1_info_requested,
+ &usr2_info_requested);
break;
default:
distribute_event(rep);
@@ -649,56 +755,38 @@ int main(int argc, char *argv[])
}
}
}
+#define ERROR_REQUESTING "auditd: error requesting "
+#define NO_CHANGE " info - no change, sending auid=? pid=? subj=? res=failed"
if (hup) {
int rc;
hup = 0;
- rc = audit_request_signal_info(fd);
+ rc = audit_request_signal_info(fd, SIGHUP);
if (rc < 0)
- send_audit_event(AUDIT_DAEMON_CONFIG,
- "auditd error getting hup info - no change, sending auid=? pid=? subj=?
res=failed");
+ send_audit_event(AUDIT_DAEMON_CONFIG, ERROR_REQUESTING "hup" NO_CHANGE);
else
hup_info_requested = 1;
}
if (rot) {
int rc;
rot = 0;
- rc = audit_request_signal_info(fd);
+ rc = audit_request_signal_info(fd, SIGUSR1);
if (rc < 0)
- send_audit_event(AUDIT_DAEMON_ROTATE,
- "auditd error getting usr1 info - no change, sending auid=? pid=? subj=?
res=failed");
+ send_audit_event(AUDIT_DAEMON_ROTATE, ERROR_REQUESTING "usr1" NO_CHANGE);
else
usr1_info_requested = 1;
}
if (resume) {
+ int rc;
resume = 0;
- resume_logging();
- send_audit_event(AUDIT_DAEMON_RESUME,
- "auditd resuming logging, sending auid=? pid=? subj=? res=success");
+ rc = audit_request_signal_info(fd, SIGUSR2);
+ if (rc < 0)
+ send_audit_event(AUDIT_DAEMON_RESUME, ERROR_REQUESTING "usr2" NO_CHANGE);
+ else
+ usr2_info_requested = 1;
}
if (stop) {
- /* Write message to log that we are going down */
- int rc;
-
- rc = audit_request_signal_info(fd);
- if (rc > 0) {
- struct audit_reply trep;
-
- rc = get_reply(fd, &trep, rc);
- if (rc > 0) {
- char txt[MAX_AUDIT_MESSAGE_LENGTH];
- snprintf(txt, sizeof(txt),
- "auditd normal halt, sending auid=%u pid=%d subj=%s res=success",
- trep.signal_info->uid,
- trep.signal_info->pid,
- trep.signal_info->ctx);
- send_audit_event(AUDIT_DAEMON_END, txt);
- }
- }
- if (rc <= 0)
- send_audit_event(AUDIT_DAEMON_END,
- "auditd normal halt, sending auid=? pid=? subj=? res=success");
+ audit_handle_term(fd);
free(rep);
- shutdown_dispatcher();
break;
}
}
@@ -761,8 +849,7 @@ static int get_reply(int fd, struct audi
do {
rc = select(fd+1, &read_mask, NULL, NULL, &t);
} while (rc < 0 && errno == EINTR);
- rc = audit_get_reply(fd, rep,
- GET_REPLY_NONBLOCKING, 0);
+ rc = audit_get_reply(fd, rep, GET_REPLY_NONBLOCKING, 0);
if (rc > 0) {
/* Don't make decisions based on wrong packet */
if (rep->nlh->nlmsg_seq != seq)
@@ -771,6 +858,11 @@ static int get_reply(int fd, struct audi
/* If its not what we are expecting, keep looping */
if (rep->type == AUDIT_SIGNAL_INFO)
return 1;
+ if (rep->type == AUDIT_SIGNAL_INFO_VERS) {
+ /* safe to always cast to _ver1 if version and sig stay put */
+ if (rep->signal_info_ver1->sig == SIGTERM)
+ return 1;
+ }
/* If we get done or error, break out */
if (rep->type == NLMSG_DONE || rep->type == NLMSG_ERROR)
diff -Naupr audit-1.7.orig/src/auditd-config.c audit-1.7/src/auditd-config.c
--- audit-1.7.orig/src/auditd-config.c 2008-03-11 09:12:18.000000000 -0400
+++ audit-1.7/src/auditd-config.c 2008-04-13 17:20:48.000000000 -0400
@@ -202,7 +202,9 @@ static void clear_config(struct daemon_c
{
config->qos = QOS_NON_BLOCKING;
config->sender_uid = 0;
+ config->sender_auid = 0;
config->sender_pid = 0;
+ config->sender_session = 0;
config->sender_ctx = NULL;
config->log_file = strdup("/var/log/audit/audit.log");
config->log_format = LF_RAW;
diff -Naupr audit-1.7.orig/src/auditd-config.h audit-1.7/src/auditd-config.h
--- audit-1.7.orig/src/auditd-config.h 2007-09-16 15:04:49.000000000 -0400
+++ audit-1.7/src/auditd-config.h 2008-04-13 17:20:48.000000000 -0400
@@ -40,12 +40,13 @@ typedef enum { QOS_NON_BLOCKING, QOS_BLO
typedef enum { TEST_AUDITD, TEST_SEARCH } log_test_t;
typedef enum { N_NONE, N_HOSTNAME, N_FQD, N_NUMERIC, N_USER } node_t;
-struct daemon_conf
-{
+struct daemon_conf {
daemon_t daemonize;
qos_t qos; /* use blocking/non-blocking sockets */
uid_t sender_uid; /* the uid for sender of sighup */
+ uid_t sender_auid; /* auid of the sighup sender */
pid_t sender_pid; /* the pid for sender of sighup */
+ uint32_t sender_session;/* session of the signal sender */
const char *sender_ctx; /* the context for the sender of sighup */
const char *log_file;
logging_formats log_format;
diff -Naupr audit-1.7.orig/src/auditd-event.c audit-1.7/src/auditd-event.c
--- audit-1.7.orig/src/auditd-event.c 2008-02-07 13:55:31.000000000 -0500
+++ audit-1.7/src/auditd-event.c 2008-04-13 17:20:48.000000000 -0400
@@ -875,7 +875,9 @@ static void reconfigure(struct auditd_co
struct daemon_conf *nconf = data->head->reply.conf;
struct daemon_conf *oconf = data->config;
uid_t uid = nconf->sender_uid;
+ uid_t auid = nconf->sender_auid;
pid_t pid = nconf->sender_pid;
+ uint32_t session = nconf->sender_session;
const char *ctx = nconf->sender_ctx;
struct timeval tv;
char txt[MAX_AUDIT_MESSAGE_LENGTH];
@@ -884,8 +886,8 @@ static void reconfigure(struct auditd_co
int need_size_check = 0, need_reopen = 0, need_space_check = 0;
snprintf(txt, sizeof(txt),
- "config change requested by pid=%d auid=%u subj=%s",
- pid, uid, ctx);
+ "config change requested by uid=%d auid=%u ses=%d pid=%d subj=%s",
+ uid, auid, session, pid, ctx);
audit_msg(LOG_NOTICE, txt);
/* Do the reconfiguring. These are done in a specific
@@ -1131,8 +1133,8 @@ static void reconfigure(struct auditd_co
}
data->head->reply.len = snprintf(txt, sizeof(txt),
- "%s config changed, auid=%u pid=%d subj=%s res=success", date,
- uid, pid, ctx );
+ "%s config changed, uid=%d auid=%u ses=%d pid=%d subj=%s res=success", date,
+ uid, auid, session, pid, ctx );
audit_msg(LOG_NOTICE, txt);
data->head->reply.type = AUDIT_DAEMON_CONFIG;
data->head->reply.message = strdup(txt);
diff -Naupr audit-1.7.orig/src/auditd-reconfig.c audit-1.7/src/auditd-reconfig.c
--- audit-1.7.orig/src/auditd-reconfig.c 2007-07-24 17:10:57.000000000 -0400
+++ audit-1.7/src/auditd-reconfig.c 2008-04-13 17:20:48.000000000 -0400
@@ -47,29 +47,28 @@ void init_config_manager(void)
int start_config_manager(struct auditd_reply_list *rep)
{
int retval, rc = 0;
-
+
retval = pthread_mutex_trylock(&config_lock);
if (retval == 0) {
pthread_attr_t detached;
pthread_attr_init(&detached);
- pthread_attr_setdetachstate(&detached,
- PTHREAD_CREATE_DETACHED);
+ pthread_attr_setdetachstate(&detached, PTHREAD_CREATE_DETACHED);
- if (pthread_create(&config_thread, &detached,
- config_thread_main, rep) < 0) {
- audit_msg(LOG_ERR,
- "Couldn't create config thread, no config changes");
+ if (pthread_create(&config_thread, &detached,
+ config_thread_main, rep) < 0) {
+ audit_msg(LOG_ERR,
+ "Couldn't create config thread, no config changes");
free(rep);
pthread_mutex_unlock(&config_lock);
- rc = 1;
- }
+ rc = 1;
+ }
pthread_attr_destroy(&detached);
} else {
- audit_msg(LOG_ERR,
- "Config thread already running, no config changes");
+ audit_msg(LOG_ERR,
+ "Config thread already running, no config changes");
free(rep);
- rc = 1;
+ rc = 1;
}
return rc;
}
@@ -85,6 +84,9 @@ static void *config_thread_main(void *ar
struct auditd_reply_list *rep = (struct auditd_reply_list *)arg;
struct daemon_conf new_config;
extern int send_audit_event(int type, const char *str);
+ struct audit_sig_info_ver1 sig_info;
+ char *ctx = NULL;
+ int rc;
/* This is a worker thread. Don't handle signals. */
sigemptyset(&sigs);
@@ -95,15 +97,18 @@ static void *config_thread_main(void *ar
sigaddset(&sigs, SIGUSR2);
pthread_sigmask(SIG_SETMASK, &sigs, NULL);
+ rc = audit_fill_siginfo(&rep->reply, &sig_info, &ctx);
+
if (load_config(&new_config, TEST_AUDITD) == 0) {
/* We will re-use the current reply */
- new_config.sender_uid = rep->reply.signal_info->uid;
- new_config.sender_pid = rep->reply.signal_info->pid;
- if (rep->reply.len > 24)
- new_config.sender_ctx =
- strdup(rep->reply.signal_info->ctx);
- else
- new_config.sender_ctx = strdup("?");
+
+ new_config.sender_uid = sig_info.uid;
+ new_config.sender_auid = sig_info.auid;
+ new_config.sender_pid = sig_info.pid;
+ new_config.sender_session = sig_info.session;
+ new_config.sender_ctx = strdup(ctx);
+
+
memcpy(rep->reply.msg.data, &new_config, sizeof(new_config));
rep->reply.conf = (struct daemon_conf *)rep->reply.msg.data;
rep->reply.type = AUDIT_DAEMON_RECONFIG;
@@ -111,12 +116,10 @@ static void *config_thread_main(void *ar
} else {
// need to send a failed event message
char txt[MAX_AUDIT_MESSAGE_LENGTH];
- snprintf(txt, sizeof(txt),
- "reconfig aborted, sending auid=%u pid=%d subj=%s res=failed",
- rep->reply.signal_info->uid,
- rep->reply.signal_info->pid,
- (rep->reply.len > 24) ?
- rep->reply.signal_info->ctx : "?");
+ snprintf(txt, sizeof(txt), "reconfig aborted, sending uid=%d "
+ "auid=%u ses=%d pid=%d subj=%s res=failed",
+ sig_info.uid, sig_info.auid, sig_info.session,
+ sig_info.pid, ctx);
send_audit_event(AUDIT_DAEMON_CONFIG, txt);
free_config(&new_config);
free(rep);