summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosh Boyer <jwboyer@fedoraproject.org>2014-12-15 14:26:22 -0500
committerJosh Boyer <jwboyer@fedoraproject.org>2014-12-15 14:26:29 -0500
commit32f1e15e155aa239cedc2fba1a319ed38b7674e5 (patch)
tree704879d6ef0865e8c64b8d31799c4a77f0958bbe
parentc1706593bc0d9e86e72df56af96bba44f452ceb0 (diff)
downloadkernel-32f1e15e155aa239cedc2fba1a319ed38b7674e5.tar.gz
kernel-32f1e15e155aa239cedc2fba1a319ed38b7674e5.tar.xz
kernel-32f1e15e155aa239cedc2fba1a319ed38b7674e5.zip
CVE-2014-8133 x86: espfix(64) bypass via set_thread_area and CLONE_SETTLS (rhbz 1172797 1174374)
-rw-r--r--kernel.spec7
-rw-r--r--x86-tls-Validate-TLS-entries-to-protect-espfix.patch77
2 files changed, 84 insertions, 0 deletions
diff --git a/kernel.spec b/kernel.spec
index 25e337239..215c64e2d 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -627,6 +627,9 @@ Patch26096: cfg80211-don-t-WARN-about-two-consecutive-Country-IE.patch
Patch26098: move-d_rcu-from-overlapping-d_child-to-overlapping-d.patch
Patch26099: deal-with-deadlock-in-d_walk.patch
+#CVE-2014-8133 rhbz 1172797 1174374
+Patch26100: x86-tls-Validate-TLS-entries-to-protect-espfix.patch
+
# git clone ssh://git.fedorahosted.org/git/kernel-arm64.git, git diff master...devel
Patch30000: kernel-arm64.patch
@@ -1363,6 +1366,9 @@ ApplyPatch cfg80211-don-t-WARN-about-two-consecutive-Country-IE.patch
ApplyPatch move-d_rcu-from-overlapping-d_child-to-overlapping-d.patch
ApplyPatch deal-with-deadlock-in-d_walk.patch
+#CVE-2014-8133 rhbz 1172797 1174374
+ApplyPatch x86-tls-Validate-TLS-entries-to-protect-espfix.patch
+
%if 0%{?aarch64patches}
ApplyPatch kernel-arm64.patch
%ifnarch aarch64 # this is stupid, but i want to notice before secondary koji does.
@@ -2232,6 +2238,7 @@ fi
# || ||
%changelog
* Mon Dec 15 2014 Josh Boyer <jwboyer@fedoraproject.org>
+- CVE-2014-8133 x86: espfix(64) bypass via set_thread_area and CLONE_SETTLS (rhbz 1172797 1174374)
- CVE-2014-8559 deadlock due to incorrect usage of rename_lock (rhbz 1159313 1173814)
* Fri Dec 12 2014 Kyle McMartin <kyle@fedoraproject.org>
diff --git a/x86-tls-Validate-TLS-entries-to-protect-espfix.patch b/x86-tls-Validate-TLS-entries-to-protect-espfix.patch
new file mode 100644
index 000000000..52c049767
--- /dev/null
+++ b/x86-tls-Validate-TLS-entries-to-protect-espfix.patch
@@ -0,0 +1,77 @@
+From: Andy Lutomirski <luto@amacapital.net>
+Date: Thu, 4 Dec 2014 16:48:16 -0800
+Subject: [PATCH] x86/tls: Validate TLS entries to protect espfix
+
+Installing a 16-bit RW data segment into the GDT defeats espfix.
+AFAICT this will not affect glibc, Wine, or dosemu at all.
+
+Signed-off-by: Andy Lutomirski <luto@amacapital.net>
+Acked-by: H. Peter Anvin <hpa@zytor.com>
+Cc: stable@vger.kernel.org
+Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
+Cc: Linus Torvalds <torvalds@linux-foundation.org>
+Cc: security@kernel.org <security@kernel.org>
+Cc: Willy Tarreau <w@1wt.eu>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+---
+ arch/x86/kernel/tls.c | 23 +++++++++++++++++++++++
+ 1 file changed, 23 insertions(+)
+
+diff --git a/arch/x86/kernel/tls.c b/arch/x86/kernel/tls.c
+index f7fec09e3e3a..e7650bd71109 100644
+--- a/arch/x86/kernel/tls.c
++++ b/arch/x86/kernel/tls.c
+@@ -27,6 +27,21 @@ static int get_free_idx(void)
+ return -ESRCH;
+ }
+
++static bool tls_desc_okay(const struct user_desc *info)
++{
++ if (LDT_empty(info))
++ return true;
++
++ /*
++ * espfix is required for 16-bit data segments, but espfix
++ * only works for LDT segments.
++ */
++ if (!info->seg_32bit)
++ return false;
++
++ return true;
++}
++
+ static void set_tls_desc(struct task_struct *p, int idx,
+ const struct user_desc *info, int n)
+ {
+@@ -66,6 +81,9 @@ int do_set_thread_area(struct task_struct *p, int idx,
+ if (copy_from_user(&info, u_info, sizeof(info)))
+ return -EFAULT;
+
++ if (!tls_desc_okay(&info))
++ return -EINVAL;
++
+ if (idx == -1)
+ idx = info.entry_number;
+
+@@ -192,6 +210,7 @@ int regset_tls_set(struct task_struct *target, const struct user_regset *regset,
+ {
+ struct user_desc infobuf[GDT_ENTRY_TLS_ENTRIES];
+ const struct user_desc *info;
++ int i;
+
+ if (pos >= GDT_ENTRY_TLS_ENTRIES * sizeof(struct user_desc) ||
+ (pos % sizeof(struct user_desc)) != 0 ||
+@@ -205,6 +224,10 @@ int regset_tls_set(struct task_struct *target, const struct user_regset *regset,
+ else
+ info = infobuf;
+
++ for (i = 0; i < count / sizeof(struct user_desc); i++)
++ if (!tls_desc_okay(info + i))
++ return -EINVAL;
++
+ set_tls_desc(target,
+ GDT_ENTRY_TLS_MIN + (pos / sizeof(struct user_desc)),
+ info, count / sizeof(struct user_desc));
+--
+2.1.0
+