[PATCH] Workaround possible pty line discipline race
Linux Kernel Mailing List <[email protected]> Sat, 12 Mar 2005 12:50:55 +0000
| Newsgroups | gmane.linux.kernel.commits.2-4 |
|---|---|
| Message-ID | <[email protected]> |
ChangeSet 1.1576, 2005/03/12 09:50:55-03:00, [email protected] [PATCH] Workaround possible pty line discipline race It's in no way "correct", in that the race hasn't actually gone away by this patch, but the patch makes it unimportant. We may end up calling a stale line discipline, which is still very wrong, but it so happens that we don't much care in practice. I think that in a 2.4.x tree there are some theoretical SMP races with module unloading etc (which the 2.6.x code doesn't have because module unload stops the other CPU's - maybe that part got backported to 2.4.x?), but quite frankly, I suspect that even in 2.4.x they are entirely theoretical and impossible to actually hit. And again, in theory some line discipline might do something strange in it's "chars_in_buffer" routine that would be problematic. In practice that's just not the case: the "chars_in_buffer()" routine might return a bogus _value_ for a stale line discipline thing, but none of them seem to follow any pointers that might have become invalid (and in fact, most ldiscs don't even have that function). So while this patch is wrong in theory, it does have the advantage of being (a) very safe minimal patch and (b) fixing the problem in practice with no performance downside. I still feel a bit guilty about it, though. pty.c | 6 ++++-- 1 files changed, 4 insertions(+), 2 deletions(-) diff -Nru a/drivers/char/pty.c b/drivers/char/pty.c --- a/drivers/char/pty.c 2005-03-12 10:03:18 -08:00 +++ b/drivers/char/pty.c 2005-03-12 10:03:18 -08:00 @@ -218,13 +218,15 @@ static int pty_chars_in_buffer(struct tty_struct *tty) { struct tty_struct *to = tty->link; + ssize_t (*chars_in_buffer)(struct tty_struct *); int count; - if (!to || !to->ldisc.chars_in_buffer) + /* We should get the line discipline lock for "tty->link" */ + if (!to || !(chars_in_buffer = to->ldisc.chars_in_buffer)) return 0; /* The ldisc must report 0 if no characters available to be read */ - count = to->ldisc.chars_in_buffer(to); + count = chars_in_buffer(to); if (tty->driver.subtype == PTY_TYPE_SLAVE) return count;