/**
 *	tty_audit_add_data	-	Add data for TTY auditing.
 *
 *	Audit @data of @size from @tty, if necessary.
 */
void tty_audit_add_data(struct tty_struct *tty, unsigned char *data,
			size_t size, unsigned icanon)
{
	struct tty_audit_buf *buf;
	int major, minor;
	int audit_log_tty_passwd;
	unsigned long flags;

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

	spin_lock_irqsave(&current->sighand->siglock, flags);
	audit_log_tty_passwd = current->signal->audit_tty_log_passwd;
	spin_unlock_irqrestore(&current->sighand->siglock, flags);
	if (!audit_log_tty_passwd && icanon && !L_ECHO(tty))
		return;

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

	buf = tty_audit_buf_get(tty, icanon);
	if (!buf)
		return;

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

		run = N_TTY_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 == N_TTY_BUF_SIZE)
			tty_audit_buf_push(buf);
	} while (size != 0);
	mutex_unlock(&buf->mutex);
	tty_audit_buf_put(buf);
}
/**
 *	tty_audit_push	-	Push buffered data out
 *
 *	Make sure no audit data is pending for @tty on the current process.
 */
void tty_audit_push(struct tty_struct *tty)
{
	struct tty_audit_buf *buf;
	unsigned long flags;

	spin_lock_irqsave(&current->sighand->siglock, flags);
	if (likely(!current->signal->audit_tty)) {
		spin_unlock_irqrestore(&current->sighand->siglock, flags);
		return;
	}
	buf = current->signal->tty_audit_buf;
	if (buf)
		atomic_inc(&buf->count);
	spin_unlock_irqrestore(&current->sighand->siglock, flags);

	if (buf) {
		int major, minor;

		major = tty->driver->major;
		minor = tty->driver->minor_start + tty->index;
		mutex_lock(&buf->mutex);
		if (buf->major == major && buf->minor == minor)
			tty_audit_buf_push(buf);
		mutex_unlock(&buf->mutex);
		tty_audit_buf_put(buf);
	}
}
/**
 * tty_audit_push_current -	Flush current's pending audit data
 *
 * Try to lock sighand and get a reference to the tty audit buffer if available.
 * Flush the buffer or return an appropriate error code.
 */
int tty_audit_push_current(void)
{
	struct tty_audit_buf *buf = ERR_PTR(-EPERM);
	struct task_struct *tsk = current;
	unsigned long flags;

	if (!lock_task_sighand(tsk, &flags))
		return -ESRCH;

	if (tsk->signal->audit_tty) {
		buf = tsk->signal->tty_audit_buf;
		if (buf)
			atomic_inc(&buf->count);
	}
	unlock_task_sighand(tsk, &flags);

	/*
	 * Return 0 when signal->audit_tty set
	 * but tsk->signal->tty_audit_buf == NULL.
	 */
	if (!buf || IS_ERR(buf))
		return PTR_ERR(buf);

	mutex_lock(&buf->mutex);
	tty_audit_buf_push(buf);
	mutex_unlock(&buf->mutex);

	tty_audit_buf_put(buf);
	return 0;
}
/**
 *	tty_audit_tiocsti	-	Log TIOCSTI
 */
void tty_audit_tiocsti(struct tty_struct *tty, char ch)
{
	struct tty_audit_buf *buf;
	int major, minor, should_audit;
	unsigned long flags;

	spin_lock_irqsave(&current->sighand->siglock, flags);
	should_audit = current->signal->audit_tty;
	buf = current->signal->tty_audit_buf;
	if (buf)
		atomic_inc(&buf->count);
	spin_unlock_irqrestore(&current->sighand->siglock, flags);

	major = tty->driver->major;
	minor = tty->driver->minor_start + tty->index;
	if (buf) {
		mutex_lock(&buf->mutex);
		if (buf->major == major && buf->minor == minor)
			tty_audit_buf_push(buf);
		mutex_unlock(&buf->mutex);
		tty_audit_buf_put(buf);
	}

	if (should_audit && audit_enabled) {
		kuid_t auid;
		unsigned int sessionid;

		auid = audit_get_loginuid(current);
		sessionid = audit_get_sessionid(current);
		tty_audit_log("ioctl=TIOCSTI", major, minor, &ch, 1);
	}
}
int tty_audit_push_task(struct task_struct *tsk, uid_t loginuid, u32 sessionid)
{
	struct tty_audit_buf *buf = ERR_PTR(-EPERM);
	unsigned long flags;

	if (!lock_task_sighand(tsk, &flags))
		return -ESRCH;

	if (tsk->signal->audit_tty) {
		buf = tsk->signal->tty_audit_buf;
		if (buf)
			atomic_inc(&buf->count);
	}
	unlock_task_sighand(tsk, &flags);

	/*
                                       
                                           
  */
	if (!buf || IS_ERR(buf))
		return PTR_ERR(buf);

	mutex_lock(&buf->mutex);
	tty_audit_buf_push(tsk, loginuid, sessionid, buf);
	mutex_unlock(&buf->mutex);

	tty_audit_buf_put(buf);
	return 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.
 */
void tty_audit_exit(void)
{
	struct tty_audit_buf *buf;

	buf = current->signal->tty_audit_buf;
	current->signal->tty_audit_buf = NULL;
	if (!buf)
		return;

	mutex_lock(&buf->mutex);
	tty_audit_buf_push(buf);
	mutex_unlock(&buf->mutex);

	tty_audit_buf_put(buf);
}
Example #7
0
/**
 *	tty_audit_push_task	-	Flush task's pending audit data
 */
void tty_audit_push_task(struct task_struct *tsk, uid_t loginuid, u32 sessionid)
{
	struct tty_audit_buf *buf;

	spin_lock_irq(&tsk->sighand->siglock);
	buf = tsk->signal->tty_audit_buf;
	if (buf)
		atomic_inc(&buf->count);
	spin_unlock_irq(&tsk->sighand->siglock);
	if (!buf)
		return;

	mutex_lock(&buf->mutex);
	tty_audit_buf_push(tsk, loginuid, sessionid, buf);
	mutex_unlock(&buf->mutex);

	tty_audit_buf_put(buf);
}
Example #8
0
/**
 *	tty_audit_buf_push_current	-	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_current(struct tty_audit_buf *buf)
{
	uid_t auid = audit_get_loginuid(current);
	unsigned int sessionid = audit_get_sessionid(current);
	tty_audit_buf_push(current, auid, sessionid, buf);
}