/** * 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(¤t->sighand->siglock, flags); audit_log_tty_passwd = current->signal->audit_tty_log_passwd; spin_unlock_irqrestore(¤t->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(¤t->sighand->siglock, flags); if (likely(!current->signal->audit_tty)) { spin_unlock_irqrestore(¤t->sighand->siglock, flags); return; } buf = current->signal->tty_audit_buf; if (buf) atomic_inc(&buf->count); spin_unlock_irqrestore(¤t->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(¤t->sighand->siglock, flags); should_audit = current->signal->audit_tty; buf = current->signal->tty_audit_buf; if (buf) atomic_inc(&buf->count); spin_unlock_irqrestore(¤t->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); }
/** * 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); }
/** * 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); }