sysusers: emit audit events for user and group creation (#35957)

Background: Fedora/RHEL are switching to sysusers.d metadata for
creation of users and groups for system users defined by packages
(https://fedoraproject.org/wiki/Changes/RPMSuportForSystemdSysusers).
Packages carry sysusers files. During package installation, rpm calls an
program to execute on this config. This program may either be
/usr/lib/rpm/sysusers.sh which calls useradd/groupadd, or
/usr/bin/systemd-sysusers. To match the functionality provided by
useradd/groupadd from the shadow-utils project, systemd-sysusers must
emit audit events so that it provides a drop-in replacement.

systemd-sysuers will emit audit events AUDIT_ADD_USER/AUDIT_ADD_GROUP
when adding users and groups. The operation "names" are copied from
shadow-utils, so the format of the events that is generated on success
should be identical. On failure, things are more complicated. We write
the whole file at once, once, so we first generate "success" messages
for each entry, then we try to write the files, and if things fail, we
generate failure messages to all entries that we failed to write.
This commit is contained in:
Zbigniew Jędrzejewski-Szmek
2025-01-15 10:36:07 +01:00
committed by GitHub
8 changed files with 118 additions and 68 deletions
+17 -39
View File
@@ -5,58 +5,36 @@
#include "audit-fd.h"
#if HAVE_AUDIT
# include <stdbool.h>
#include <libaudit.h>
#include <stdbool.h>
#include "capability-util.h"
#include "fd-util.h"
#include "log.h"
# include "audit-util.h"
# include "capability-util.h"
static bool initialized = false;
static int audit_fd;
int get_audit_fd(void) {
static int audit_fd = -EBADF;
#endif
int get_core_audit_fd(void) {
#if HAVE_AUDIT
if (!initialized) {
if (have_effective_cap(CAP_AUDIT_WRITE) <= 0) {
if (have_effective_cap(CAP_AUDIT_WRITE) <= 0)
audit_fd = -EPERM;
initialized = true;
return audit_fd;
}
audit_fd = audit_open();
if (audit_fd < 0) {
if (!IN_SET(errno, EAFNOSUPPORT, EPROTONOSUPPORT))
log_error_errno(errno, "Failed to connect to audit log: %m");
audit_fd = errno ? -errno : -EINVAL;
}
else
audit_fd = open_audit_fd_or_warn();
initialized = true;
}
return audit_fd;
#else
return -EAFNOSUPPORT;
#endif
}
void close_audit_fd(void) {
if (initialized && audit_fd >= 0)
safe_close(audit_fd);
void close_core_audit_fd(void) {
#if HAVE_AUDIT
close_audit_fd(audit_fd);
initialized = true;
audit_fd = -ECONNRESET;
}
#else
int get_audit_fd(void) {
return -EAFNOSUPPORT;
}
void close_audit_fd(void) {
}
#endif
}
+2 -2
View File
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
int get_audit_fd(void);
void close_audit_fd(void);
int get_core_audit_fd(void);
void close_core_audit_fd(void);
+2 -2
View File
@@ -3560,7 +3560,7 @@ void manager_send_unit_audit(Manager *m, Unit *u, int type, bool success) {
if (MANAGER_IS_RELOADING(m))
return;
audit_fd = get_audit_fd();
audit_fd = get_core_audit_fd();
if (audit_fd < 0)
return;
@@ -3575,7 +3575,7 @@ void manager_send_unit_audit(Manager *m, Unit *u, int type, bool success) {
if (ERRNO_IS_PRIVILEGE(errno)) {
/* We aren't allowed to send audit messages? Then let's not retry again. */
log_debug_errno(errno, "Failed to send audit message, closing audit socket: %m");
close_audit_fd();
close_core_audit_fd();
} else
log_warning_errno(errno, "Failed to send audit message, ignoring: %m");
}
+3 -5
View File
@@ -98,9 +98,7 @@ _printf_(2, 3) static int log_callback(int type, const char *fmt, ...) {
const char *fmt2;
#if HAVE_AUDIT
int fd;
fd = get_audit_fd();
int fd = get_core_audit_fd();
if (fd >= 0) {
_cleanup_free_ char *buf = NULL;
@@ -112,9 +110,9 @@ _printf_(2, 3) static int log_callback(int type, const char *fmt, ...) {
if (r >= 0) {
if (type == SELINUX_AVC)
audit_log_user_avc_message(get_audit_fd(), AUDIT_USER_AVC, buf, NULL, NULL, NULL, getuid());
audit_log_user_avc_message(fd, AUDIT_USER_AVC, buf, NULL, NULL, NULL, getuid());
else if (type == SELINUX_ERROR)
audit_log_user_avc_message(get_audit_fd(), AUDIT_USER_SELINUX_ERR, buf, NULL, NULL, NULL, getuid());
audit_log_user_avc_message(fd, AUDIT_USER_SELINUX_ERR, buf, NULL, NULL, NULL, getuid());
return 0;
}