// SPDX-License-Identifier: GPL-2.0
/*
 * Creating audit events from TTY input.
 *
 * Copyright (C) 2007 Red Hat, Inc.  All rights reserved.
 *
 * Authors: Miloslav Trmac <mitr@redhat.com>
 */

#include <linux/audit.h>
#include <linux/slab.h>
#include <linux/tty.h>
#include "tty.h"

#define TTY_AUDIT_BUF_SIZE	4096

struct tty_audit_buf {
	struct mutex mutex;	/* Protects all data below */
	dev_t dev;		/* The TTY which the data is from */
	bool icanon;
	size_t valid;
	u8 *data;		/* Allocated size TTY_AUDIT_BUF_SIZE */
};

static struct tty_audit_buf *tty_audit_buf_ref(void)
{
	struct tty_audit_buf *buf;

	buf = current->signal->tty_audit_buf;
	WARN_ON(buf == ERR_PTR(-ESRCH));
	return buf;
}

static struct tty_audit_buf *tty_audit_buf_alloc(void)
{
	struct tty_audit_buf *buf;

	buf = kzalloc_obj(*buf);
	if (!buf)
		goto err;

	buf->data = kmalloc(TTY_AUDIT_BUF_SIZE, GFP_KERNEL);
	if (!buf->data)
		goto err_buf;

	mutex_init(&buf->mutex);

	return buf;

err_buf:
	kfree(buf);
err:
	return NULL;
}

static void tty_audit_buf_free(struct tty_audit_buf *buf)
{
	WARN_ON(buf->valid != 0);
	kfree(buf->data);
	kfree(buf);
}

static void tty_audit_log(const char *description, dev_t dev,
			  const u8 *data, size_t size)
{
	struct audit_buffer *ab;
	pid_t pid = task_pid_nr(current);
	uid_t uid = from_kuid(&init_user_ns, task_uid(current));
	uid_t loginuid = from_kuid(&init_user_ns, audit_get_loginuid(current));
	unsigned int sessionid = audit_get_sessionid(current);
	char name[TASK_COMM_LEN];

	ab = audit_log_start(audit_context(), GFP_KERNEL, AUDIT_TTY);
	if (!ab)
		return;

	audit_log_format(ab, "%s pid=%u uid=%u auid=%u ses=%u major=%d minor=%d comm=",
			 description, pid, uid, loginuid, sessionid,
			 MAJOR(dev), MINOR(dev));
	get_task_comm(name, current);
	audit_log_untrustedstring(ab, name);
	audit_log_format(ab, " data=");
	audit_log_n_hex(ab, data, size);
	audit_log_end(ab);
}

/*
 *	tty_audit_buf_push	-	Push buffered data out
 *
 *	Generate an audit message from the contents of @buf, which is owned by
 *	the current task.  @buf->mutex must be locked.
 */
static void tty_audit_buf_push(struct tty_audit_buf *buf)
{
	if (buf->valid == 0)
		return;
	if (audit_enabled == AUDIT_OFF) {
		buf->valid = 0;
		return;
	}
	tty_audit_log("tty", buf->dev, buf->data, buf->valid);
	buf->valid = 0;
}

/**
 *	tty_audit_exit	-	Handle a task exit
 *
 *	Make sure all buffered data is written out and deallocate the buffer.
 *	Only needs to be called if current->signal->tty_audit_buf != %NULL.
 *
 *	The process is single-threaded at this point; no other threads share
 *	current->signal.
 */
void tty_audit_exit(void)
{
	struct tty_audit_buf *buf;

	buf = xchg(&current->signal->tty_audit_buf, ERR_PTR(-ESRCH));
	if (!buf)
		return;

	tty_audit_buf_push(buf);
	tty_audit_buf_free(buf);
}

/*
 *	tty_audit_fork	-	Copy TTY audit state for a new task
 *
 *	Set up TTY audit state in @sig from current.  @sig needs no locking.
 */
void tty_audit_fork(struct signal_struct *sig)
{
	sig->audit_tty = current->signal->audit_tty;
}

/*
 *	tty_audit_tiocsti	-	Log TIOCSTI
 */
void tty_audit_tiocsti(const struct tty_struct *tty, u8 ch)
{
	dev_t dev;

	dev = MKDEV(tty->driver->major, tty->driver->minor_start) + tty->index;
	if (tty_audit_push())
		return;

	if (audit_enabled)
		tty_audit_log("ioctl=TIOCSTI", dev, &ch, 1);
}

/*
 *	tty_audit_push	-	Flush current's pending audit data
 *
 *	Returns 0 if success, -EPERM if tty audit is disabled
 */
int tty_audit_push(void)
{
	struct tty_audit_buf *buf;

	if (~current->signal->audit_tty & AUDIT_TTY_ENABLE)
		return -EPERM;

	buf = tty_audit_buf_ref();
	if (!IS_ERR_OR_NULL(buf)) {
		mutex_lock(&buf->mutex);
		tty_audit_buf_push(buf);
		mutex_unlock(&buf->mutex);
	}
	return 0;
}

/*
 *	tty_audit_buf_get	-	Get an audit buffer.
 *
 *	Get an audit buffer, allocate it if necessary.  Return %NULL
 *	if out of memory or ERR_PTR(-ESRCH) if tty_audit_exit() has already
 *	occurred.  Otherwise, return a new reference to the buffer.
 */
static struct tty_audit_buf *tty_audit_buf_get(void)
{
	struct tty_audit_buf *buf;

	buf = tty_audit_buf_ref();
	if (buf)
		return buf;

	buf = tty_audit_buf_alloc();
	if (buf == NULL) {
		audit_log_lost("out of memory in TTY auditing");
		return NULL;
	}

	/* Race to use this buffer, free it if another wins */
	if (cmpxchg(&current->signal->tty_audit_buf, NULL, buf) != NULL)
		tty_audit_buf_free(buf);
	return tty_audit_buf_ref();
}

/*
 *	tty_audit_add_data	-	Add data for TTY auditing.
 *
 *	Audit @data of @size from @tty, if necessary.
 */
void tty_audit_add_data(const struct tty_struct *tty, const void *data,
			size_t size)
{
	struct tty_audit_buf *buf;
	unsigned int audit_tty;
	bool icanon = L_ICANON(tty);
	dev_t dev;

	audit_tty = READ_ONCE(current->signal->audit_tty);
	if (~audit_tty & AUDIT_TTY_ENABLE)
		return;

	if (unlikely(size == 0))
		return;

	if (tty->driver->type == TTY_DRIVER_TYPE_PTY
	    && tty->driver->subtype == PTY_TYPE_MASTER)
		return;

	if ((~audit_tty & AUDIT_TTY_LOG_PASSWD) && icanon && !L_ECHO(tty))
		return;

	buf = tty_audit_buf_get();
	if (IS_ERR_OR_NULL(buf))
		return;

	mutex_lock(&buf->mutex);
	dev = MKDEV(tty->driver->major, tty->driver->minor_start) + tty->index;
	if (buf->dev != dev || buf->icanon != icanon) {
		tty_audit_buf_push(buf);
		buf->dev = dev;
		buf->icanon = icanon;
	}
	do {
		size_t run;

		run = TTY_AUDIT_BUF_SIZE - buf->valid;
		if (run > size)
			run = size;
		memcpy(buf->data + buf->valid, data, run);
		buf->valid += run;
		data += run;
		size -= run;
		if (buf->valid == TTY_AUDIT_BUF_SIZE)
			tty_audit_buf_push(buf);
	} while (size != 0);
	mutex_unlock(&buf->mutex);
}
