static void init_auditd (NMAuditManager *self) { NMAuditManagerPrivate *priv = NM_AUDIT_MANAGER_GET_PRIVATE (self); NMConfigData *data = nm_config_get_data (priv->config); if (nm_config_data_get_value_boolean (data, NM_CONFIG_KEYFILE_GROUP_LOGGING, NM_CONFIG_KEYFILE_KEY_AUDIT, NM_CONFIG_DEFAULT_LOGGING_AUDIT)) { if (priv->auditd_fd < 0) { priv->auditd_fd = audit_open (); if (priv->auditd_fd < 0) { nm_log_err (LOGD_CORE, "failed to open auditd socket: %s", strerror (errno)); } else nm_log_dbg (LOGD_CORE, "audit socket created"); } } else { if (priv->auditd_fd >= 0) { audit_close (priv->auditd_fd); priv->auditd_fd = -1; nm_log_dbg (LOGD_CORE, "audit socket closed"); } } }
static void maybe_audit_mass_relabel(int mass_relabel __attribute__((unused)), int mass_relabel_errs __attribute__((unused))) { #else static void maybe_audit_mass_relabel(int mass_relabel, int mass_relabel_errs) { int audit_fd = -1; int rc = 0; if (!mass_relabel) /* only audit a forced full relabel */ return; audit_fd = audit_open(); if (audit_fd < 0) { fprintf(stderr, "Error connecting to audit system.\n"); exit(-1); } rc = audit_log_user_message(audit_fd, AUDIT_FS_RELABEL, "op=mass relabel", NULL, NULL, NULL, !mass_relabel_errs); if (rc <= 0) { fprintf(stderr, "Error sending audit message: %s.\n", strerror(errno)); /* exit(-1); -- don't exit atm. as fix for eff_cap isn't in most kernels */ } audit_close(audit_fd); #endif }
/** * Close the libaudit fd. */ void bus_audit_shutdown (void) { #ifdef HAVE_LIBAUDIT audit_close (audit_fd); #endif /* HAVE_LIBAUDIT */ }
static bool audit_mainloop() { int fd = audit_open(); if (fd < 0) { LOGE("Failed to open audit socket: %s", strerror(errno)); return false; } auto close_fd = finally([&]{ audit_close(fd); }); if (audit_setup(fd, static_cast<uint32_t>(getpid())) < 0) { return false; } while (true) { struct audit_message reply; reply.nlh.nlmsg_type = 0; reply.nlh.nlmsg_len = 0; reply.data[0] = '\0'; if (audit_get_reply(fd, &reply, GET_REPLY_BLOCKING, 0) < 0) { LOGE("Failed to get reply from audit socket: %s", strerror(errno)); return false; } LOGV("type=%d %.*s", reply.nlh.nlmsg_type, reply.nlh.nlmsg_len, reply.data); } // unreachable }
static int _audit_log(int type, const char *uname, int rc) { int audit_fd; audit_fd = audit_open(); if (audit_fd < 0) { /* You get these error codes only when the kernel doesn't have * audit compiled in. */ if (errno == EINVAL || errno == EPROTONOSUPPORT || errno == EAFNOSUPPORT) return PAM_SUCCESS; helper_log_err(LOG_CRIT, "audit_open() failed: %m"); return PAM_AUTH_ERR; } rc = audit_log_acct_message(audit_fd, type, NULL, "PAM:unix_chkpwd", uname, -1, NULL, NULL, NULL, rc == PAM_SUCCESS); if (rc == -EPERM && geteuid() != 0) { rc = 0; } audit_close(audit_fd); return rc < 0 ? PAM_AUTH_ERR : PAM_SUCCESS; }
/* Clean up the AVC before exiting. */ void nscd_avc_destroy (void) { avc_destroy (); #ifdef HAVE_LIBAUDIT audit_close (audit_fd); #endif }
static void context_clear(Context *c) { assert(c); c->bus = sd_bus_flush_close_unref(c->bus); #if HAVE_AUDIT if (c->audit_fd >= 0) audit_close(c->audit_fd); c->audit_fd = -1; #endif }
int LogAudit::getLogSocket() { int fd = audit_open(); if (fd < 0) { return fd; } if (audit_setup(fd, getpid()) < 0) { audit_close(fd); fd = -1; } return fd; }
/* * A clean exit means : * 1) we log that we are going down * 2) deregister with kernel * 3) close the netlink socket */ static void clean_exit(void) { audit_msg(LOG_INFO, "The audit daemon is exiting."); if (fd >= 0) { audit_set_pid(fd, 0, WAIT_NO); audit_close(fd); } if (pidfile) unlink(pidfile); closelog(); }
static void dispose (GObject *object) { #if HAVE_LIBAUDIT NMAuditManager *self = NM_AUDIT_MANAGER (object); NMAuditManagerPrivate *priv = NM_AUDIT_MANAGER_GET_PRIVATE (self); if (priv->config) { g_signal_handlers_disconnect_by_func (priv->config, config_changed_cb, self); g_clear_object (&priv->config); } if (priv->auditd_fd >= 0) { audit_close (priv->auditd_fd); priv->auditd_fd = -1; } #endif G_OBJECT_CLASS (nm_audit_manager_parent_class)->dispose (object); }
/* * This function interprets the reply and prints it to stdout. It returns * 0 if no more should be read and 1 to indicate that more messages of this * type may need to be read. */ int audit_print_reply(struct audit_reply *rep, int fd) { _audit_elf = 0; switch (rep->type) { case NLMSG_NOOP: return 1; case NLMSG_DONE: // Close the socket so kernel can do other things audit_close(fd); if (printed == 0) printf("No rules\n"); else { lnode *n; list_first(&l); n = l.cur; while (n) { print_rule(n->r); n = list_next(&l); } list_clear(&l); } break; case NLMSG_ERROR: printf("NLMSG_ERROR %d (%s)\n", -rep->error->error, strerror(-rep->error->error)); printed = 1; break; case AUDIT_GET: if (interpret) printf("enabled %s\nfailure %s\n", get_enable(rep->status->enabled), get_failure(rep->status->failure)); else printf("enabled %u\nfailure %u\n", rep->status->enabled, rep->status->failure); printf("pid %u\nrate_limit %u\nbacklog_limit %u\n" "lost %u\nbacklog %u\n", rep->status->pid, rep->status->rate_limit, rep->status->backlog_limit, rep->status->lost, rep->status->backlog); #if HAVE_DECL_AUDIT_VERSION_BACKLOG_WAIT_TIME printf("backlog_wait_time %u\n", rep->status->backlog_wait_time); #endif printed = 1; break; #if HAVE_DECL_AUDIT_FEATURE_VERSION case AUDIT_GET_FEATURE: { uint32_t mask = AUDIT_FEATURE_TO_MASK(AUDIT_FEATURE_LOGINUID_IMMUTABLE); if (rep->features->mask & mask) printf("loginuid_immutable %u %s\n", !!(rep->features->features & mask), rep->features->lock & mask ? "locked" : "unlocked"); } printed = 1; break; #endif case AUDIT_LIST_RULES: list_requested = 0; if (key_match(rep->ruledata)) list_append(&l, rep->ruledata, sizeof(struct audit_rule_data) + rep->ruledata->buflen); printed = 1; return 1; default: printf("Unknown: type=%d, len=%d\n", rep->type, rep->nlh->nlmsg_len); printed = 1; break; } return 0; }
/* * This function is called after setopt to handle the return code. * On entry, status = 0 means just get the reply. Greater than 0 means we * are adding or deleting a rule or watch. -1 means an error occurred. * -2 means everything is OK and no reply needed. Even if there's an * error, we need to call this routine to close up the audit fd. * The return code from this function is 0 success and -1 error. */ static int handle_request(int status) { if (status == 0) { if (_audit_syscalladded) { fprintf(stderr, "Error - no list specified\n"); return -1; } get_reply(); } else if (status == -2) status = 0; // report success else if (status > 0) { int rc; if (add != AUDIT_FILTER_UNSET) { // if !task add syscall any if not specified if ((add & AUDIT_FILTER_MASK) != AUDIT_FILTER_TASK && _audit_syscalladded != 1) { audit_rule_syscallbyname_data( rule_new, "all"); } set_aumessage_mode(MSG_QUIET, DBG_NO); rc = audit_add_rule_data(fd, rule_new, add, action); set_aumessage_mode(MSG_STDERR, DBG_NO); /* Retry for legacy kernels */ if (rc < 0) { if (errno == EINVAL && rule_new->fields[0] == AUDIT_DIR) { rule_new->fields[0] = AUDIT_WATCH; rc = audit_add_rule_data(fd, rule_new, add, action); } else { fprintf(stderr, "Error sending add rule data request (%s)\n", errno == EEXIST ? "Rule exists" : strerror(-rc)); } } } else if (del != AUDIT_FILTER_UNSET) { if ((del & AUDIT_FILTER_MASK) != AUDIT_FILTER_TASK && _audit_syscalladded != 1) { audit_rule_syscallbyname_data( rule_new, "all"); } set_aumessage_mode(MSG_QUIET, DBG_NO); rc = audit_delete_rule_data(fd, rule_new, del, action); set_aumessage_mode(MSG_STDERR, DBG_NO); /* Retry for legacy kernels */ if (rc < 0) { if (errno == EINVAL && rule_new->fields[0] == AUDIT_DIR) { rule_new->fields[0] = AUDIT_WATCH; rc = audit_delete_rule_data(fd,rule_new, del, action); } else { fprintf(stderr, "Error sending delete rule data request (%s)\n", errno == EEXIST ? "Rule exists" : strerror(-rc)); } } } else { usage(); audit_close(fd); exit(1); } if (rc <= 0) status = -1; else status = 0; } else status = -1; audit_close(fd); fd = -1; return status; }
static void do_auditd(int fd) { struct audit_reply rep; sigset_t sigs; struct sigaction sa; struct pollfd pds = { .events = POLLIN | POLLPRI | POLLERR | POLLHUP | POLLMSG, .revents = 0, .fd = fd, }; if (audit_set_pid(fd, getpid(), WAIT_YES) < 0) return; if (audit_set_enabled(fd, 1) < 0) return; memset(&sa, '\0', sizeof (sa)); sa.sa_handler = sig_done; sigaction(SIGTERM, &sa, NULL); sigaction(SIGINT, &sa, NULL); sigaction(SIGHUP, &sa, NULL); sigfillset(&sigs); sigdelset(&sigs, SIGTERM); sigdelset(&sigs, SIGINT); sigdelset(&sigs, SIGHUP); while (1) { struct timespec timeout = { -1, -1 }; int retval; memset(&rep, 0, sizeof(rep)); do { retval = ppoll(&pds, 1, &timeout, &sigs); } while (retval == -1 && errno == EINTR && !done); if (done) break; if (audit_get_reply(fd, &rep, GET_REPLY_NONBLOCKING, 0) > 0) { /* we don't actually want to do anything here. */ ; } } return; } #endif /* USESELINUX */ int audit_daemonize(void) { #ifdef USESELINUX int fd; #ifndef STANDALONE int i; pid_t child; if ((child = fork()) > 0) return 0; for (i = 0; i < getdtablesize(); i++) close(i); signal(SIGTTOU, SIG_IGN); signal(SIGTTIN, SIG_IGN); signal(SIGTSTP, SIG_IGN); if ((fd = open("/proc/self/oom_adj", O_RDWR)) >= 0) { i = write(fd, "-17", 3); close(fd); } #endif /* !defined(STANDALONE) */ fd = audit_open(); do_auditd(fd); audit_close(fd); #endif /* USESELINUX */ exit(0); }
int main(int argc, char *argv[]) { int r; DBusError error; Context c; dbus_error_init(&error); zero(c); #ifdef HAVE_AUDIT c.audit_fd = -1; #endif if (getppid() != 1) { log_error("This program should be invoked by init only."); return EXIT_FAILURE; } if (argc != 2) { log_error("This program requires one argument."); return EXIT_FAILURE; } log_set_target(LOG_TARGET_SYSLOG_OR_KMSG); log_parse_environment(); log_open(); #ifdef HAVE_AUDIT if ((c.audit_fd = audit_open()) < 0) log_error("Failed to connect to audit log: %m"); #endif if (bus_connect(DBUS_BUS_SYSTEM, &c.bus, NULL, &error) < 0) { log_error("Failed to get D-Bus connection: %s", bus_error_message(&error)); r = -EIO; goto finish; } log_debug("systemd-update-utmp running as pid %lu", (unsigned long) getpid()); if (streq(argv[1], "reboot")) r = on_reboot(&c); else if (streq(argv[1], "shutdown")) r = on_shutdown(&c); else if (streq(argv[1], "runlevel")) r = on_runlevel(&c); else { log_error("Unknown command %s", argv[1]); r = -EINVAL; } log_debug("systemd-update-utmp stopped as pid %lu", (unsigned long) getpid()); finish: #ifdef HAVE_AUDIT if (c.audit_fd >= 0) audit_close(c.audit_fd); #endif if (c.bus) { dbus_connection_flush(c.bus); dbus_connection_close(c.bus); dbus_connection_unref(c.bus); } dbus_error_free(&error); dbus_shutdown(); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; }