Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 2091

kernel-2.6.18-238.el5.src.rpm

From: Vitaly Mayatskikh <vmayatsk@redhat.com>
Date: Thu, 23 Oct 2008 14:52:10 +0200
Subject: [misc] rtc: disable SIGIO notification on close
Message-id: m3fxmnzd6t.wl%vmayatsk@redhat.com
O-Subject: [RHEL-5.3 PATCH] bz465747 rtc: fix kernel panic on second use of SIGIO notification
Bugzilla: 465747
RH-Acked-by: Chuck Ebbert <cebbert@redhat.com>
RH-Acked-by: Jerome Marchand <jmarchan@redhat.com>
RH-Acked-by: Prarit Bhargava <prarit@redhat.com>
RH-Acked-by: Oleg Nesterov <oleg@redhat.com>

Bugzilla: 465747

https://bugzilla.redhat.com/show_bug.cgi?id=465747

Description:
============
Marcin Slusarz reported: When userspace uses SIGIO notification and forgets to
disable it before closing file descriptor, rtc->async_queue contains stale
pointer to struct file.  When user space enables again SIGIO notification in
different process, kernel dereferences this (poisoned) pointer and crashes.

So disable SIGIO notification on close.

Upstream status:
================
commit 2e4a75cdcb89ff53bb182dda3a6dcdc14befe007

Test status:
============
I wasn't able to panic kernel with qemu or reproducer (qemu-like work
with rtc), but looking at the fasync code there truly may occur bad
pointer dereference. So it's better to prevent possible crashes in
future.

diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c
index 61a5825..9a78ed7 100644
--- a/drivers/rtc/rtc-dev.c
+++ b/drivers/rtc/rtc-dev.c
@@ -350,6 +350,12 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file,
 	return err;
 }
 
+static int rtc_dev_fasync(int fd, struct file *file, int on)
+{
+	struct rtc_device *rtc = to_rtc_device(file->private_data);
+	return fasync_helper(fd, file, on, &rtc->async_queue);
+}
+
 static int rtc_dev_release(struct inode *inode, struct file *file)
 {
 	struct rtc_device *rtc = to_rtc_device(file->private_data);
@@ -360,16 +366,13 @@ static int rtc_dev_release(struct inode *inode, struct file *file)
 	if (rtc->ops->release)
 		rtc->ops->release(rtc->class_dev.dev);
 
+	if (file->f_flags & FASYNC)
+		rtc_dev_fasync(-1, file, 0);
+
 	mutex_unlock(&rtc->char_lock);
 	return 0;
 }
 
-static int rtc_dev_fasync(int fd, struct file *file, int on)
-{
-	struct rtc_device *rtc = to_rtc_device(file->private_data);
-	return fasync_helper(fd, file, on, &rtc->async_queue);
-}
-
 static struct file_operations rtc_dev_fops = {
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,