linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* NULL dereference in tty_open()
@ 2011-10-04 20:05 Dan Carpenter
  2011-10-05 14:22 ` NULL dereference in tty_open() [and other bugs there] Jiri Slaby
  0 siblings, 1 reply; 11+ messages in thread
From: Dan Carpenter @ 2011-10-04 20:05 UTC (permalink / raw)
  To: linux-kernel

There is a NULL dereference here.  It was artificially triggered so
not a huge priority.

drivers/tty/tty_io.c
  1893          retval = tty_add_file(tty, filp);
  1894          if (retval) {
  1895                  tty_unlock();
  1896                  tty_release(inode, filp);
  1897                  return retval;
  1898          }

tty_add_file() is supposed to setup filp->private_data but the
allocation fails.  In tty_release() we call file_tty(filp),
__tty_fasync() and tty_del_file() which dereference
filp->private_data and Oops.

I looked at ptmx_open() to see how the error handling was done there.
That function only calls tty_release() if tty_add_file() succeeds,
so maybe we could just call devpts_kill_index() here and remove the
tty_release()?  I don't know the code well enough to say.

regards,
dan carpenter

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: NULL dereference in tty_open() [and other bugs there]
  2011-10-04 20:05 NULL dereference in tty_open() Dan Carpenter
@ 2011-10-05 14:22 ` Jiri Slaby
  2011-10-12  9:32   ` [PATCH 1/4] TTY: drop driver reference in tty_open fail path Jiri Slaby
  0 siblings, 1 reply; 11+ messages in thread
From: Jiri Slaby @ 2011-10-05 14:22 UTC (permalink / raw)
  To: Dan Carpenter; +Cc: linux-kernel, Alan Cox, Greg KH

On 10/04/2011 10:05 PM, Dan Carpenter wrote:
> There is a NULL dereference here.  It was artificially triggered so
> not a huge priority.
> 
> drivers/tty/tty_io.c
>   1893          retval = tty_add_file(tty, filp);
>   1894          if (retval) {
>   1895                  tty_unlock();
>   1896                  tty_release(inode, filp);
>   1897                  return retval;
>   1898          }
> 
> tty_add_file() is supposed to setup filp->private_data but the
> allocation fails.  In tty_release() we call file_tty(filp),
> __tty_fasync() and tty_del_file() which dereference
> filp->private_data and Oops.

Thanks, that's very true. It was added by:
commit 0259894c732837c801565d038eaecdcf8fc5bbe7
Author: Jiri Slaby <jslaby@suse.cz>
Date:   Wed Mar 23 10:48:37 2011 +0100

    TTY: fix fail path in tty_open
=====

So instead of leaks, we now crash, hmm.

> I looked at ptmx_open() to see how the error handling was done there.
> That function only calls tty_release() if tty_add_file() succeeds,
> so maybe we could just call devpts_kill_index() here and remove the
> tty_release()?  I don't know the code well enough to say.

No, that won't work. We need to revert all the changes done in
tty_reopen/tty_init_dev. Yes, ptmx_open looks broken to me too because
the tty is not properly freed.

What is worse, the tty_open code seems to be broken more than that.
* when tty_driver_lookup_tty fails in tty_open, we don't drop a
  reference to the tty driver.
* tty lookup looks broken for the current console. Look:

As of:
commit 4a2b5fddd53b80efcb3266ee36e23b8de28e761a
Author: Sukadev Bhattiprolu <sukadev@us.ibm.com>
Date:   Mon Oct 13 10:42:49 2008 +0100

    Move tty lookup/reopen to caller
=====

The code looks like:
struct tty_struct *tty = NULL;
...
if (device == MKDEV(TTYAUX_MAJOR, 0)) {
  tty = get_current_tty(); // ==== tty is not NULL
...
  tty_kref_put(tty); // ==== tty is dropped
  goto got_driver;
}
... // ============== POINT 1 (see below)
if (tty) {
  retval = tty_reopen(tty);
  ...
}
=====

Previously we called tty_driver_lookup_tty unconditionally at POINT 1.
Now we pass a tty structure to tty_reopen for which we dropped a
reference count. I don't think this was intentional, right?


Back to the point of your email. I have a patch which splits
tty_add_file into:
* tty_alloc_file intented to be called earlier in the open functions, so
we don't need to rollback
* tty_add_file which doesn't fail. It sets up the structure and adds it
to the list.

Otherwise we would need to split tty_release into smaller functions
somehow. We would need at least decreasing refcounts, checking tty count
for zero and freeing tty.

I will submit the simpler way above (tty_add_file split) along with
fixes for the other 3 bugs (ptmx_open, tty driver refcount, tty_reopen
of an unreferenced tty) after I test them all a bit.

thanks,
-- 
js
suse labs

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 1/4] TTY: drop driver reference in tty_open fail path
  2011-10-05 14:22 ` NULL dereference in tty_open() [and other bugs there] Jiri Slaby
@ 2011-10-12  9:32   ` Jiri Slaby
  2011-10-12  9:32     ` [PATCH 2/4] TTY: make tty_add_file non-failing Jiri Slaby
                       ` (3 more replies)
  0 siblings, 4 replies; 11+ messages in thread
From: Jiri Slaby @ 2011-10-12  9:32 UTC (permalink / raw)
  To: gregkh; +Cc: linux-kernel, jirislaby, stable, Sukadev Bhattiprolu, Alan Cox

When tty_driver_lookup_tty fails in tty_open, we forget to drop a
reference to the tty driver. This was added by commit 4a2b5fddd5 (Move
tty lookup/reopen to caller).

Fix that by adding tty_driver_kref_put to the fail path.

I will refactor the code later. This is for the ease of backporting to
stable.

Introduced-in: v2.6.28-rc2
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Cc: stable@kernel.org
Cc: Sukadev Bhattiprolu <sukadev@us.ibm.com>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Cc: Greg Kroah-Hartman <gregkh@suse.de>
---
 drivers/tty/tty_io.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index 4f1fc81..54b3cc4 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -1872,6 +1872,7 @@ got_driver:
 		if (IS_ERR(tty)) {
 			tty_unlock();
 			mutex_unlock(&tty_mutex);
+			tty_driver_kref_put(driver);
 			return PTR_ERR(tty);
 		}
 	}
-- 
1.7.7



^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 2/4] TTY: make tty_add_file non-failing
  2011-10-12  9:32   ` [PATCH 1/4] TTY: drop driver reference in tty_open fail path Jiri Slaby
@ 2011-10-12  9:32     ` Jiri Slaby
  2011-10-12  9:32     ` [PATCH 3/4] TTY: pty, release tty in all ptmx_open fail paths Jiri Slaby
                       ` (2 subsequent siblings)
  3 siblings, 0 replies; 11+ messages in thread
From: Jiri Slaby @ 2011-10-12  9:32 UTC (permalink / raw)
  To: gregkh; +Cc: linux-kernel, jirislaby, stable, Alan Cox, Pekka Enberg

If tty_add_file fails at the point it is now, we have to revert all
the changes we did to the tty. It means either decrease all refcounts
if this was a tty reopen or delete the tty if it was newly allocated.

There was a try to fix this in v3.0-rc2 using tty_release in 0259894c7
(TTY: fix fail path in tty_open). But instead it introduced a NULL
dereference. It's because tty_release dereferences
filp->private_data, but that one is set even in our tty_add_file. And
when tty_add_file fails, it's still NULL/garbage. Hence tty_release
cannot be called there.

To circumvent the original leak (and the current NULL deref) we split
tty_add_file into two functions, making the latter non-failing. In
that case we may do the former early in open, where handling failures
is easy. The latter stays as it is now. So there is no change in
functionality.

The original bug (leak) was introduced by f573bd176 (tty: Remove
__GFP_NOFAIL from tty_add_file()). Thanks Dan for reporting this.

Later, we may split tty_release into more functions and call only some
of them in this fail path instead. (If at all possible.)

Introduced-in: v2.6.37-rc2
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
Cc: stable@kernel.org
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Cc: Greg KH <gregkh@suse.de>
Cc: Pekka Enberg <penberg@kernel.org>
---
 drivers/tty/pty.c    |   16 +++++++++++-----
 drivers/tty/tty_io.c |   47 +++++++++++++++++++++++++++++++++++------------
 include/linux/tty.h  |    4 +++-
 3 files changed, 49 insertions(+), 18 deletions(-)

diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c
index e809e9d..696e851 100644
--- a/drivers/tty/pty.c
+++ b/drivers/tty/pty.c
@@ -670,12 +670,18 @@ static int ptmx_open(struct inode *inode, struct file *filp)
 
 	nonseekable_open(inode, filp);
 
+	retval = tty_alloc_file(filp);
+	if (retval)
+		return retval;
+
 	/* find a device that is not in use. */
 	tty_lock();
 	index = devpts_new_index(inode);
 	tty_unlock();
-	if (index < 0)
-		return index;
+	if (index < 0) {
+		retval = index;
+		goto err_file;
+	}
 
 	mutex_lock(&tty_mutex);
 	tty_lock();
@@ -689,9 +695,7 @@ static int ptmx_open(struct inode *inode, struct file *filp)
 
 	set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
 
-	retval = tty_add_file(tty, filp);
-	if (retval)
-		goto out;
+	tty_add_file(tty, filp);
 
 	retval = devpts_pty_new(inode, tty->link);
 	if (retval)
@@ -710,6 +714,8 @@ out2:
 out:
 	devpts_kill_index(inode, index);
 	tty_unlock();
+err_file:
+	tty_free_file(filp);
 	return retval;
 }
 
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index 54b3cc4..1a890e2 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -194,8 +194,7 @@ static inline struct tty_struct *file_tty(struct file *file)
 	return ((struct tty_file_private *)file->private_data)->tty;
 }
 
-/* Associate a new file with the tty structure */
-int tty_add_file(struct tty_struct *tty, struct file *file)
+int tty_alloc_file(struct file *file)
 {
 	struct tty_file_private *priv;
 
@@ -203,15 +202,36 @@ int tty_add_file(struct tty_struct *tty, struct file *file)
 	if (!priv)
 		return -ENOMEM;
 
+	file->private_data = priv;
+
+	return 0;
+}
+
+/* Associate a new file with the tty structure */
+void tty_add_file(struct tty_struct *tty, struct file *file)
+{
+	struct tty_file_private *priv = file->private_data;
+
 	priv->tty = tty;
 	priv->file = file;
-	file->private_data = priv;
 
 	spin_lock(&tty_files_lock);
 	list_add(&priv->list, &tty->tty_files);
 	spin_unlock(&tty_files_lock);
+}
 
-	return 0;
+/**
+ * tty_free_file - free file->private_data
+ *
+ * This shall be used only for fail path handling when tty_add_file was not
+ * called yet.
+ */
+void tty_free_file(struct file *file)
+{
+	struct tty_file_private *priv = file->private_data;
+
+	file->private_data = NULL;
+	kfree(priv);
 }
 
 /* Delete file from its tty */
@@ -222,8 +242,7 @@ void tty_del_file(struct file *file)
 	spin_lock(&tty_files_lock);
 	list_del(&priv->list);
 	spin_unlock(&tty_files_lock);
-	file->private_data = NULL;
-	kfree(priv);
+	tty_free_file(file);
 }
 
 
@@ -1811,6 +1830,10 @@ static int tty_open(struct inode *inode, struct file *filp)
 	nonseekable_open(inode, filp);
 
 retry_open:
+	retval = tty_alloc_file(filp);
+	if (retval)
+		return -ENOMEM;
+
 	noctty = filp->f_flags & O_NOCTTY;
 	index  = -1;
 	retval = 0;
@@ -1823,6 +1846,7 @@ retry_open:
 		if (!tty) {
 			tty_unlock();
 			mutex_unlock(&tty_mutex);
+			tty_free_file(filp);
 			return -ENXIO;
 		}
 		driver = tty_driver_kref_get(tty->driver);
@@ -1855,6 +1879,7 @@ retry_open:
 		}
 		tty_unlock();
 		mutex_unlock(&tty_mutex);
+		tty_free_file(filp);
 		return -ENODEV;
 	}
 
@@ -1862,6 +1887,7 @@ retry_open:
 	if (!driver) {
 		tty_unlock();
 		mutex_unlock(&tty_mutex);
+		tty_free_file(filp);
 		return -ENODEV;
 	}
 got_driver:
@@ -1873,6 +1899,7 @@ got_driver:
 			tty_unlock();
 			mutex_unlock(&tty_mutex);
 			tty_driver_kref_put(driver);
+			tty_free_file(filp);
 			return PTR_ERR(tty);
 		}
 	}
@@ -1888,15 +1915,11 @@ got_driver:
 	tty_driver_kref_put(driver);
 	if (IS_ERR(tty)) {
 		tty_unlock();
+		tty_free_file(filp);
 		return PTR_ERR(tty);
 	}
 
-	retval = tty_add_file(tty, filp);
-	if (retval) {
-		tty_unlock();
-		tty_release(inode, filp);
-		return retval;
-	}
+	tty_add_file(tty, filp);
 
 	check_tty_count(tty, "tty_open");
 	if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 6af44ab..ac275c2 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -479,7 +479,9 @@ extern void proc_clear_tty(struct task_struct *p);
 extern struct tty_struct *get_current_tty(void);
 extern void tty_default_fops(struct file_operations *fops);
 extern struct tty_struct *alloc_tty_struct(void);
-extern int tty_add_file(struct tty_struct *tty, struct file *file);
+extern int tty_alloc_file(struct file *file);
+extern void tty_add_file(struct tty_struct *tty, struct file *file);
+extern void tty_free_file(struct file *file);
 extern void free_tty_struct(struct tty_struct *tty);
 extern void initialize_tty_struct(struct tty_struct *tty,
 		struct tty_driver *driver, int idx);
-- 
1.7.7



^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 3/4] TTY: pty, release tty in all ptmx_open fail paths
  2011-10-12  9:32   ` [PATCH 1/4] TTY: drop driver reference in tty_open fail path Jiri Slaby
  2011-10-12  9:32     ` [PATCH 2/4] TTY: make tty_add_file non-failing Jiri Slaby
@ 2011-10-12  9:32     ` Jiri Slaby
  2011-10-12 13:23       ` Arnd Bergmann
  2011-10-12  9:32     ` [PATCH 4/4] TTY: call tty_driver_lookup_tty unconditionally Jiri Slaby
  2011-10-16 18:28     ` [PATCH 1/4] TTY: drop driver reference in tty_open fail path Sukadev Bhattiprolu
  3 siblings, 1 reply; 11+ messages in thread
From: Jiri Slaby @ 2011-10-12  9:32 UTC (permalink / raw)
  To: gregkh; +Cc: linux-kernel, jirislaby, stable, Arnd Bergmann, Alan Cox

Mistakenly, commit 64ba3dc3143d (tty: never hold BTM while getting
tty_mutex) switched one fail path in ptmx_open to not free the newly
allocated tty.

Fix that by jumping to the appropriate place. And rename the labels so
that it's clear what is going on there.

Introduced-in: v2.6.36-rc2
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Cc: stable@kernel.org
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Cc: Greg Kroah-Hartman <gregkh@suse.de>
---
 drivers/tty/pty.c |   10 +++++-----
 1 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c
index 696e851..e18604b 100644
--- a/drivers/tty/pty.c
+++ b/drivers/tty/pty.c
@@ -699,15 +699,15 @@ static int ptmx_open(struct inode *inode, struct file *filp)
 
 	retval = devpts_pty_new(inode, tty->link);
 	if (retval)
-		goto out1;
+		goto err_release;
 
 	retval = ptm_driver->ops->open(tty, filp);
 	if (retval)
-		goto out2;
-out1:
+		goto err_release;
+
 	tty_unlock();
-	return retval;
-out2:
+	return 0;
+err_release:
 	tty_unlock();
 	tty_release(inode, filp);
 	return retval;
-- 
1.7.7



^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 4/4] TTY: call tty_driver_lookup_tty unconditionally
  2011-10-12  9:32   ` [PATCH 1/4] TTY: drop driver reference in tty_open fail path Jiri Slaby
  2011-10-12  9:32     ` [PATCH 2/4] TTY: make tty_add_file non-failing Jiri Slaby
  2011-10-12  9:32     ` [PATCH 3/4] TTY: pty, release tty in all ptmx_open fail paths Jiri Slaby
@ 2011-10-12  9:32     ` Jiri Slaby
  2011-10-12 20:59       ` Jiri Slaby
  2011-10-16 18:28     ` [PATCH 1/4] TTY: drop driver reference in tty_open fail path Sukadev Bhattiprolu
  3 siblings, 1 reply; 11+ messages in thread
From: Jiri Slaby @ 2011-10-12  9:32 UTC (permalink / raw)
  To: gregkh; +Cc: linux-kernel, jirislaby, Sukadev Bhattiprolu, Alan Cox

Commit 4a2b5fddd5 (Move tty lookup/reopen to caller) made the call to
tty_driver_lookup_tty conditional in tty_open. It doesn't look like it
was an intention. Or if it was, it was not documented in the changelog
and the code now looks weird. For example there would be no need to
remember the tty driver and tty index. Further the condition depends
on a tty which we drop a reference of already.

If I'm looking correctly, this should not matter thanks to the locking
currently done there. Thus, tty_driver->ttys[idx] cannot change under
our hands. But anyway, it makes sense to change that to the old
behaviour.

Introduced-in: v2.6.28-rc2
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Cc: Sukadev Bhattiprolu <sukadev@us.ibm.com>
Cc: Alan Cox <alan@redhat.com>
Cc: Greg Kroah-Hartman <gregkh@suse.de>
---
 drivers/tty/tty_io.c |   21 +++++++++------------
 1 files changed, 9 insertions(+), 12 deletions(-)

diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index 1a890e2..3283d0a 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -1820,7 +1820,7 @@ int tty_release(struct inode *inode, struct file *filp)
 
 static int tty_open(struct inode *inode, struct file *filp)
 {
-	struct tty_struct *tty = NULL;
+	struct tty_struct *tty;
 	int noctty, retval;
 	struct tty_driver *driver;
 	int index;
@@ -1891,17 +1891,14 @@ retry_open:
 		return -ENODEV;
 	}
 got_driver:
-	if (!tty) {
-		/* check whether we're reopening an existing tty */
-		tty = tty_driver_lookup_tty(driver, inode, index);
-
-		if (IS_ERR(tty)) {
-			tty_unlock();
-			mutex_unlock(&tty_mutex);
-			tty_driver_kref_put(driver);
-			tty_free_file(filp);
-			return PTR_ERR(tty);
-		}
+	/* check whether we're reopening an existing tty */
+	tty = tty_driver_lookup_tty(driver, inode, index);
+	if (IS_ERR(tty)) {
+		tty_unlock();
+		mutex_unlock(&tty_mutex);
+		tty_driver_kref_put(driver);
+		tty_free_file(filp);
+		return PTR_ERR(tty);
 	}
 
 	if (tty) {
-- 
1.7.7



^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH 3/4] TTY: pty, release tty in all ptmx_open fail paths
  2011-10-12  9:32     ` [PATCH 3/4] TTY: pty, release tty in all ptmx_open fail paths Jiri Slaby
@ 2011-10-12 13:23       ` Arnd Bergmann
  0 siblings, 0 replies; 11+ messages in thread
From: Arnd Bergmann @ 2011-10-12 13:23 UTC (permalink / raw)
  To: Jiri Slaby; +Cc: gregkh, linux-kernel, jirislaby, stable, Alan Cox

On Wednesday 12 October 2011, Jiri Slaby wrote:
> Mistakenly, commit 64ba3dc3143d (tty: never hold BTM while getting
> tty_mutex) switched one fail path in ptmx_open to not free the newly
> allocated tty.
> 
> Fix that by jumping to the appropriate place. And rename the labels so
> that it's clear what is going on there.
> 
> Introduced-in: v2.6.36-rc2
> Signed-off-by: Jiri Slaby <jslaby@suse.cz>
> Cc: stable@kernel.org
> Cc: Arnd Bergmann <arnd@arndb.de>
> Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
> Cc: Greg Kroah-Hartman <gregkh@suse.de>

Ok, I have checked that this patch returns the code into the state
before my broken patch, that looks good.

I think I made the same mistake trying to understand your patch
that I made originally when I introduced the bug, which was to
confuse the lifetime of the pty master with the lifetime of the
slave device, so I thought that tty_release should not be called
if we never called ptm_driver->ops->open(), but that's actually
a different device.

	Arnd

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 4/4] TTY: call tty_driver_lookup_tty unconditionally
  2011-10-12  9:32     ` [PATCH 4/4] TTY: call tty_driver_lookup_tty unconditionally Jiri Slaby
@ 2011-10-12 20:59       ` Jiri Slaby
  2011-10-16 19:20         ` Sukadev Bhattiprolu
  0 siblings, 1 reply; 11+ messages in thread
From: Jiri Slaby @ 2011-10-12 20:59 UTC (permalink / raw)
  To: Jiri Slaby; +Cc: gregkh, linux-kernel, Sukadev Bhattiprolu, Alan Cox

On 10/12/2011 11:32 AM, Jiri Slaby wrote:
> Commit 4a2b5fddd5 (Move tty lookup/reopen to caller) made the call to
> tty_driver_lookup_tty conditional in tty_open. It doesn't look like it
> was an intention. Or if it was, it was not documented in the changelog
> and the code now looks weird. For example there would be no need to
> remember the tty driver and tty index. Further the condition depends
> on a tty which we drop a reference of already.
> 
> If I'm looking correctly, this should not matter thanks to the locking
> currently done there. Thus, tty_driver->ttys[idx] cannot change under
> our hands. But anyway, it makes sense to change that to the old
> behaviour.

Well, this doesn't work for ptys. devpts lookup code expects an inode to
be one of devpts filesystem (/dev/pts/*), not something on tmpfs like
/dev/tty. So it looks like the change was intentional, but very
undocumented and leaving there some unused code.

Now, I don't know what to do with the tty being around with a dropped
reference. Maybe nothing in the presence of the BTM which I *think*
prevents tty to go now.

Also I have just found that having ptm_unix98_lookup is pointless. For
master, we have ptmx_open which doesn't call lookup. And if it did, it
would trigger BUG_ON in devpts_get_tty called from ptm_unix98_lookup.

thanks,
-- 
js

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 1/4] TTY: drop driver reference in tty_open fail path
  2011-10-12  9:32   ` [PATCH 1/4] TTY: drop driver reference in tty_open fail path Jiri Slaby
                       ` (2 preceding siblings ...)
  2011-10-12  9:32     ` [PATCH 4/4] TTY: call tty_driver_lookup_tty unconditionally Jiri Slaby
@ 2011-10-16 18:28     ` Sukadev Bhattiprolu
  3 siblings, 0 replies; 11+ messages in thread
From: Sukadev Bhattiprolu @ 2011-10-16 18:28 UTC (permalink / raw)
  To: Jiri Slaby
  Cc: gregkh, linux-kernel, jirislaby, stable, Sukadev Bhattiprolu,
	Alan Cox

Jiri Slaby [jslaby@suse.cz] wrote:
| When tty_driver_lookup_tty fails in tty_open, we forget to drop a
| reference to the tty driver. This was added by commit 4a2b5fddd5 (Move
| tty lookup/reopen to caller).
| 
| Fix that by adding tty_driver_kref_put to the fail path.

Arg. Sorry about that. Thanks for spotting/fixing it.

| 
| I will refactor the code later. This is for the ease of backporting to
| stable.
| 
| Introduced-in: v2.6.28-rc2
| Signed-off-by: Jiri Slaby <jslaby@suse.cz>
| Cc: stable@kernel.org
| Cc: Sukadev Bhattiprolu <sukadev@us.ibm.com>
| Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
| Cc: Greg Kroah-Hartman <gregkh@suse.de>

Acked-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 4/4] TTY: call tty_driver_lookup_tty unconditionally
  2011-10-12 20:59       ` Jiri Slaby
@ 2011-10-16 19:20         ` Sukadev Bhattiprolu
  2011-10-16 19:37           ` Jiri Slaby
  0 siblings, 1 reply; 11+ messages in thread
From: Sukadev Bhattiprolu @ 2011-10-16 19:20 UTC (permalink / raw)
  To: Jiri Slaby
  Cc: Jiri Slaby, gregkh, linux-kernel, Sukadev Bhattiprolu, Alan Cox,
	hpa

Ccing H.Peter Anvin.

Jiri Slaby [jirislaby@gmail.com] wrote:
| On 10/12/2011 11:32 AM, Jiri Slaby wrote:
| > Commit 4a2b5fddd5 (Move tty lookup/reopen to caller) made the call to
| > tty_driver_lookup_tty conditional in tty_open. It doesn't look like it
| > was an intention. Or if it was, it was not documented in the changelog
| > and the code now looks weird. For example there would be no need to
| > remember the tty driver and tty index. Further the condition depends
| > on a tty which we drop a reference of already.
| > 
| > If I'm looking correctly, this should not matter thanks to the locking
| > currently done there. Thus, tty_driver->ttys[idx] cannot change under
| > our hands. But anyway, it makes sense to change that to the old
| > behaviour.
| 
| Well, this doesn't work for ptys. devpts lookup code expects an inode to
| be one of devpts filesystem (/dev/pts/*), not something on tmpfs like
| /dev/tty. So it looks like the change was intentional, but very
| undocumented and leaving there some unused code.

Yes this was intentional - even though the tty_driver_lookup() was
unconditional in tty_init_dev() I believe it did not do anything useful
when called from ptmx_open(). ptmx_open() would be setting up a new pty and
the lookup would not find a tty.

Would the following change to tty_open() help ?

got_driver:
+	/* check if we are opening a new pty or reopening an existing tty */
        if (!tty) {
-	/* check whether we're reopening an existing tty */
                tty = tty_driver_lookup_tty(driver, inode, index);

I am not sure about the unused code you refer to above. Can you please
clarify ?

Sukadev


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 4/4] TTY: call tty_driver_lookup_tty unconditionally
  2011-10-16 19:20         ` Sukadev Bhattiprolu
@ 2011-10-16 19:37           ` Jiri Slaby
  0 siblings, 0 replies; 11+ messages in thread
From: Jiri Slaby @ 2011-10-16 19:37 UTC (permalink / raw)
  To: Sukadev Bhattiprolu
  Cc: Jiri Slaby, gregkh, linux-kernel, Sukadev Bhattiprolu, Alan Cox,
	hpa

Fixing Alan's address. Somehow I put there a RH (defunct) one.

On 10/16/2011 09:20 PM, Sukadev Bhattiprolu wrote:
> Jiri Slaby [jirislaby@gmail.com] wrote:
> | On 10/12/2011 11:32 AM, Jiri Slaby wrote:
> | > Commit 4a2b5fddd5 (Move tty lookup/reopen to caller) made the call to
> | > tty_driver_lookup_tty conditional in tty_open. It doesn't look like it
> | > was an intention. Or if it was, it was not documented in the changelog
> | > and the code now looks weird. For example there would be no need to
> | > remember the tty driver and tty index. Further the condition depends
> | > on a tty which we drop a reference of already.
> | > 
> | > If I'm looking correctly, this should not matter thanks to the locking
> | > currently done there. Thus, tty_driver->ttys[idx] cannot change under
> | > our hands. But anyway, it makes sense to change that to the old
> | > behaviour.
> | 
> | Well, this doesn't work for ptys. devpts lookup code expects an inode to
> | be one of devpts filesystem (/dev/pts/*), not something on tmpfs like
> | /dev/tty. So it looks like the change was intentional, but very
> | undocumented and leaving there some unused code.
> 
> Yes this was intentional - even though the tty_driver_lookup() was
> unconditional in tty_init_dev() I believe it did not do anything useful
> when called from ptmx_open(). ptmx_open() would be setting up a new pty and
> the lookup would not find a tty.

Yes, I'm not arguing against moving the code from tty_init_dev to
tty_open change. That is perfectly OK.

What I mind is that now we do:
=====
  tty = get_current_tty();
  if (!tty)
        return -ENXIO;
  driver = tty_driver_kref_get(tty->driver); /* ZZZ */
  index = tty->index;                        /* ZZZ */
...
  tty_kref_put(tty); /* XXX */
  goto got_driver;
...
got_driver:
  if (!tty) {   /* YYY */
  }
=====

But at the point of YYY, the tty may be invalid due to reference drop at
XXX. I *hope* it is not the case thanks to the current locking there
(namely BTM) but I'm really *not sure*. And if it is the case, there
should definitely be a note. (Or better the reference should be held
while necessary.)

> Would the following change to tty_open() help ?

No, it doesn't matter now. I would prefer a description of the change to
be a part of the commit log. And it missed such a notice.

> I am not sure about the unused code you refer to above. Can you please
> clarify ?

It is index and driver assigned in the branch above (see ZZZ). When we
have a live tty (which I'm not sure we have -- see above), it is
guaranteed that the driver is reff'ed. And we need neither driver nor
index when we have such a tty.

thanks,
-- 
js

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2011-10-16 19:37 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-10-04 20:05 NULL dereference in tty_open() Dan Carpenter
2011-10-05 14:22 ` NULL dereference in tty_open() [and other bugs there] Jiri Slaby
2011-10-12  9:32   ` [PATCH 1/4] TTY: drop driver reference in tty_open fail path Jiri Slaby
2011-10-12  9:32     ` [PATCH 2/4] TTY: make tty_add_file non-failing Jiri Slaby
2011-10-12  9:32     ` [PATCH 3/4] TTY: pty, release tty in all ptmx_open fail paths Jiri Slaby
2011-10-12 13:23       ` Arnd Bergmann
2011-10-12  9:32     ` [PATCH 4/4] TTY: call tty_driver_lookup_tty unconditionally Jiri Slaby
2011-10-12 20:59       ` Jiri Slaby
2011-10-16 19:20         ` Sukadev Bhattiprolu
2011-10-16 19:37           ` Jiri Slaby
2011-10-16 18:28     ` [PATCH 1/4] TTY: drop driver reference in tty_open fail path Sukadev Bhattiprolu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).