lkml.org 
[lkml]   [2016]   [Jan]   [10]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v2 09/15] tty: audit: Handle tty audit enable atomically
    Date
    The audit_tty and audit_tty_log_passwd fields are actually bool
    values, so merge into single memory location to access atomically.

    NB: audit log operations may still occur after tty audit is disabled
    which is consistent with the existing functionality

    Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
    ---
    drivers/tty/tty_audit.c | 53 ++++++++++++++++++++-----------------------------
    include/linux/audit.h | 4 ++++
    include/linux/sched.h | 1 -
    kernel/audit.c | 25 +++++++++++------------
    4 files changed, 38 insertions(+), 45 deletions(-)

    diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c
    index 50380d8..3d90f88 100644
    --- a/drivers/tty/tty_audit.c
    +++ b/drivers/tty/tty_audit.c
    @@ -131,7 +131,6 @@ void tty_audit_exit(void)
    void tty_audit_fork(struct signal_struct *sig)
    {
    sig->audit_tty = current->signal->audit_tty;
    - sig->audit_tty_log_passwd = current->signal->audit_tty_log_passwd;
    }

    /**
    @@ -141,11 +140,9 @@ void tty_audit_tiocsti(struct tty_struct *tty, char ch)
    {
    struct tty_audit_buf *buf;
    dev_t dev;
    - int 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);
    @@ -160,7 +157,7 @@ void tty_audit_tiocsti(struct tty_struct *tty, char ch)
    tty_audit_buf_put(buf);
    }

    - if (should_audit && audit_enabled) {
    + if (audit_enabled && (current->signal->audit_tty & AUDIT_TTY_ENABLE)) {
    kuid_t auid;
    unsigned int sessionid;

    @@ -177,29 +174,25 @@ void tty_audit_tiocsti(struct tty_struct *tty, char ch)
    */
    int tty_audit_push(void)
    {
    - struct tty_audit_buf *buf = ERR_PTR(-EPERM);
    + struct tty_audit_buf *buf;
    unsigned long flags;

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

    - /*
    - * Return 0 when signal->audit_tty set
    - * but current->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);
    + if (buf) {
    + mutex_lock(&buf->mutex);
    + tty_audit_buf_push(buf);
    + mutex_unlock(&buf->mutex);

    - tty_audit_buf_put(buf);
    + tty_audit_buf_put(buf);
    + }
    return 0;
    }

    @@ -218,8 +211,6 @@ static struct tty_audit_buf *tty_audit_buf_get(void)
    buf = NULL;
    buf2 = NULL;
    spin_lock_irqsave(&current->sighand->siglock, flags);
    - if (likely(!current->signal->audit_tty))
    - goto out;
    buf = current->signal->tty_audit_buf;
    if (buf) {
    atomic_inc(&buf->count);
    @@ -233,9 +224,10 @@ static struct tty_audit_buf *tty_audit_buf_get(void)
    return NULL;
    }

    - spin_lock_irqsave(&current->sighand->siglock, flags);
    - if (!current->signal->audit_tty)
    + if (~current->signal->audit_tty & AUDIT_TTY_ENABLE)
    goto out;
    +
    + spin_lock_irqsave(&current->sighand->siglock, flags);
    buf = current->signal->tty_audit_buf;
    if (!buf) {
    current->signal->tty_audit_buf = buf2;
    @@ -259,9 +251,8 @@ static struct tty_audit_buf *tty_audit_buf_get(void)
    void tty_audit_add_data(struct tty_struct *tty, const void *data, size_t size)
    {
    struct tty_audit_buf *buf;
    - int audit_log_tty_passwd;
    - unsigned long flags;
    unsigned int icanon = !!L_ICANON(tty);
    + unsigned int audit_tty;
    dev_t dev;

    if (unlikely(size == 0))
    @@ -271,10 +262,10 @@ void tty_audit_add_data(struct tty_struct *tty, const void *data, size_t size)
    && tty->driver->subtype == PTY_TYPE_MASTER)
    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))
    + audit_tty = READ_ONCE(current->signal->audit_tty);
    + if (~audit_tty & AUDIT_TTY_ENABLE)
    + return;
    + if ((~audit_tty & AUDIT_TTY_LOG_PASSWD) && icanon && !L_ECHO(tty))
    return;

    buf = tty_audit_buf_get();
    diff --git a/include/linux/audit.h b/include/linux/audit.h
    index 20eba1e..9ed7254 100644
    --- a/include/linux/audit.h
    +++ b/include/linux/audit.h
    @@ -109,6 +109,10 @@ extern int audit_classify_compat_syscall(int abi, unsigned syscall);
    /* maximized args number that audit_socketcall can process */
    #define AUDITSC_ARGS 6

    +/* bit values for ->signal->audit_tty */
    +#define AUDIT_TTY_ENABLE BIT(0)
    +#define AUDIT_TTY_LOG_PASSWD BIT(1)
    +
    struct filename;

    extern void audit_log_session_info(struct audit_buffer *ab);
    diff --git a/include/linux/sched.h b/include/linux/sched.h
    index edad7a4..400a738 100644
    --- a/include/linux/sched.h
    +++ b/include/linux/sched.h
    @@ -771,7 +771,6 @@ struct signal_struct {
    #endif
    #ifdef CONFIG_AUDIT
    unsigned audit_tty;
    - unsigned audit_tty_log_passwd;
    struct tty_audit_buf *tty_audit_buf;
    #endif

    diff --git a/kernel/audit.c b/kernel/audit.c
    index 270dfb9..dfaa8e7 100644
    --- a/kernel/audit.c
    +++ b/kernel/audit.c
    @@ -1031,20 +1031,19 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
    break;
    case AUDIT_TTY_GET: {
    struct audit_tty_status s;
    - struct task_struct *tsk = current;
    + unsigned int t;

    - spin_lock(&tsk->sighand->siglock);
    - s.enabled = tsk->signal->audit_tty;
    - s.log_passwd = tsk->signal->audit_tty_log_passwd;
    - spin_unlock(&tsk->sighand->siglock);
    + t = READ_ONCE(current->signal->audit_tty);
    + s.enabled = t & AUDIT_TTY_ENABLE;
    + s.log_passwd = !!(t & AUDIT_TTY_LOG_PASSWD);

    audit_send_reply(skb, seq, AUDIT_TTY_GET, 0, 0, &s, sizeof(s));
    break;
    }
    case AUDIT_TTY_SET: {
    struct audit_tty_status s, old;
    - struct task_struct *tsk = current;
    struct audit_buffer *ab;
    + unsigned int t;

    memset(&s, 0, sizeof(s));
    /* guard against past and future API changes */
    @@ -1054,14 +1053,14 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
    (s.log_passwd != 0 && s.log_passwd != 1))
    err = -EINVAL;

    - spin_lock(&tsk->sighand->siglock);
    - old.enabled = tsk->signal->audit_tty;
    - old.log_passwd = tsk->signal->audit_tty_log_passwd;
    - if (!err) {
    - tsk->signal->audit_tty = s.enabled;
    - tsk->signal->audit_tty_log_passwd = s.log_passwd;
    + if (err)
    + t = READ_ONCE(current->signal->audit_tty);
    + else {
    + t = s.enabled | (-s.log_passwd & AUDIT_TTY_LOG_PASSWD);
    + t = xchg(&current->signal->audit_tty, t);
    }
    - spin_unlock(&tsk->sighand->siglock);
    + old.enabled = t & AUDIT_TTY_ENABLE;
    + old.log_passwd = !!(t & AUDIT_TTY_LOG_PASSWD);

    audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE);
    audit_log_format(ab, " op=tty_set old-enabled=%d new-enabled=%d"
    --
    2.7.0
    \
     
     \ /
      Last update: 2016-01-10 08:41    [W:4.233 / U:0.260 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site