summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSona Sarmadi <sona.sarmadi@enea.com>2016-01-27 10:45:52 +0100
committerPaul Vaduva <Paul.Vaduva@enea.com>2016-01-28 09:17:35 +0100
commitf846a18b030d4bccbb7a2d1fb7359df6c6c69048 (patch)
tree77a25f09545a30519ea1b141a71a2e483d1ef05b
parente568d65e41f3fde7db8a8aab60ac7e750ea73325 (diff)
downloadmeta-hierofalcon-f846a18b030d4bccbb7a2d1fb7359df6c6c69048.tar.gz
kernel:vfs: CVE-2015-2925
Fixes a flaw which was found in the way the Linux kernel's file system implementation handled rename operations in which the source was inside and the destination was outside of a bind mount. A privileged user inside a container could use this flaw to escape the bind mount and, potentially, escalate their privileges on the system. References: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2015-2925 http://www.openwall.com/lists/oss-security/2015/04/03/7 Reference to the upstream fixes: vfs: http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/ commit/?id=397d425dc26da728396e66d392d5dcb8dac30c37 dcache: http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/ commit/?id=cde93be45a8a90d8c264c776fab63487b5038a65 Signed-off-by: Sona Sarmadi <sona.sarmadi@enea.com> Signed-off-by: Paul Vaduva <Paul.Vaduva@enea.com>
-rw-r--r--recipes-kernel/linux/linux-hierofalcon-3.19/dcache-CVE-2015-2925.patch70
-rw-r--r--recipes-kernel/linux/linux-hierofalcon-3.19/vfs-CVE-2015-2925.patch126
-rw-r--r--recipes-kernel/linux/linux-hierofalcon-4.1/dcache-CVE-2015-2925.patch70
-rw-r--r--recipes-kernel/linux/linux-hierofalcon-4.1/vfs-CVE-2015-2925.patch126
-rw-r--r--recipes-kernel/linux/linux-hierofalcon_3.19.bb2
-rw-r--r--recipes-kernel/linux/linux-hierofalcon_4.1.bb2
6 files changed, 396 insertions, 0 deletions
diff --git a/recipes-kernel/linux/linux-hierofalcon-3.19/dcache-CVE-2015-2925.patch b/recipes-kernel/linux/linux-hierofalcon-3.19/dcache-CVE-2015-2925.patch
new file mode 100644
index 0000000..264b27d
--- /dev/null
+++ b/recipes-kernel/linux/linux-hierofalcon-3.19/dcache-CVE-2015-2925.patch
@@ -0,0 +1,70 @@
1From 27f5c615afb5303eb902a1f2535903e0fd1d7517 Mon Sep 17 00:00:00 2001
2From: "Eric W. Biederman" <ebiederm@xmission.com>
3Date: Sat, 15 Aug 2015 13:36:12 -0500
4Subject: dcache: Handle escaped paths in prepend_path
5
6[ Upstream commit cde93be45a8a90d8c264c776fab63487b5038a65 ]
7
8A rename can result in a dentry that by walking up d_parent
9will never reach it's mnt_root. For lack of a better term
10I call this an escaped path.
11
12prepend_path is called by four different functions __d_path,
13d_absolute_path, d_path, and getcwd.
14
15__d_path only wants to see paths are connected to the root it passes
16in. So __d_path needs prepend_path to return an error.
17
18d_absolute_path similarly wants to see paths that are connected to
19some root. Escaped paths are not connected to any mnt_root so
20d_absolute_path needs prepend_path to return an error greater
21than 1. So escaped paths will be treated like paths on lazily
22unmounted mounts.
23
24getcwd needs to prepend "(unreachable)" so getcwd also needs
25prepend_path to return an error.
26
27d_path is the interesting hold out. d_path just wants to print
28something, and does not care about the weird cases. Which raises
29the question what should be printed?
30
31Given that <escaped_path>/<anything> should result in -ENOENT I
32believe it is desirable for escaped paths to be printed as empty
33paths. As there are not really any meaninful path components when
34considered from the perspective of a mount tree.
35
36So tweak prepend_path to return an empty path with an new error
37code of 3 when it encounters an escaped path.
38
39Fixes CVE-2015-2925.
40Upstream-Status: Backport
41
42Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
43Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
44Signed-off-by: Sasha Levin <sasha.levin@oracle.com>
45Signed-off-by: Sona Sarmadi <sona.sarmadi@enea.com>
46---
47 fs/dcache.c | 7 +++++++
48 1 file changed, 7 insertions(+)
49
50diff --git a/fs/dcache.c b/fs/dcache.c
51index a66d6d8..28ee20a 100644
52--- a/fs/dcache.c
53+++ b/fs/dcache.c
54@@ -2889,6 +2889,13 @@ restart:
55
56 if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
57 struct mount *parent = ACCESS_ONCE(mnt->mnt_parent);
58+ /* Escaped? */
59+ if (dentry != vfsmnt->mnt_root) {
60+ bptr = *buffer;
61+ blen = *buflen;
62+ error = 3;
63+ break;
64+ }
65 /* Global root? */
66 if (mnt != parent) {
67 dentry = ACCESS_ONCE(mnt->mnt_mountpoint);
68--
69cgit v0.12
70
diff --git a/recipes-kernel/linux/linux-hierofalcon-3.19/vfs-CVE-2015-2925.patch b/recipes-kernel/linux/linux-hierofalcon-3.19/vfs-CVE-2015-2925.patch
new file mode 100644
index 0000000..ed930b7
--- /dev/null
+++ b/recipes-kernel/linux/linux-hierofalcon-3.19/vfs-CVE-2015-2925.patch
@@ -0,0 +1,126 @@
1From 7f61fd99a60195578215f46ed870b5c118cfbfc0 Mon Sep 17 00:00:00 2001
2From: "Eric W. Biederman" <ebiederm@xmission.com>
3Date: Sat, 15 Aug 2015 20:27:13 -0500
4Subject: vfs: Test for and handle paths that are unreachable from their
5 mnt_root
6
7[ Upstream commit 397d425dc26da728396e66d392d5dcb8dac30c37 ]
8
9In rare cases a directory can be renamed out from under a bind mount.
10In those cases without special handling it becomes possible to walk up
11the directory tree to the root dentry of the filesystem and down
12from the root dentry to every other file or directory on the filesystem.
13
14Like division by zero .. from an unconnected path can not be given
15a useful semantic as there is no predicting at which path component
16the code will realize it is unconnected. We certainly can not match
17the current behavior as the current behavior is a security hole.
18
19Therefore when encounting .. when following an unconnected path
20return -ENOENT.
21
22- Add a function path_connected to verify path->dentry is reachable
23 from path->mnt.mnt_root. AKA to validate that rename did not do
24 something nasty to the bind mount.
25
26 To avoid races path_connected must be called after following a path
27 component to it's next path component.
28
29Fixes CVE-2015-2925.
30Upstream-Status: Backport
31
32Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
33Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
34Signed-off-by: Sasha Levin <sasha.levin@oracle.com>
35Signed-off-by: Sona Sarmadi <sona.sarmadi@enea.com>
36---
37 fs/namei.c | 31 ++++++++++++++++++++++++++++---
38 1 file changed, 28 insertions(+), 3 deletions(-)
39
40diff --git a/fs/namei.c b/fs/namei.c
41index d20f061..be3d538 100644
42--- a/fs/namei.c
43+++ b/fs/namei.c
44@@ -487,6 +487,24 @@ void path_put(const struct path *path)
45 }
46 EXPORT_SYMBOL(path_put);
47
48+/**
49+ * path_connected - Verify that a path->dentry is below path->mnt.mnt_root
50+ * @path: nameidate to verify
51+ *
52+ * Rename can sometimes move a file or directory outside of a bind
53+ * mount, path_connected allows those cases to be detected.
54+ */
55+static bool path_connected(const struct path *path)
56+{
57+ struct vfsmount *mnt = path->mnt;
58+
59+ /* Only bind mounts can have disconnected paths */
60+ if (mnt->mnt_root == mnt->mnt_sb->s_root)
61+ return true;
62+
63+ return is_subdir(path->dentry, mnt->mnt_root);
64+}
65+
66 /*
67 * Path walking has 2 modes, rcu-walk and ref-walk (see
68 * Documentation/filesystems/path-lookup.txt). In situations when we can't
69@@ -1164,6 +1182,8 @@ static int follow_dotdot_rcu(struct nameidata *nd)
70 goto failed;
71 nd->path.dentry = parent;
72 nd->seq = seq;
73+ if (unlikely(!path_connected(&nd->path)))
74+ goto failed;
75 break;
76 }
77 if (!follow_up_rcu(&nd->path))
78@@ -1260,7 +1280,7 @@ static void follow_mount(struct path *path)
79 }
80 }
81
82-static void follow_dotdot(struct nameidata *nd)
83+static int follow_dotdot(struct nameidata *nd)
84 {
85 if (!nd->root.mnt)
86 set_root(nd);
87@@ -1276,6 +1296,10 @@ static void follow_dotdot(struct nameidata *nd)
88 /* rare case of legitimate dget_parent()... */
89 nd->path.dentry = dget_parent(nd->path.dentry);
90 dput(old);
91+ if (unlikely(!path_connected(&nd->path))) {
92+ path_put(&nd->path);
93+ return -ENOENT;
94+ }
95 break;
96 }
97 if (!follow_up(&nd->path))
98@@ -1283,6 +1307,7 @@ static void follow_dotdot(struct nameidata *nd)
99 }
100 follow_mount(&nd->path);
101 nd->inode = nd->path.dentry->d_inode;
102+ return 0;
103 }
104
105 /*
106@@ -1503,7 +1528,7 @@ static inline int handle_dots(struct nameidata *nd, int type)
107 if (follow_dotdot_rcu(nd))
108 return -ECHILD;
109 } else
110- follow_dotdot(nd);
111+ return follow_dotdot(nd);
112 }
113 return 0;
114 }
115@@ -2239,7 +2264,7 @@ mountpoint_last(struct nameidata *nd, struct path *path)
116 if (unlikely(nd->last_type != LAST_NORM)) {
117 error = handle_dots(nd, nd->last_type);
118 if (error)
119- goto out;
120+ return error;
121 dentry = dget(nd->path.dentry);
122 goto done;
123 }
124--
125cgit v0.12
126
diff --git a/recipes-kernel/linux/linux-hierofalcon-4.1/dcache-CVE-2015-2925.patch b/recipes-kernel/linux/linux-hierofalcon-4.1/dcache-CVE-2015-2925.patch
new file mode 100644
index 0000000..a6a8449
--- /dev/null
+++ b/recipes-kernel/linux/linux-hierofalcon-4.1/dcache-CVE-2015-2925.patch
@@ -0,0 +1,70 @@
1From 6f4e45e35c02fd23589a62aab0dc84286cc1302c Mon Sep 17 00:00:00 2001
2From: "Eric W. Biederman" <ebiederm@xmission.com>
3Date: Sat, 15 Aug 2015 13:36:12 -0500
4Subject: dcache: Handle escaped paths in prepend_path
5
6commit cde93be45a8a90d8c264c776fab63487b5038a65 upstream.
7
8A rename can result in a dentry that by walking up d_parent
9will never reach it's mnt_root. For lack of a better term
10I call this an escaped path.
11
12prepend_path is called by four different functions __d_path,
13d_absolute_path, d_path, and getcwd.
14
15__d_path only wants to see paths are connected to the root it passes
16in. So __d_path needs prepend_path to return an error.
17
18d_absolute_path similarly wants to see paths that are connected to
19some root. Escaped paths are not connected to any mnt_root so
20d_absolute_path needs prepend_path to return an error greater
21than 1. So escaped paths will be treated like paths on lazily
22unmounted mounts.
23
24getcwd needs to prepend "(unreachable)" so getcwd also needs
25prepend_path to return an error.
26
27d_path is the interesting hold out. d_path just wants to print
28something, and does not care about the weird cases. Which raises
29the question what should be printed?
30
31Given that <escaped_path>/<anything> should result in -ENOENT I
32believe it is desirable for escaped paths to be printed as empty
33paths. As there are not really any meaninful path components when
34considered from the perspective of a mount tree.
35
36So tweak prepend_path to return an empty path with an new error
37code of 3 when it encounters an escaped path.
38
39Fixes CVE-2015-2925.
40Upstream-Status: Backport
41
42Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
43Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
44Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
45Signed-off-by: Sona Sarmadi <sona.sarmadi@enea.com>
46---
47 fs/dcache.c | 7 +++++++
48 1 file changed, 7 insertions(+)
49
50diff --git a/fs/dcache.c b/fs/dcache.c
51index 5d03eb0..2e8ddc1 100644
52--- a/fs/dcache.c
53+++ b/fs/dcache.c
54@@ -2923,6 +2923,13 @@ restart:
55
56 if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
57 struct mount *parent = ACCESS_ONCE(mnt->mnt_parent);
58+ /* Escaped? */
59+ if (dentry != vfsmnt->mnt_root) {
60+ bptr = *buffer;
61+ blen = *buflen;
62+ error = 3;
63+ break;
64+ }
65 /* Global root? */
66 if (mnt != parent) {
67 dentry = ACCESS_ONCE(mnt->mnt_mountpoint);
68--
69cgit v0.12
70
diff --git a/recipes-kernel/linux/linux-hierofalcon-4.1/vfs-CVE-2015-2925.patch b/recipes-kernel/linux/linux-hierofalcon-4.1/vfs-CVE-2015-2925.patch
new file mode 100644
index 0000000..aa20d7f
--- /dev/null
+++ b/recipes-kernel/linux/linux-hierofalcon-4.1/vfs-CVE-2015-2925.patch
@@ -0,0 +1,126 @@
1From eed13ce27f481cba65352e73403ca15e67bc26a4 Mon Sep 17 00:00:00 2001
2From: "Eric W. Biederman" <ebiederm@xmission.com>
3Date: Sat, 15 Aug 2015 20:27:13 -0500
4Subject: vfs: Test for and handle paths that are unreachable from their
5 mnt_root
6
7commit 397d425dc26da728396e66d392d5dcb8dac30c37 upstream.
8
9In rare cases a directory can be renamed out from under a bind mount.
10In those cases without special handling it becomes possible to walk up
11the directory tree to the root dentry of the filesystem and down
12from the root dentry to every other file or directory on the filesystem.
13
14Like division by zero .. from an unconnected path can not be given
15a useful semantic as there is no predicting at which path component
16the code will realize it is unconnected. We certainly can not match
17the current behavior as the current behavior is a security hole.
18
19Therefore when encounting .. when following an unconnected path
20return -ENOENT.
21
22- Add a function path_connected to verify path->dentry is reachable
23 from path->mnt.mnt_root. AKA to validate that rename did not do
24 something nasty to the bind mount.
25
26 To avoid races path_connected must be called after following a path
27 component to it's next path component.
28
29Fixes CVE-2015-2925.
30Upstream-Status: Backport
31
32Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
33Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
34Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
35Signed-off-by: Sona Sarmadi <sona.sarmadi@enea.com>
36---
37 fs/namei.c | 31 ++++++++++++++++++++++++++++---
38 1 file changed, 28 insertions(+), 3 deletions(-)
39
40diff --git a/fs/namei.c b/fs/namei.c
41index fe30d3b..acdab61 100644
42--- a/fs/namei.c
43+++ b/fs/namei.c
44@@ -505,6 +505,24 @@ struct nameidata {
45 char *saved_names[MAX_NESTED_LINKS + 1];
46 };
47
48+/**
49+ * path_connected - Verify that a path->dentry is below path->mnt.mnt_root
50+ * @path: nameidate to verify
51+ *
52+ * Rename can sometimes move a file or directory outside of a bind
53+ * mount, path_connected allows those cases to be detected.
54+ */
55+static bool path_connected(const struct path *path)
56+{
57+ struct vfsmount *mnt = path->mnt;
58+
59+ /* Only bind mounts can have disconnected paths */
60+ if (mnt->mnt_root == mnt->mnt_sb->s_root)
61+ return true;
62+
63+ return is_subdir(path->dentry, mnt->mnt_root);
64+}
65+
66 /*
67 * Path walking has 2 modes, rcu-walk and ref-walk (see
68 * Documentation/filesystems/path-lookup.txt). In situations when we can't
69@@ -1194,6 +1212,8 @@ static int follow_dotdot_rcu(struct nameidata *nd)
70 goto failed;
71 nd->path.dentry = parent;
72 nd->seq = seq;
73+ if (unlikely(!path_connected(&nd->path)))
74+ goto failed;
75 break;
76 }
77 if (!follow_up_rcu(&nd->path))
78@@ -1290,7 +1310,7 @@ static void follow_mount(struct path *path)
79 }
80 }
81
82-static void follow_dotdot(struct nameidata *nd)
83+static int follow_dotdot(struct nameidata *nd)
84 {
85 if (!nd->root.mnt)
86 set_root(nd);
87@@ -1306,6 +1326,10 @@ static void follow_dotdot(struct nameidata *nd)
88 /* rare case of legitimate dget_parent()... */
89 nd->path.dentry = dget_parent(nd->path.dentry);
90 dput(old);
91+ if (unlikely(!path_connected(&nd->path))) {
92+ path_put(&nd->path);
93+ return -ENOENT;
94+ }
95 break;
96 }
97 if (!follow_up(&nd->path))
98@@ -1313,6 +1337,7 @@ static void follow_dotdot(struct nameidata *nd)
99 }
100 follow_mount(&nd->path);
101 nd->inode = nd->path.dentry->d_inode;
102+ return 0;
103 }
104
105 /*
106@@ -1541,7 +1566,7 @@ static inline int handle_dots(struct nameidata *nd, int type)
107 if (follow_dotdot_rcu(nd))
108 return -ECHILD;
109 } else
110- follow_dotdot(nd);
111+ return follow_dotdot(nd);
112 }
113 return 0;
114 }
115@@ -2290,7 +2315,7 @@ mountpoint_last(struct nameidata *nd, struct path *path)
116 if (unlikely(nd->last_type != LAST_NORM)) {
117 error = handle_dots(nd, nd->last_type);
118 if (error)
119- goto out;
120+ return error;
121 dentry = dget(nd->path.dentry);
122 goto done;
123 }
124--
125cgit v0.12
126
diff --git a/recipes-kernel/linux/linux-hierofalcon_3.19.bb b/recipes-kernel/linux/linux-hierofalcon_3.19.bb
index 6e77066..7f4720a 100644
--- a/recipes-kernel/linux/linux-hierofalcon_3.19.bb
+++ b/recipes-kernel/linux/linux-hierofalcon_3.19.bb
@@ -29,6 +29,8 @@ SRC_URI = "git://git.yoctoproject.org/linux-yocto-3.19;branch="standard/qemuarm6
29 file://ipv4-CVE-2015-3636.patch \ 29 file://ipv4-CVE-2015-3636.patch \
30 file://usb-whiteheat-CVE-2015-5257.patch \ 30 file://usb-whiteheat-CVE-2015-5257.patch \
31 file://security-keys-CVE-2016-0728.patch \ 31 file://security-keys-CVE-2016-0728.patch \
32 file://vfs-CVE-2015-2925.patch \
33 file://dcache-CVE-2015-2925.patch \
32 " 34 "
33 35
34S = "${WORKDIR}/git" 36S = "${WORKDIR}/git"
diff --git a/recipes-kernel/linux/linux-hierofalcon_4.1.bb b/recipes-kernel/linux/linux-hierofalcon_4.1.bb
index 61b1dae..4fafe34 100644
--- a/recipes-kernel/linux/linux-hierofalcon_4.1.bb
+++ b/recipes-kernel/linux/linux-hierofalcon_4.1.bb
@@ -28,6 +28,8 @@ SRC_URI = "git://git.yoctoproject.org/linux-yocto-4.1;branch="standard/qemuarm64
28 file://vhost-CVE-2015-6252.patch \ 28 file://vhost-CVE-2015-6252.patch \
29 file://usb-whiteheat-CVE-2015-5257.patch \ 29 file://usb-whiteheat-CVE-2015-5257.patch \
30 file://security-keys-CVE-2016-0728.patch \ 30 file://security-keys-CVE-2016-0728.patch \
31 file://vfs-CVE-2015-2925.patch \
32 file://dcache-CVE-2015-2925.patch \
31 " 33 "
32 34
33S = "${WORKDIR}/git" 35S = "${WORKDIR}/git"