[lkml]   [2009]   [Dec]   [16]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
Messages in this thread
Patch in this message
Subject[060/151] devpts_get_tty() should validate inode
2.6.32-stable review patch.  If anyone has any objections, please let us know.


From: Sukadev Bhattiprolu <>

commit edfacdd6f81119b9005615593f2cbd94b8c7e2d8 upstream.

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

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:


#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);

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);

kill(pid, SIGHUP);
return 0; /* exit before child opens /dev/console */

Reported-by: Grzegorz Nosek <>
Signed-off-by: Sukadev Bhattiprolu <>
Tested-by: Serge Hallyn <>
Signed-off-by: Greg Kroah-Hartman <>

fs/devpts/inode.c | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)

--- a/fs/devpts/inode.c
+++ b/fs/devpts/inode.c
@@ -517,11 +517,23 @@ int devpts_pty_new(struct inode *ptmx_in

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)

 \ /
  Last update: 2009-12-17 05:39    [W:0.379 / U:0.820 seconds]
©2003-2018 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site