tty: audit: Defer audit buffer association

The tty audit buffer used to audit/record tty input is allocated on
the process's first call to tty_audit_add_data(), and not freed until
the process exits. On each call to tty_audit_add_data(), the current
tty is compared (by major:minor) with the last tty associated with
the audit buffer, and if the tty has changed the existing data is
logged to the audit log. The audit buffer is then re-associated with
the new tty.

Currently, the audit buffer is immediately associated with the tty;
however, the association must be re-checked when the buffer is locked
prior to copying the tty input. This extra step is always necessary,
since a concurrent read of a different tty by another thread of the
process may have used the buffer in between allocation and buffer
lock.

Rather than associate the audit buffer with the tty at allocation,
leave the buffer initially un-associated (null dev_t); simply let the
re-association check also perform the initial association.

Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Peter Hurley 2016-01-09 22:55:28 -08:00 committed by Greg Kroah-Hartman
parent 309426ae69
commit a75c9b0912

View file

@ -22,7 +22,7 @@ struct tty_audit_buf {
unsigned char *data; /* Allocated size N_TTY_BUF_SIZE */
};
static struct tty_audit_buf *tty_audit_buf_alloc(struct tty_struct *tty)
static struct tty_audit_buf *tty_audit_buf_alloc(void)
{
struct tty_audit_buf *buf;
@ -34,9 +34,9 @@ static struct tty_audit_buf *tty_audit_buf_alloc(struct tty_struct *tty)
goto err_buf;
atomic_set(&buf->count, 1);
mutex_init(&buf->mutex);
buf->major = tty->driver->major;
buf->minor = tty->driver->minor_start + tty->index;
buf->icanon = !!L_ICANON(tty);
buf->major = 0;
buf->minor = 0;
buf->icanon = 0;
buf->valid = 0;
return buf;
@ -211,11 +211,11 @@ int tty_audit_push_current(void)
/**
* tty_audit_buf_get - Get an audit buffer.
*
* Get an audit buffer for @tty, allocate it if necessary. Return %NULL
* Get an audit buffer, allocate it if necessary. Return %NULL
* if TTY auditing is disabled or out of memory. Otherwise, return a new
* reference to the buffer.
*/
static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty)
static struct tty_audit_buf *tty_audit_buf_get(void)
{
struct tty_audit_buf *buf, *buf2;
unsigned long flags;
@ -232,7 +232,7 @@ static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty)
}
spin_unlock_irqrestore(&current->sighand->siglock, flags);
buf2 = tty_audit_buf_alloc(tty);
buf2 = tty_audit_buf_alloc();
if (buf2 == NULL) {
audit_log_lost("out of memory in TTY auditing");
return NULL;
@ -282,7 +282,7 @@ void tty_audit_add_data(struct tty_struct *tty, const void *data, size_t size)
if (!audit_log_tty_passwd && icanon && !L_ECHO(tty))
return;
buf = tty_audit_buf_get(tty);
buf = tty_audit_buf_get();
if (!buf)
return;