]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/3.7.10/tmpfs-fix-use-after-free-of-mempolicy-object.patch
4.14-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 3.7.10 / tmpfs-fix-use-after-free-of-mempolicy-object.patch
1 From 5f00110f7273f9ff04ac69a5f85bb535a4fd0987 Mon Sep 17 00:00:00 2001
2 From: Greg Thelen <gthelen@google.com>
3 Date: Fri, 22 Feb 2013 16:36:01 -0800
4 Subject: tmpfs: fix use-after-free of mempolicy object
5
6 From: Greg Thelen <gthelen@google.com>
7
8 commit 5f00110f7273f9ff04ac69a5f85bb535a4fd0987 upstream.
9
10 The tmpfs remount logic preserves filesystem mempolicy if the mpol=M
11 option is not specified in the remount request. A new policy can be
12 specified if mpol=M is given.
13
14 Before this patch remounting an mpol bound tmpfs without specifying
15 mpol= mount option in the remount request would set the filesystem's
16 mempolicy object to a freed mempolicy object.
17
18 To reproduce the problem boot a DEBUG_PAGEALLOC kernel and run:
19 # mkdir /tmp/x
20
21 # mount -t tmpfs -o size=100M,mpol=interleave nodev /tmp/x
22
23 # grep /tmp/x /proc/mounts
24 nodev /tmp/x tmpfs rw,relatime,size=102400k,mpol=interleave:0-3 0 0
25
26 # mount -o remount,size=200M nodev /tmp/x
27
28 # grep /tmp/x /proc/mounts
29 nodev /tmp/x tmpfs rw,relatime,size=204800k,mpol=??? 0 0
30 # note ? garbage in mpol=... output above
31
32 # dd if=/dev/zero of=/tmp/x/f count=1
33 # panic here
34
35 Panic:
36 BUG: unable to handle kernel NULL pointer dereference at (null)
37 IP: [< (null)>] (null)
38 [...]
39 Oops: 0010 [#1] SMP DEBUG_PAGEALLOC
40 Call Trace:
41 mpol_shared_policy_init+0xa5/0x160
42 shmem_get_inode+0x209/0x270
43 shmem_mknod+0x3e/0xf0
44 shmem_create+0x18/0x20
45 vfs_create+0xb5/0x130
46 do_last+0x9a1/0xea0
47 path_openat+0xb3/0x4d0
48 do_filp_open+0x42/0xa0
49 do_sys_open+0xfe/0x1e0
50 compat_sys_open+0x1b/0x20
51 cstar_dispatch+0x7/0x1f
52
53 Non-debug kernels will not crash immediately because referencing the
54 dangling mpol will not cause a fault. Instead the filesystem will
55 reference a freed mempolicy object, which will cause unpredictable
56 behavior.
57
58 The problem boils down to a dropped mpol reference below if
59 shmem_parse_options() does not allocate a new mpol:
60
61 config = *sbinfo
62 shmem_parse_options(data, &config, true)
63 mpol_put(sbinfo->mpol)
64 sbinfo->mpol = config.mpol /* BUG: saves unreferenced mpol */
65
66 This patch avoids the crash by not releasing the mempolicy if
67 shmem_parse_options() doesn't create a new mpol.
68
69 How far back does this issue go? I see it in both 2.6.36 and 3.3. I did
70 not look back further.
71
72 Signed-off-by: Greg Thelen <gthelen@google.com>
73 Acked-by: Hugh Dickins <hughd@google.com>
74 Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
75 Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
76 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
77
78 ---
79 mm/shmem.c | 10 ++++++++--
80 1 file changed, 8 insertions(+), 2 deletions(-)
81
82 --- a/mm/shmem.c
83 +++ b/mm/shmem.c
84 @@ -2397,6 +2397,7 @@ static int shmem_remount_fs(struct super
85 unsigned long inodes;
86 int error = -EINVAL;
87
88 + config.mpol = NULL;
89 if (shmem_parse_options(data, &config, true))
90 return error;
91
92 @@ -2421,8 +2422,13 @@ static int shmem_remount_fs(struct super
93 sbinfo->max_inodes = config.max_inodes;
94 sbinfo->free_inodes = config.max_inodes - inodes;
95
96 - mpol_put(sbinfo->mpol);
97 - sbinfo->mpol = config.mpol; /* transfers initial ref */
98 + /*
99 + * Preserve previous mempolicy unless mpol remount option was specified.
100 + */
101 + if (config.mpol) {
102 + mpol_put(sbinfo->mpol);
103 + sbinfo->mpol = config.mpol; /* transfers initial ref */
104 + }
105 out:
106 spin_unlock(&sbinfo->stat_lock);
107 return error;