Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S935088AbZLKXiB (ORCPT ); Fri, 11 Dec 2009 18:38:01 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S934827AbZLKXgr (ORCPT ); Fri, 11 Dec 2009 18:36:47 -0500 Received: from kroah.org ([198.145.64.141]:50447 "EHLO coco.kroah.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933860AbZLKX3H (ORCPT ); Fri, 11 Dec 2009 18:29:07 -0500 From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Sukadev Bhattiprolu , stable , Greg Kroah-Hartman Subject: [PATCH 24/58] devpts_get_tty() should validate inode Date: Fri, 11 Dec 2009 15:28:08 -0800 Message-Id: <1260574122-10676-24-git-send-email-gregkh@suse.de> X-Mailer: git-send-email 1.6.5.3 In-Reply-To: <20091211232805.GA10652@kroah.com> References: <20091211232805.GA10652@kroah.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 3118 Lines: 119 From: Sukadev Bhattiprolu devpts_get_tty() assumes that the inode passed in is associated with a valid pty. But if the only reference to the pty is via a bind-mount, the inode passed to devpts_get_tty() while valid, would refer to a pty that no longer exists. With a lot of debug effort, Grzegorz Nosek developed a small program (see below) to reproduce a crash on recent kernels. This crash is a regression introduced by the commit: commit 527b3e4773628b30d03323a2cb5fb0d84441990f Author: Sukadev Bhattiprolu Date: Mon Oct 13 10:43:08 2008 +0100 To fix, ensure that the dentry associated with the inode has not yet been deleted/unhashed by devpts_pty_kill(). See also: https://lists.linux-foundation.org/pipermail/containers/2009-July/019273.html tty-bug.c: #define _GNU_SOURCE #include #include #include #include #include #include #include #include void dummy(int sig) { } static int child(void *unused) { int fd; signal(SIGINT, dummy); signal(SIGHUP, dummy); pause(); /* cheesy synchronisation to wait for /dev/pts/0 to appear */ mount("/dev/pts/0", "/dev/console", NULL, MS_BIND, NULL); sleep(2); fd = open("/dev/console", O_RDWR); dup(0); dup(0); write(1, "Hello world!\n", sizeof("Hello world!\n")-1); return 0; } int main(void) { pid_t pid; char *stack; stack = malloc(16384); pid = clone(child, stack+16384, CLONE_NEWNS|SIGCHLD, NULL); open("/dev/ptmx", O_RDWR|O_NOCTTY|O_NONBLOCK); unlockpt(fd); grantpt(fd); sleep(2); kill(pid, SIGHUP); sleep(1); return 0; /* exit before child opens /dev/console */ } Reported-by: Grzegorz Nosek Signed-off-by: Sukadev Bhattiprolu Tested-by: Serge Hallyn Cc: stable Signed-off-by: Greg Kroah-Hartman --- fs/devpts/inode.c | 16 ++++++++++++++-- 1 files changed, 14 insertions(+), 2 deletions(-) diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c index d5f8c96..8882ecc 100644 --- a/fs/devpts/inode.c +++ b/fs/devpts/inode.c @@ -517,11 +517,23 @@ int devpts_pty_new(struct inode *ptmx_inode, struct tty_struct *tty) struct tty_struct *devpts_get_tty(struct inode *pts_inode, int number) { + struct dentry *dentry; + struct tty_struct *tty; + BUG_ON(pts_inode->i_rdev == MKDEV(TTYAUX_MAJOR, PTMX_MINOR)); + /* Ensure dentry has not been deleted by devpts_pty_kill() */ + dentry = d_find_alias(pts_inode); + if (!dentry) + return NULL; + + tty = NULL; if (pts_inode->i_sb->s_magic == DEVPTS_SUPER_MAGIC) - return (struct tty_struct *)pts_inode->i_private; - return NULL; + tty = (struct tty_struct *)pts_inode->i_private; + + dput(dentry); + + return tty; } void devpts_pty_kill(struct tty_struct *tty) -- 1.6.5.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/