audit-util: return -ENODATA from audit_{session|loginuid}_from_pid() if invoked in a container
The auditing subsystem is still not virtualized for containers, hence the two values don't really make sense inside them, they will just leak information from outside into the container. Hence don't make use of the data if we detect we are run inside of a container. This has visible effects: logind will no longer try to reuse the auditing session ids as its own session ids when run inside a container. While are at it, modernize the calls in more ways: 1. switch to pidref behaviour, all but one of our uses are using pidref anyway already. 2. use read_virtual_file() + proc_mounted() 3. reasonable distinguish ENOENT errors when reading the process proc files: distinguish the case where /proc is not mounted, from the case where the process is already gone, from where auditing is not enabled in the kernel build.
This commit is contained in:
+50
-26
@@ -15,27 +15,59 @@
|
||||
#include "parse-util.h"
|
||||
#include "process-util.h"
|
||||
#include "socket-util.h"
|
||||
#include "stat-util.h"
|
||||
#include "user-util.h"
|
||||
#include "virt.h"
|
||||
|
||||
int audit_session_from_pid(pid_t pid, uint32_t *id) {
|
||||
_cleanup_free_ char *s = NULL;
|
||||
const char *p;
|
||||
uint32_t u;
|
||||
static int audit_read_field(const PidRef *pid, const char *field, char **ret) {
|
||||
int r;
|
||||
|
||||
assert(id);
|
||||
assert(field);
|
||||
assert(ret);
|
||||
|
||||
/* 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. */
|
||||
if (!pidref_is_set(pid))
|
||||
return -ESRCH;
|
||||
|
||||
p = procfs_file_alloca(pid, "sessionid");
|
||||
/* 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;
|
||||
|
||||
r = read_one_line_file(p, &s);
|
||||
const char *p = procfs_file_alloca(pid->pid, field);
|
||||
|
||||
_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;
|
||||
|
||||
uint32_t u;
|
||||
r = safe_atou32(s, &u);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@@ -43,32 +75,24 @@ int audit_session_from_pid(pid_t pid, uint32_t *id) {
|
||||
if (!audit_session_is_valid(u))
|
||||
return -ENODATA;
|
||||
|
||||
*id = u;
|
||||
if (ret_id)
|
||||
*ret_id = u;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int audit_loginuid_from_pid(pid_t pid, uid_t *uid) {
|
||||
int audit_loginuid_from_pid(const PidRef *pid, uid_t *ret_uid) {
|
||||
_cleanup_free_ char *s = NULL;
|
||||
const char *p;
|
||||
uid_t u;
|
||||
int r;
|
||||
|
||||
assert(uid);
|
||||
|
||||
p = procfs_file_alloca(pid, "loginuid");
|
||||
|
||||
r = read_one_line_file(p, &s);
|
||||
r = audit_read_field(pid, "loginuid", &s);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = parse_uid(s, &u);
|
||||
if (r == -ENXIO) /* the UID was -1 */
|
||||
if (streq(s, "4294967295")) /* loginuid as 4294967295 means not part of any session. */
|
||||
return -ENODATA;
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*uid = u;
|
||||
return 0;
|
||||
return parse_uid(s, ret_uid);
|
||||
}
|
||||
|
||||
static int try_audit_request(int fd) {
|
||||
|
||||
@@ -5,10 +5,12 @@
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "pidref.h"
|
||||
|
||||
#define AUDIT_SESSION_INVALID UINT32_MAX
|
||||
|
||||
int audit_session_from_pid(pid_t pid, uint32_t *id);
|
||||
int audit_loginuid_from_pid(pid_t pid, uid_t *uid);
|
||||
int audit_session_from_pid(const PidRef *pid, uint32_t *id);
|
||||
int audit_loginuid_from_pid(const PidRef *pid, uid_t *uid);
|
||||
|
||||
bool use_audit(void);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user