devpts_get_tty() should validate inode
PATCH 1/1 devpts_get_tty() should validate inode
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 <[email protected]> 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 <fcntl.h>
#include <sched.h>
#include <stdlib.h>
#include <sys/mount.h>
#include <sys/signal.h>
#include <unistd.h>
#include <stdio.h>
#include <linux/fs.h>
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 */
}---
fs/devpts/inode.c +14 -2
@@ -517,11 +517,23 @@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)
A message that is not in the archive (sent off-list or not yet received): 20091118023541.GA14430-r/[email protected]
Quoted 14 lines · 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 todevpts_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 <sukadev-r/[email protected]> Date: Mon Oct 13 10:43:08 2008 +0100
Quoted 5 lines
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
Good debugging, I'll queue this up.
greg k-h
[email protected]
Appliedpatch devpts_get_tty-should-validate-inode.patch added to gregkh-2.6 tree
In reply to a message not in the archiveThis is a note to let you know that I've just added the patch titled
Subject: devpts_get_tty() should validate inode
to my gregkh-2.6 tree. Its filename is
devpts_get_tty-should-validate-inode.patch
This tree can be found at
http://www.kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/patches/
From [email protected] Thu Nov 19 15:40:33 2009
From: Sukadev Bhattiprolu <[email protected]>
Date: Tue, 17 Nov 2009 18:35:43 -0800
Subject: devpts_get_tty() should validate inode
To: [email protected]
Cc: Alan Cox <alan-qBU/[email protected]>, [email protected], [email protected], [email protected], Containers <containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org>
Message-ID: <20091118023541.GA14430-r/[email protected]>
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 <sukadev-r/[email protected]> 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 <fcntl.h>
#include <sched.h>
#include <stdlib.h>
#include <sys/mount.h>
#include <sys/signal.h>
#include <unistd.h>
#include <stdio.h>
#include <linux/fs.h>
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 */
}--- fs/devpts/inode.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-)
fs/devpts/inode.c +14 -2
@@ -517,11 +517,23 @@ int devpts_pty_new(struct inode *ptmx_instruct 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)
Quoted 14 lines · 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 todevpts_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 <[email protected]> Date: Mon Oct 13 10:43:08 2008 +0100
Quoted 5 lines
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
Good debugging, I'll queue this up.
greg k-h
Quoted 71 lines · 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 todevpts_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 <sukadev-r/[email protected]> Date: Mon Oct 13 10:43:08 2008 +0100To 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 <fcntl.h>
#include <sched.h>
#include <stdlib.h>
#include <sys/mount.h>
#include <sys/signal.h>
#include <unistd.h>
#include <stdio.h>#include <
linux/fs.h>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 */ }
Quoted 2 lines
Reported-by Grzegorz Nosek <[email protected]>Signed-off-by Sukadev Bhattiprolu <[email protected]>
fwiw,
Quoted 35 lines
---
Index:linux-2.6/fs/devpts/inode.c
===================================================================fs/devpts/inode.c +14
-2@@ -517,11 +517,23 @@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)_______________________________________________
Containers mailing list Containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org
https://lists.linux-foundation.org/mailman/listinfo/containers