From: Peter Hurley <peter@hurleysoftware.com>
To: Dmitry Vyukov <dvyukov@google.com>, gregkh@linuxfoundation.org
Cc: jslaby@suse.com, linux-kernel@vger.kernel.org, jslaby@suse.cz,
andreyknvl@google.com, kcc@google.com, glider@google.com
Subject: Re: [PATCH] tty: fix data race in flush_to_ldisc
Date: Wed, 2 Sep 2015 20:50:57 -0400 [thread overview]
Message-ID: <55E79971.9010308@hurleysoftware.com> (raw)
In-Reply-To: <1441216422-47412-1-git-send-email-dvyukov@google.com>
On 09/02/2015 01:53 PM, Dmitry Vyukov wrote:
> The data race is found with KernelThreadSanitizer (on rev 21bdb584af8c):
>
> ThreadSanitizer: data-race in release_tty
> Write of size 8 by thread T325 (K2579):
> release_tty+0xf3/0x1c0 drivers/tty/tty_io.c:1688
> tty_release+0x698/0x7c0 drivers/tty/tty_io.c:1920
> __fput+0x15f/0x310 fs/file_table.c:207
> ____fput+0x1d/0x30 fs/file_table.c:243
> task_work_run+0x115/0x130 kernel/task_work.c:123
> do_notify_resume+0x73/0x80
> tracehook_notify_resume include/linux/tracehook.h:190
> do_notify_resume+0x73/0x80 arch/x86/kernel/signal.c:757
> int_signal+0x12/0x17 arch/x86/entry/entry_64.S:326
> Previous read of size 8 by thread T19 (K16):
> flush_to_ldisc+0x29/0x300 drivers/tty/tty_buffer.c:472
> process_one_work+0x47e/0x930 kernel/workqueue.c:2036
> worker_thread+0xb0/0x900 kernel/workqueue.c:2170
> kthread+0x150/0x170 kernel/kthread.c:207
The stack traces are not really helpful in describing how the race
occurs; I would leave it out of the changelog.
> flush_to_ldisc reads port->itty and checks that it is not NULL,
> concurrently release_tty sets port->itty to NULL. It is possible
> that flush_to_ldisc loads port->itty once, ensures that it is
> not NULL, but then reloads it again and uses. The second load
> can already return NULL, which will cause a crash.
>
> Use READ_ONCE/WRITE_ONCE to read/update port->itty.
See below.
> Signed-off-by: Dmitry Vyukov <dvyukov@google.com>
> ---
> drivers/tty/tty_buffer.c | 2 +-
> drivers/tty/tty_io.c | 2 +-
> 2 files changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c
> index 4cf263d..1f1031d 100644
> --- a/drivers/tty/tty_buffer.c
> +++ b/drivers/tty/tty_buffer.c
> @@ -469,7 +469,7 @@ static void flush_to_ldisc(struct work_struct *work)
> struct tty_struct *tty;
> struct tty_ldisc *disc;
>
> - tty = port->itty;
> + tty = READ_ONCE(port->itty);
This is fine.
> if (tty == NULL)
> return;
>
> diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
> index 57fc6ee..aad47df 100644
> --- a/drivers/tty/tty_io.c
> +++ b/drivers/tty/tty_io.c
> @@ -1685,7 +1685,7 @@ static void release_tty(struct tty_struct *tty, int idx)
> tty_driver_remove_tty(tty->driver, tty);
> tty->port->itty = NULL;
> if (tty->link)
> - tty->link->port->itty = NULL;
> + WRITE_ONCE(tty->link->port->itty, NULL);
This isn't doing anything useful.
1. The compiler can't push the store past the cancel_work_sync() (because the
compiler has no visibility into cancel_work_sync()), and,
2. There's no effect if the compiler hoists the store higher in the release_tty()
because the line discipline has already been closed and killed (so the
tty_ldisc_ref() in flush_to_ldisc() returns NULL anyway).
Regards,
Peter Hurley
> cancel_work_sync(&tty->port->buf.work);
>
> tty_kref_put(tty->link);
>
next prev parent reply other threads:[~2015-09-03 0:51 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-09-01 20:11 [PATCH] tty: fix data race in flush_to_ldisc Dmitry Vyukov
2015-09-02 14:18 ` Peter Hurley
2015-09-02 14:41 ` Dmitry Vyukov
2015-09-02 15:28 ` Peter Hurley
2015-09-02 17:53 ` Dmitry Vyukov
2015-09-03 0:50 ` Peter Hurley [this message]
2015-09-04 19:28 ` Dmitry Vyukov
2015-09-16 2:54 ` Peter Hurley
2015-09-17 11:42 ` Dmitry Vyukov
2015-09-02 17:55 ` Dmitry Vyukov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=55E79971.9010308@hurleysoftware.com \
--to=peter@hurleysoftware.com \
--cc=andreyknvl@google.com \
--cc=dvyukov@google.com \
--cc=glider@google.com \
--cc=gregkh@linuxfoundation.org \
--cc=jslaby@suse.com \
--cc=jslaby@suse.cz \
--cc=kcc@google.com \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.