]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/3.4.39/sysfs-fix-race-between-readdir-and-lseek.patch
5.0-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 3.4.39 / sysfs-fix-race-between-readdir-and-lseek.patch
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
5
6 From: Ming Lei <ming.lei@canonical.com>
7
8 commit 991f76f837bf22c5bb07261cfd86525a0a96650c upstream.
9
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().
14
15 This patch holds inode->i_mutex to avoid the problem since
16 the lock is always held in readdir path.
17
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>
22
23 ---
24 fs/sysfs/dir.c | 13 ++++++++++++-
25 1 file changed, 12 insertions(+), 1 deletion(-)
26
27 --- a/fs/sysfs/dir.c
28 +++ b/fs/sysfs/dir.c
29 @@ -1040,10 +1040,21 @@ static int sysfs_readdir(struct file * f
30 return 0;
31 }
32
33 +static loff_t sysfs_dir_llseek(struct file *file, loff_t offset, int whence)
34 +{
35 + struct inode *inode = file->f_path.dentry->d_inode;
36 + loff_t ret;
37 +
38 + mutex_lock(&inode->i_mutex);
39 + ret = generic_file_llseek(file, offset, whence);
40 + mutex_unlock(&inode->i_mutex);
41 +
42 + return ret;
43 +}
44
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,
51 };