Revert "audit-util: return -ENODATA from audit_{session|loginuid}_from_pid() …"

This commit is contained in:
Luca Boccassi 2024-11-20 10:01:06 +00:00 committed by GitHub
parent 52b0351a15
commit be46e1d70f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 68 additions and 137 deletions

View File

@ -15,59 +15,27 @@
#include "parse-util.h"
#include "process-util.h"
#include "socket-util.h"
#include "stat-util.h"
#include "user-util.h"
#include "virt.h"
static int audit_read_field(const PidRef *pid, const char *field, char **ret) {
int r;
assert(field);
assert(ret);
if (!pidref_is_set(pid))
return -ESRCH;
/* Auditing is currently not virtualized for containers. Let's hence not use the audit session ID or
* login UID for now, it will be leaked in from the host */
if (detect_container() > 0)
return -ENODATA;
const char *p = procfs_file_alloca(pid->pid, field);
int audit_session_from_pid(pid_t pid, uint32_t *id) {
_cleanup_free_ char *s = NULL;
bool enoent = false;
r = read_virtual_file(p, SIZE_MAX, &s, /* ret_size= */ NULL);
if (r == -ENOENT) {
if (proc_mounted() == 0)
return -ENOSYS;
enoent = true;
} else if (r < 0)
return r;
r = pidref_verify(pid);
if (r < 0)
return r;
if (enoent) /* We got ENOENT, but /proc/ was mounted and the PID still valid? In that case it appears
* auditing is not supported by the kernel. */
return -ENODATA;
delete_trailing_chars(s, NEWLINE);
*ret = TAKE_PTR(s);
return 0;
}
int audit_session_from_pid(const PidRef *pid, uint32_t *ret_id) {
_cleanup_free_ char *s = NULL;
int r;
r = audit_read_field(pid, "sessionid", &s);
if (r < 0)
return r;
const char *p;
uint32_t u;
int r;
assert(id);
/* We don't convert ENOENT to ESRCH here, since we can't
* really distinguish between "audit is not available in the
* kernel" and "the process does not exist", both which will
* result in ENOENT. */
p = procfs_file_alloca(pid, "sessionid");
r = read_one_line_file(p, &s);
if (r < 0)
return r;
r = safe_atou32(s, &u);
if (r < 0)
return r;
@ -75,24 +43,32 @@ int audit_session_from_pid(const PidRef *pid, uint32_t *ret_id) {
if (!audit_session_is_valid(u))
return -ENODATA;
if (ret_id)
*ret_id = u;
*id = u;
return 0;
}
int audit_loginuid_from_pid(const PidRef *pid, uid_t *ret_uid) {
int audit_loginuid_from_pid(pid_t pid, uid_t *uid) {
_cleanup_free_ char *s = NULL;
const char *p;
uid_t u;
int r;
r = audit_read_field(pid, "loginuid", &s);
assert(uid);
p = procfs_file_alloca(pid, "loginuid");
r = read_one_line_file(p, &s);
if (r < 0)
return r;
if (streq(s, "4294967295")) /* loginuid as 4294967295 means not part of any session. */
r = parse_uid(s, &u);
if (r == -ENXIO) /* the UID was -1 */
return -ENODATA;
if (r < 0)
return r;
return parse_uid(s, ret_uid);
*uid = u;
return 0;
}
static int try_audit_request(int fd) {
@ -137,32 +113,33 @@ bool use_audit(void) {
static int cached_use = -1;
int r;
if (cached_use >= 0)
return cached_use;
if (cached_use < 0) {
int fd;
_cleanup_close_ int fd = socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, NETLINK_AUDIT);
if (fd < 0) {
cached_use = !ERRNO_IS_PRIVILEGE(errno) && !ERRNO_IS_NOT_SUPPORTED(errno);
if (cached_use)
log_debug_errno(errno, "Unexpected error while creating audit socket, proceeding with its use: %m");
else
log_debug_errno(errno, "Won't talk to audit, because feature or privilege absent: %m");
} else {
/* If we try and use the audit fd but get -ECONNREFUSED, it is because we are not in the
* initial user namespace, and the kernel does not have support for audit outside of the
* initial user namespace (see
* https://elixir.bootlin.com/linux/latest/C/ident/audit_netlink_ok).
*
* If we receive any other error, do not disable audit because we are not sure that the error
* indicates that audit will not work in general. */
r = try_audit_request(fd);
if (r < 0) {
cached_use = r != -ECONNREFUSED;
log_debug_errno(r, cached_use ?
"Failed to make request on audit fd, ignoring: %m" :
"Won't talk to audit: %m");
} else
cached_use = true;
fd = socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, NETLINK_AUDIT);
if (fd < 0) {
cached_use = !IN_SET(errno, EAFNOSUPPORT, EPROTONOSUPPORT, EPERM);
if (!cached_use)
log_debug_errno(errno, "Won't talk to audit: %m");
} else {
/* If we try and use the audit fd but get -ECONNREFUSED, it is because
* we are not in the initial user namespace, and the kernel does not
* have support for audit outside of the initial user namespace
* (see https://elixir.bootlin.com/linux/latest/C/ident/audit_netlink_ok).
*
* If we receive any other error, do not disable audit because we are not
* sure that the error indicates that audit will not work in general. */
r = try_audit_request(fd);
if (r < 0) {
cached_use = r != -ECONNREFUSED;
log_debug_errno(r, cached_use ?
"Failed to make request on audit fd, ignoring: %m" :
"Won't talk to audit: %m");
} else
cached_use = true;
safe_close(fd);
}
}
return cached_use;

View File

@ -5,12 +5,10 @@
#include <stdint.h>
#include <sys/types.h>
#include "pidref.h"
#define AUDIT_SESSION_INVALID UINT32_MAX
int audit_session_from_pid(const PidRef *pid, uint32_t *id);
int audit_loginuid_from_pid(const PidRef *pid, uid_t *uid);
int audit_session_from_pid(pid_t pid, uint32_t *id);
int audit_loginuid_from_pid(pid_t pid, uid_t *uid);
bool use_audit(void);

View File

@ -1815,9 +1815,6 @@ int namespace_fork(
int set_oom_score_adjust(int value) {
char t[DECIMAL_STR_MAX(int)];
if (!oom_score_adjust_is_valid(value))
return -EINVAL;
xsprintf(t, "%i", value);
return write_string_file("/proc/self/oom_score_adj", t,
@ -1834,16 +1831,11 @@ int get_oom_score_adjust(int *ret) {
delete_trailing_chars(t, WHITESPACE);
r = safe_atoi(t, &a);
if (r < 0)
return r;
if (!oom_score_adjust_is_valid(a))
return -ENODATA;
assert_se(safe_atoi(t, &a) >= 0);
assert_se(oom_score_adjust_is_valid(a));
if (ret)
*ret = a;
return 0;
}

View File

@ -526,8 +526,8 @@ static void client_context_really_refresh(
client_context_read_basic(c);
(void) client_context_read_label(c, label, label_size);
(void) audit_session_from_pid(&PIDREF_MAKE_FROM_PID(c->pid), &c->auditid);
(void) audit_loginuid_from_pid(&PIDREF_MAKE_FROM_PID(c->pid), &c->loginuid);
(void) audit_session_from_pid(c->pid, &c->auditid);
(void) audit_loginuid_from_pid(c->pid, &c->loginuid);
(void) client_context_read_cgroup(s, c, unit_id);
(void) client_context_read_invocation_id(s, c);

View File

@ -1118,7 +1118,7 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, PidRef *pidref, pid_t tid
}
if (missing & SD_BUS_CREDS_AUDIT_SESSION_ID) {
r = audit_session_from_pid(pidref, &c->audit_session_id);
r = audit_session_from_pid(pidref->pid, &c->audit_session_id);
if (r == -ENODATA) {
/* ENODATA means: no audit session id assigned */
c->audit_session_id = AUDIT_SESSION_INVALID;
@ -1131,7 +1131,7 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, PidRef *pidref, pid_t tid
}
if (missing & SD_BUS_CREDS_AUDIT_LOGIN_UID) {
r = audit_loginuid_from_pid(pidref, &c->audit_login_uid);
r = audit_loginuid_from_pid(pidref->pid, &c->audit_login_uid);
if (r == -ENODATA) {
/* ENODATA means: no audit login uid assigned */
c->audit_login_uid = UID_INVALID;

View File

@ -1006,7 +1006,7 @@ static int create_session(
"Maximum number of sessions (%" PRIu64 ") reached, refusing further sessions.",
m->sessions_max);
(void) audit_session_from_pid(&leader, &audit_id);
(void) audit_session_from_pid(leader.pid, &audit_id);
if (audit_session_is_valid(audit_id)) {
/* Keep our session IDs and the audit session IDs in sync */

View File

@ -254,7 +254,7 @@ int session_set_leader_consume(Session *s, PidRef _leader) {
s->leader_fd_saved = true;
}
(void) audit_session_from_pid(&s->leader, &s->audit_id);
(void) audit_session_from_pid(s->leader.pid, &s->audit_id);
return 1;
}

View File

@ -46,7 +46,6 @@ simple_tests += files(
'test-alloc-util.c',
'test-architecture.c',
'test-argv-util.c',
'test-audit-util.c',
'test-barrier.c',
'test-bitfield.c',
'test-bitmap.c',

View File

@ -1,35 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "audit-util.h"
#include "tests.h"
TEST(audit_loginuid_from_pid) {
_cleanup_(pidref_done) PidRef self = PIDREF_NULL, pid1 = PIDREF_NULL;
int r;
assert_se(pidref_set_self(&self) >= 0);
assert_se(pidref_set_pid(&pid1, 1) >= 0);
uid_t uid;
r = audit_loginuid_from_pid(&self, &uid);
assert_se(r >= 0 || r == -ENODATA);
if (r >= 0)
log_info("self audit login uid: " UID_FMT, uid);
assert_se(audit_loginuid_from_pid(&pid1, &uid) == -ENODATA);
uint32_t sessionid;
r = audit_session_from_pid(&self, &sessionid);
assert_se(r >= 0 || r == -ENODATA);
if (r >= 0)
log_info("self audit session id: %" PRIu32, sessionid);
assert_se(audit_session_from_pid(&pid1, &sessionid) == -ENODATA);
}
static int intro(void) {
log_show_color(true);
return EXIT_SUCCESS;
}
DEFINE_TEST_MAIN_WITH_INTRO(LOG_INFO, intro);