1 From 991f76f837bf22c5bb07261cfd86525a0a96650c Mon Sep 17 00:00:00 2001
2 From: Ming Lei <ming.lei@canonical.com>
3 Date: Wed, 20 Mar 2013 23:25:24 +0800
4 Subject: sysfs: fix race between readdir and lseek
6 From: Ming Lei <ming.lei@canonical.com>
8 commit 991f76f837bf22c5bb07261cfd86525a0a96650c upstream.
10 While readdir() is running, lseek() may set filp->f_pos as zero,
11 then may leave filp->private_data pointing to one sysfs_dirent
12 object without holding its reference counter, so the sysfs_dirent
13 object may be used after free in next readdir().
15 This patch holds inode->i_mutex to avoid the problem since
16 the lock is always held in readdir path.
18 Reported-by: Dave Jones <davej@redhat.com>
19 Tested-by: Sasha Levin <levinsasha928@gmail.com>
20 Signed-off-by: Ming Lei <ming.lei@canonical.com>
21 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
24 fs/sysfs/dir.c | 13 ++++++++++++-
25 1 file changed, 12 insertions(+), 1 deletion(-)
29 @@ -1040,10 +1040,21 @@ static int sysfs_readdir(struct file * f
33 +static loff_t sysfs_dir_llseek(struct file *file, loff_t offset, int whence)
35 + struct inode *inode = file->f_path.dentry->d_inode;
38 + mutex_lock(&inode->i_mutex);
39 + ret = generic_file_llseek(file, offset, whence);
40 + mutex_unlock(&inode->i_mutex);
45 const struct file_operations sysfs_dir_operations = {
46 .read = generic_read_dir,
47 .readdir = sysfs_readdir,
48 .release = sysfs_dir_release,
49 - .llseek = generic_file_llseek,
50 + .llseek = sysfs_dir_llseek,