aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/pty.c
diff options
context:
space:
mode:
authorNick Piggin <npiggin@kernel.dk>2010-08-17 14:37:36 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2010-08-18 08:35:47 -0400
commitd996b62a8df1d935b01319bf8defb95b5709f7b8 (patch)
treed81f8240da776336845a2063555d7bb4dce684bd /drivers/char/pty.c
parentee2ffa0dfdd2db19705f2ba1c6a4c0bfe8122dd8 (diff)
tty: fix fu_list abuse
tty: fix fu_list abuse tty code abuses fu_list, which causes a bug in remount,ro handling. If a tty device node is opened on a filesystem, then the last link to the inode removed, the filesystem will be allowed to be remounted readonly. This is because fs_may_remount_ro does not find the 0 link tty inode on the file sb list (because the tty code incorrectly removed it to use for its own purpose). This can result in a filesystem with errors after it is marked "clean". Taking idea from Christoph's initial patch, allocate a tty private struct at file->private_data and put our required list fields in there, linking file and tty. This makes tty nodes behave the same way as other device nodes and avoid meddling with the vfs, and avoids this bug. The error handling is not trivial in the tty code, so for this bugfix, I take the simple approach of using __GFP_NOFAIL and don't worry about memory errors. This is not a problem because our allocator doesn't fail small allocs as a rule anyway. So proper error handling is left as an exercise for tty hackers. [ Arguably filesystem's device inode would ideally be divorced from the driver's pseudo inode when it is opened, but in practice it's not clear whether that will ever be worth implementing. ] Cc: linux-kernel@vger.kernel.org Cc: Christoph Hellwig <hch@infradead.org> Cc: Alan Cox <alan@lxorguk.ukuu.org.uk> Cc: Greg Kroah-Hartman <gregkh@suse.de> Signed-off-by: Nick Piggin <npiggin@kernel.dk> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'drivers/char/pty.c')
-rw-r--r--drivers/char/pty.c6
1 files changed, 1 insertions, 5 deletions
diff --git a/drivers/char/pty.c b/drivers/char/pty.c
index 2c64faa8efa4..c350d01716bd 100644
--- a/drivers/char/pty.c
+++ b/drivers/char/pty.c
@@ -675,12 +675,8 @@ static int ptmx_open(struct inode *inode, struct file *filp)
675 } 675 }
676 676
677 set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */ 677 set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
678 filp->private_data = tty;
679 678
680 file_sb_list_del(filp); /* __dentry_open has put it on the sb list */ 679 tty_add_file(tty, filp);
681 spin_lock(&tty_files_lock);
682 list_add(&filp->f_u.fu_list, &tty->tty_files);
683 spin_unlock(&tty_files_lock);
684 680
685 retval = devpts_pty_new(inode, tty->link); 681 retval = devpts_pty_new(inode, tty->link);
686 if (retval) 682 if (retval)