/*
 * sestatus.c
 *
 * APIs to reference SELinux kernel status page (/selinux/status)
 *
 * Author: KaiGai Kohei <kaigai@ak.jp.nec.com>
 *
 */
#include <fcntl.h>
#include <limits.h>
#include <sched.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include "avc_internal.h"
#include "policy.h"

/*
 * copied from the selinux/include/security.h
 */
struct selinux_status_t
{
	uint32_t	version;	/* version number of thie structure */
	uint32_t	sequence;	/* sequence number of seqlock logic */
	uint32_t	enforcing;	/* current setting of enforcing mode */
	uint32_t	policyload;	/* times of policy reloaded */
	uint32_t	deny_unknown;	/* current setting of deny_unknown */
	/* version > 0 support above status */
} __attribute((packed));

/*
 * `selinux_status'
 *
 * NULL : not initialized yet
 * MAP_FAILED : opened, but fallback-mode
 * Valid Pointer : opened and mapped correctly
 */
static struct selinux_status_t *selinux_status = NULL;
static int			selinux_status_fd;
static uint32_t			last_seqno;

static uint32_t			fallback_sequence;
static int			fallback_enforcing;
static int			fallback_policyload;

/*
 * read_sequence
 *
 * A utility routine to reference kernel status page according to
 * seqlock logic. Since selinux_status->sequence is an odd value during
 * the kernel status page being updated, we try to synchronize completion
 * of this updating, but we assume it is rare.
 * The sequence is almost even number.
 *
 * __sync_synchronize is a portable memory barrier for various kind
 * of architecture that is supported by GCC.
 */
static inline uint32_t read_sequence(struct selinux_status_t *status)
{
	uint32_t	seqno = 0;

	do {
		/*
		 * No need for sched_yield() in the first trial of
		 * this loop.
		 */
		if (seqno & 0x0001)
			sched_yield();

		seqno = status->sequence;

		__sync_synchronize();

	} while (seqno & 0x0001);

	return seqno;
}

/*
 * selinux_status_updated
 *
 * It returns whether something has been happened since the last call.
 * Because `selinux_status->sequence' shall be always incremented on
 * both of setenforce/policyreload events, so differences from the last
 * value informs us something has been happened.
 */
int selinux_status_updated(void)
{
	uint32_t	curr_seqno;
	int		result = 0;

	if (selinux_status == NULL) {
		errno = EINVAL;
		return -1;
	}

	if (selinux_status == MAP_FAILED) {
		if (avc_netlink_check_nb() < 0)
			return -1;

		curr_seqno = fallback_sequence;
	} else {
		curr_seqno = read_sequence(selinux_status);
	}

	/*
	 * `curr_seqno' is always even-number, so it does not match with
	 * `last_seqno' being initialized to odd-number in the first call.
	 * We never return 'something was updated' in the first call,
	 * because this function focuses on status-updating since the last
	 * invocation.
	 */
	if (last_seqno & 0x0001)
		last_seqno = curr_seqno;

	if (last_seqno != curr_seqno)
	{
		last_seqno = curr_seqno;
		result = 1;
	}
	return result;
}

/*
 * selinux_status_getenforce
 *
 * It returns the current performing mode of SELinux.
 * 1 means currently we run in enforcing mode, or 0 means permissive mode.
 */
int selinux_status_getenforce(void)
{
	uint32_t	seqno;
	uint32_t	enforcing;

	if (selinux_status == NULL) {
		errno = EINVAL;
		return -1;
	}

	if (selinux_status == MAP_FAILED) {
		if (avc_netlink_check_nb() < 0)
			return -1;

		return fallback_enforcing;
	}

	/* sequence must not be changed during references */
	do {
		seqno = read_sequence(selinux_status);

		enforcing = selinux_status->enforcing;

	} while (seqno != read_sequence(selinux_status));

	return enforcing ? 1 : 0;
}

/*
 * selinux_status_policyload
 *
 * It returns times of policy reloaded on the running system.
 * Note that it is not a reliable value on fallback-mode until it receives
 * the first event message via netlink socket, so, a correct usage of this
 * value is to compare it with the previous value to detect policy reloaded
 * event.
 */
int selinux_status_policyload(void)
{
	uint32_t	seqno;
	uint32_t	policyload;

	if (selinux_status == NULL) {
		errno = EINVAL;
		return -1;
	}

	if (selinux_status == MAP_FAILED) {
		if (avc_netlink_check_nb() < 0)
			return -1;

		return fallback_policyload;
	}

	/* sequence must not be changed during references */
	do {
		seqno = read_sequence(selinux_status);

		policyload = selinux_status->policyload;

	} while (seqno != read_sequence(selinux_status));

	return policyload;
}

/*
 * selinux_status_deny_unknown
 *
 * It returns a guideline to handle undefined object classes or permissions.
 * 0 means SELinux treats policy queries on undefined stuff being allowed,
 * however, 1 means such queries are denied.
 */
int selinux_status_deny_unknown(void)
{
	uint32_t	seqno;
	uint32_t	deny_unknown;

	if (selinux_status == NULL) {
		errno = EINVAL;
		return -1;
	}

	if (selinux_status == MAP_FAILED)
		return security_deny_unknown();

	/* sequence must not be changed during references */
	do {
		seqno = read_sequence(selinux_status);

		deny_unknown = selinux_status->deny_unknown;

	} while (seqno != read_sequence(selinux_status));

	return deny_unknown ? 1 : 0;
}

/*
 * callback routines for fallback case using netlink socket
 */
static int fallback_cb_setenforce(int enforcing)
{
	fallback_sequence += 2;
	fallback_enforcing = enforcing;

	return 0;
}

static int fallback_cb_policyload(int policyload)
{
	fallback_sequence += 2;
	fallback_policyload = policyload;

	return 0;
}

/*
 * selinux_status_open
 *
 * It tries to open and mmap kernel status page (/selinux/status).
 * Since Linux 2.6.37 or later supports this feature, we may run
 * fallback routine using a netlink socket on older kernels, if
 * the supplied `fallback' is not zero.
 * It returns 0 on success, or -1 on error.
 */
int selinux_status_open(int fallback)
{
	int	fd;
	char	path[PATH_MAX];
	long	pagesize;

	if (!selinux_mnt) {
		errno = ENOENT;
		return -1;
	}

	pagesize = sysconf(_SC_PAGESIZE);
	if (pagesize < 0)
		return -1;

	snprintf(path, sizeof(path), "%s/status", selinux_mnt);
	fd = open(path, O_RDONLY | O_CLOEXEC);
	if (fd < 0)
		goto error;

	selinux_status = mmap(NULL, pagesize, PROT_READ, MAP_SHARED, fd, 0);
	if (selinux_status == MAP_FAILED) {
		close(fd);
		goto error;
	}
	selinux_status_fd = fd;
	last_seqno = (uint32_t)(-1);

	return 0;

error:
	/*
	 * If caller wants fallback routine, we try to provide
	 * an equivalent functionality using existing netlink
	 * socket, although it needs system call invocation to
	 * receive event notification.
	 */
	if (fallback && avc_netlink_open(0) == 0) {
		union selinux_callback	cb;

		/* register my callbacks */
		cb.func_setenforce = fallback_cb_setenforce;
		selinux_set_callback(SELINUX_CB_SETENFORCE, cb);
		cb.func_policyload = fallback_cb_policyload;
		selinux_set_callback(SELINUX_CB_POLICYLOAD, cb);

		/* mark as fallback mode */
		selinux_status = MAP_FAILED;
		selinux_status_fd = avc_netlink_acquire_fd();
		last_seqno = (uint32_t)(-1);

		fallback_sequence = 0;
		fallback_enforcing = security_getenforce();
		fallback_policyload = 0;

		return 1;
	}
	selinux_status = NULL;

	return -1;
}

/*
 * selinux_status_close
 *
 * It unmap and close the kernel status page, or close netlink socket
 * if fallback mode.
 */
void selinux_status_close(void)
{
	long pagesize;

	/* not opened */
	if (selinux_status == NULL)
		return;

	/* fallback-mode */
	if (selinux_status == MAP_FAILED)
	{
		avc_netlink_release_fd();
		avc_netlink_close();
		selinux_status = NULL;
		return;
	}

	pagesize = sysconf(_SC_PAGESIZE);
	/* not much we can do other than leak memory */
	if (pagesize > 0)
		munmap(selinux_status, pagesize);
	selinux_status = NULL;

	close(selinux_status_fd);
	selinux_status_fd = -1;
	last_seqno = (uint32_t)(-1);
}
