/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Landlock audit helpers
 *
 * Copyright © 2024-2025 Microsoft Corporation
 */

#define _GNU_SOURCE
#include <errno.h>
#include <linux/audit.h>
#include <linux/limits.h>
#include <linux/netlink.h>
#include <regex.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <unistd.h>

#include "kselftest.h"

#ifndef ARRAY_SIZE
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
#endif

#define REGEX_LANDLOCK_PREFIX "^audit([0-9.:]\\+): domain=\\([0-9a-f]\\+\\)"

struct audit_filter {
	__u32 record_type;
	size_t exe_len;
	char exe[PATH_MAX];
};

struct audit_message {
	struct nlmsghdr header;
	union {
		struct audit_status status;
		struct audit_features features;
		struct audit_rule_data rule;
		struct nlmsgerr err;
		char data[PATH_MAX + 200];
	};
};

static const struct timeval audit_tv_default = {
	/*
	 * Default socket timeout for audit_match_record() callers that expect a
	 * record to arrive.  Asynchronous kauditd delivery can exceed 1 usec
	 * under heavy debug configs (KASAN, lockdep), where kauditd_thread
	 * scheduling between audit_log_end() and netlink_unicast() takes longer
	 * than the previous 1 usec timeout. 1 second is a generous ceiling: on
	 * the happy path, kauditd delivers within dozens of usec.
	 */
	.tv_sec = 1,
};

static const struct timeval audit_tv_fast = {
	/*
	 * Fast timeout for paths that expect no record (audit_init() drain,
	 * audit_count_records(), probes).  Causes audit_recv() to return
	 * -EAGAIN once the socket buffer is empty, naturally terminating the
	 * read loop.
	 */
	.tv_usec = 1,
};

static int audit_send(const int fd, const struct audit_message *const msg)
{
	struct sockaddr_nl addr = {
		.nl_family = AF_NETLINK,
	};
	int ret;

	do {
		ret = sendto(fd, msg, msg->header.nlmsg_len, 0,
			     (struct sockaddr *)&addr, sizeof(addr));
	} while (ret < 0 && errno == EINTR);

	if (ret < 0)
		return -errno;

	if (ret != msg->header.nlmsg_len)
		return -E2BIG;

	return 0;
}

static int audit_recv(const int fd, struct audit_message *msg)
{
	struct sockaddr_nl addr;
	socklen_t addrlen = sizeof(addr);
	struct audit_message msg_tmp;
	int err;

	if (!msg)
		msg = &msg_tmp;

	do {
		err = recvfrom(fd, msg, sizeof(*msg), 0,
			       (struct sockaddr *)&addr, &addrlen);
	} while (err < 0 && errno == EINTR);

	if (err < 0)
		return -errno;

	if (addrlen != sizeof(addr) || addr.nl_pid != 0)
		return -EINVAL;

	/* Checks Netlink error or end of messages. */
	if (msg->header.nlmsg_type == NLMSG_ERROR)
		return msg->err.error;

	return 0;
}

static int audit_request(const int fd,
			 const struct audit_message *const request,
			 struct audit_message *reply)
{
	struct audit_message msg_tmp;
	bool first_reply = true;
	int err;

	err = audit_send(fd, request);
	if (err)
		return err;

	if (!reply)
		reply = &msg_tmp;

	do {
		if (first_reply)
			first_reply = false;
		else
			reply = &msg_tmp;

		err = audit_recv(fd, reply);
		if (err)
			return err;
	} while (reply->header.nlmsg_type != NLMSG_ERROR &&
		 reply->err.msg.nlmsg_type != request->header.nlmsg_type);

	return reply->err.error;
}

static int audit_filter_exe(const int audit_fd,
			    const struct audit_filter *const filter,
			    const __u16 type)
{
	struct audit_message msg = {
		.header = {
			.nlmsg_len = NLMSG_SPACE(sizeof(msg.rule)) +
				     NLMSG_ALIGN(filter->exe_len),
			.nlmsg_type = type,
			.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK,
		},
		.rule = {
			.flags = AUDIT_FILTER_EXCLUDE,
			.action = AUDIT_NEVER,
			.field_count = 1,
			.fields[0] = filter->record_type,
			.fieldflags[0] = AUDIT_NOT_EQUAL,
			.values[0] = filter->exe_len,
			.buflen = filter->exe_len,
		}
	};

	if (filter->record_type != AUDIT_EXE)
		return -EINVAL;

	memcpy(msg.rule.buf, filter->exe, filter->exe_len);
	return audit_request(audit_fd, &msg, NULL);
}

static int audit_filter_drop(const int audit_fd, const __u16 type)
{
	struct audit_message msg = {
		.header = {
			.nlmsg_len = NLMSG_SPACE(sizeof(msg.rule)),
			.nlmsg_type = type,
			.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK,
		},
		.rule = {
			.flags = AUDIT_FILTER_EXCLUDE,
			.action = AUDIT_NEVER,
			.field_count = 1,
			.fields[0] = AUDIT_MSGTYPE,
			.fieldflags[0] = AUDIT_NOT_EQUAL,
			.values[0] = AUDIT_LANDLOCK_DOMAIN,
		}
	};

	return audit_request(audit_fd, &msg, NULL);
}

static int audit_set_status(int fd, __u32 key, __u32 val)
{
	const struct audit_message msg = {
		.header = {
			.nlmsg_len = NLMSG_SPACE(sizeof(msg.status)),
			.nlmsg_type = AUDIT_SET,
			.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK,
		},
		.status = {
			.mask = key,
			.enabled = key == AUDIT_STATUS_ENABLED ? val : 0,
			.pid = key == AUDIT_STATUS_PID ? val : 0,
		}
	};

	return audit_request(fd, &msg, NULL);
}

/*
 * @domain_id: The domain ID extracted from the audit message (if the first part
 * of @pattern is REGEX_LANDLOCK_PREFIX).  It is set to 0 if the domain ID is
 * not found.
 */
static int audit_match_record(int audit_fd, const __u16 type,
			      const char *const pattern, __u64 *domain_id)
{
	struct audit_message msg, last_mismatch = {};
	int ret, err = 0;
	int num_type_match = 0;
	regmatch_t matches[2];
	regex_t regex;

	ret = regcomp(&regex, pattern, 0);
	if (ret)
		return -EINVAL;

	/*
	 * Reads records until one matches both the expected type and the
	 * pattern.  Type-matching records with non-matching content are
	 * silently consumed, which handles stale domain deallocation records
	 * from a previous test emitted asynchronously by kworker threads.
	 */
	while (true) {
		memset(&msg, 0, sizeof(msg));
		err = audit_recv(audit_fd, &msg);
		if (err) {
			if (num_type_match) {
				printf("DATA: %s\n", last_mismatch.data);
				printf("ERROR: %d record(s) matched type %u"
				       " but not pattern: %s\n",
				       num_type_match, type, pattern);
			}
			goto out;
		}

		if (type && msg.header.nlmsg_type != type)
			continue;

		ret = regexec(&regex, msg.data, ARRAY_SIZE(matches), matches,
			      0);
		if (!ret)
			break;

		num_type_match++;
		last_mismatch = msg;
	}

	if (domain_id) {
		*domain_id = 0;
		if (matches[1].rm_so != -1) {
			int match_len = matches[1].rm_eo - matches[1].rm_so;
			/* The maximal characters of a 2^64 hexadecimal number is 17. */
			char dom_id[18];

			if (match_len > 0 && match_len < sizeof(dom_id)) {
				memcpy(dom_id, msg.data + matches[1].rm_so,
				       match_len);
				dom_id[match_len] = '\0';
				if (domain_id)
					*domain_id = strtoull(dom_id, NULL, 16);
			}
		}
	}

out:
	regfree(&regex);
	return err;
}

static int __maybe_unused matches_log_domain_allocated(int audit_fd, pid_t pid,
						       __u64 *domain_id)
{
	static const char log_template[] = REGEX_LANDLOCK_PREFIX
		" status=allocated mode=enforcing pid=%d uid=[0-9]\\+"
		" exe=\"[^\"]\\+\" comm=\".*_test\"$";
	char log_match[sizeof(log_template) + 10];
	int log_match_len;

	log_match_len =
		snprintf(log_match, sizeof(log_match), log_template, pid);
	if (log_match_len >= sizeof(log_match))
		return -E2BIG;

	return audit_match_record(audit_fd, AUDIT_LANDLOCK_DOMAIN, log_match,
				  domain_id);
}

/*
 * Matches a domain deallocation record.  When expected_domain_id is non-zero,
 * the pattern includes the specific domain ID so that stale deallocation
 * records from a previous test (with a different domain ID) are skipped by
 * audit_match_record(), waiting for the asynchronous kworker deallocation with
 * the default patient timeout.
 *
 * When expected_domain_id is zero, the caller is probing for any dealloc record
 * that may or may not arrive.  Temporarily lowers the socket timeout to
 * audit_tv_fast for this probe so it returns promptly when no record is
 * pending; restores audit_tv_default after.
 */
static int __maybe_unused
matches_log_domain_deallocated(int audit_fd, unsigned int num_denials,
			       __u64 expected_domain_id, __u64 *domain_id)
{
	static const char log_template[] = REGEX_LANDLOCK_PREFIX
		" status=deallocated denials=%u$";
	static const char log_template_with_id[] =
		"^audit([0-9.:]\\+): domain=\\(%llx\\)"
		" status=deallocated denials=%u$";
	char log_match[sizeof(log_template_with_id) + 32];
	int log_match_len, err;

	if (expected_domain_id)
		log_match_len = snprintf(log_match, sizeof(log_match),
					 log_template_with_id,
					 (unsigned long long)expected_domain_id,
					 num_denials);
	else
		log_match_len = snprintf(log_match, sizeof(log_match),
					 log_template, num_denials);

	if (log_match_len >= sizeof(log_match))
		return -E2BIG;

	if (!expected_domain_id) {
		if (setsockopt(audit_fd, SOL_SOCKET, SO_RCVTIMEO,
			       &audit_tv_fast, sizeof(audit_tv_fast)))
			return -errno;
	}

	err = audit_match_record(audit_fd, AUDIT_LANDLOCK_DOMAIN, log_match,
				 domain_id);

	if (!expected_domain_id) {
		if (setsockopt(audit_fd, SOL_SOCKET, SO_RCVTIMEO,
			       &audit_tv_default, sizeof(audit_tv_default)) &&
		    !err)
			err = -errno;
	}

	return err;
}

struct audit_records {
	size_t access;
	size_t domain;
};

/*
 * Counts remaining audit records by type, skipping domain deallocation records.
 * Deallocation records are emitted asynchronously from kworker threads after a
 * previous test's child has exited, so they can arrive after the drain in
 * audit_init() and after the preceding audit_match_record() call.  Allocation
 * records are emitted synchronously during landlock_log_denial() in the current
 * test's syscall context, so only those are counted in records->domain.
 *
 * Temporarily lowers SO_RCVTIMEO to audit_tv_fast for the read loop: this is a
 * "no record expected" path that should terminate on the first -EAGAIN.  The
 * default patient timeout is restored on exit for subsequent
 * audit_match_record() callers.
 */
static int audit_count_records(int audit_fd, struct audit_records *records)
{
	static const char dealloc_pattern[] = REGEX_LANDLOCK_PREFIX
		" status=deallocated ";
	struct audit_message msg;
	regex_t dealloc_re;
	int ret, err = 0;

	ret = regcomp(&dealloc_re, dealloc_pattern, 0);
	if (ret)
		return -ENOMEM;

	records->access = 0;
	records->domain = 0;

	if (setsockopt(audit_fd, SOL_SOCKET, SO_RCVTIMEO, &audit_tv_fast,
		       sizeof(audit_tv_fast))) {
		err = -errno;
		goto out;
	}

	do {
		memset(&msg, 0, sizeof(msg));
		err = audit_recv(audit_fd, &msg);
		if (err) {
			if (err == -EAGAIN)
				err = 0;
			break;
		}

		switch (msg.header.nlmsg_type) {
		case AUDIT_LANDLOCK_ACCESS:
			records->access++;
			break;
		case AUDIT_LANDLOCK_DOMAIN:
			ret = regexec(&dealloc_re, msg.data, 0, NULL, 0);
			if (ret == REG_NOMATCH) {
				records->domain++;
			} else if (ret != 0) {
				err = -EIO;
				goto out;
			}
			break;
		}
	} while (true);

out:
	if (setsockopt(audit_fd, SOL_SOCKET, SO_RCVTIMEO, &audit_tv_default,
		       sizeof(audit_tv_default)) &&
	    !err)
		err = -errno;
	regfree(&dealloc_re);
	return err;
}

static int audit_init(void)
{
	int fd, err;

	fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_AUDIT);
	if (fd < 0)
		return -errno;

	err = audit_set_status(fd, AUDIT_STATUS_ENABLED, 1);
	if (err)
		goto err_close;

	err = audit_set_status(fd, AUDIT_STATUS_PID, getpid());
	if (err)
		goto err_close;

	/* Uses the fast timeout to drain stale records below. */
	err = setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &audit_tv_fast,
			 sizeof(audit_tv_fast));
	if (err) {
		err = -errno;
		goto err_close;
	}

	/*
	 * Drains stale audit records that accumulated in the kernel backlog
	 * while no audit daemon socket was open.  This happens when non-audit
	 * Landlock tests generate records while audit_enabled is non-zero (e.g.
	 * from boot configuration), or when domain deallocation records arrive
	 * asynchronously after a previous test's socket was closed.
	 */
	while (audit_recv(fd, NULL) == 0)
		;

	/*
	 * Restores the default timeout for audit_match_record() callers that
	 * expect a record to arrive.  Paths that expect no record restore the
	 * fast timeout locally (audit_count_records(), the expected_domain_id
	 * == 0 probe in matches_log_domain_deallocated()).
	 */
	err = setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &audit_tv_default,
			 sizeof(audit_tv_default));
	if (err) {
		err = -errno;
		goto err_close;
	}

	return fd;

err_close:
	close(fd);
	return err;
}

static int audit_init_filter_exe(struct audit_filter *filter, const char *path)
{
	char *absolute_path = NULL;

	/* It is assume that there is not already filtering rules. */
	filter->record_type = AUDIT_EXE;
	if (!path) {
		int ret = readlink("/proc/self/exe", filter->exe,
				   sizeof(filter->exe) - 1);
		if (ret < 0)
			return -errno;

		filter->exe_len = ret;
		return 0;
	}

	absolute_path = realpath(path, NULL);
	if (!absolute_path)
		return -errno;

	/* No need for the terminating NULL byte. */
	filter->exe_len = strlen(absolute_path);
	if (filter->exe_len > sizeof(filter->exe))
		return -E2BIG;

	memcpy(filter->exe, absolute_path, filter->exe_len);
	free(absolute_path);
	return 0;
}

static int audit_cleanup(int audit_fd, struct audit_filter *filter)
{
	struct audit_filter new_filter;
	int err = 0;

	if (audit_fd < 0 || !filter) {
		/*
		 * Simulates audit_init_with_exe_filter() when called from
		 * FIXTURE_TEARDOWN_PARENT().
		 */
		audit_fd = audit_init();
		if (audit_fd < 0)
			return audit_fd;

		filter = &new_filter;
		err = audit_init_filter_exe(filter, NULL);
		if (err)
			goto err_close;
	}

	/* Filters might not be in place. */
	audit_filter_exe(audit_fd, filter, AUDIT_DEL_RULE);
	audit_filter_drop(audit_fd, AUDIT_DEL_RULE);

	err = audit_set_status(audit_fd, AUDIT_STATUS_ENABLED, 0);

err_close:
	close(audit_fd);
	return err;
}

static int audit_init_with_exe_filter(struct audit_filter *filter)
{
	int fd, err;

	fd = audit_init();
	if (fd < 0)
		return fd;

	err = audit_init_filter_exe(filter, NULL);
	if (err)
		goto err_close;

	err = audit_filter_exe(fd, filter, AUDIT_ADD_RULE);
	if (err)
		goto err_close;

	return fd;

err_close:
	close(fd);
	return err;
}
