diff options
author | Peter Hurley <peter@hurleysoftware.com> | 2016-01-09 22:55:36 -0800 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2016-01-27 16:41:04 -0800 |
commit | fbaa122718a1235f4f83baa3abaad21cfefdbc9d (patch) | |
tree | 4ded90498dab94dce2f1c2c6679558ff217343fb /drivers/tty/tty_audit.c | |
parent | 5493090fc2341d9f28bdd9e81445fe0a130bafc2 (diff) | |
download | lwn-fbaa122718a1235f4f83baa3abaad21cfefdbc9d.tar.gz lwn-fbaa122718a1235f4f83baa3abaad21cfefdbc9d.zip |
tty: audit: Simplify first-use allocation
The first-use tty audit buffer allocation is a potential race
amongst multiple attempts at 'first-use'; only one 'winner' is
acceptable.
The successful buffer assignment occurs if tty_audit_buf == NULL
(which will also be the return from cmpxchg()); otherwise, another
racer 'won' and this buffer allocation is freed.
Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty/tty_audit.c')
-rw-r--r-- | drivers/tty/tty_audit.c | 22 |
1 files changed, 7 insertions, 15 deletions
diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c index 71ba8baee14d..6e33e41ec74d 100644 --- a/drivers/tty/tty_audit.c +++ b/drivers/tty/tty_audit.c @@ -181,30 +181,22 @@ int tty_audit_push(void) */ static struct tty_audit_buf *tty_audit_buf_get(void) { - struct tty_audit_buf *buf, *buf2; - unsigned long flags; + struct tty_audit_buf *buf; buf = current->signal->tty_audit_buf; if (buf) return buf; - buf2 = tty_audit_buf_alloc(); - if (buf2 == NULL) { + buf = tty_audit_buf_alloc(); + if (buf == NULL) { audit_log_lost("out of memory in TTY auditing"); return NULL; } - spin_lock_irqsave(¤t->sighand->siglock, flags); - buf = current->signal->tty_audit_buf; - if (!buf) { - current->signal->tty_audit_buf = buf2; - buf = buf2; - buf2 = NULL; - } - spin_unlock_irqrestore(¤t->sighand->siglock, flags); - if (buf2) - tty_audit_buf_free(buf2); - return buf; + /* Race to use this buffer, free it if another wins */ + if (cmpxchg(¤t->signal->tty_audit_buf, NULL, buf) != NULL) + tty_audit_buf_free(buf); + return current->signal->tty_audit_buf; } /** |