More security fixes
drm-i915-sanity-check-pread-pwrite.patch; fix CVE-2010-2962, arbitrary kernel memory write via i915 GEM ioctl kvm-fix-fs-gs-reload-oops-with-invalid-ldt.patch; fix CVE-2010-3698, kvm: invalid selector in fs/gs causes kernel panic v4l1-fix-32-bit-compat-microcode-loading-translation.patch; fixes CVE-2010-2963, v4l: VIDIOCSMICROCODE arbitrary write
This commit is contained in:
parent
cbdb312a9e
commit
643d353feb
|
@ -0,0 +1,89 @@
|
|||
From ce9d419dbecc292cc3e06e8b1d6d123d3fa813a4 Mon Sep 17 00:00:00 2001
|
||||
From: Chris Wilson <chris@chris-wilson.co.uk>
|
||||
Date: Sun, 26 Sep 2010 20:50:05 +0100
|
||||
Subject: drm/i915: Sanity check pread/pwrite
|
||||
|
||||
From: Chris Wilson <chris@chris-wilson.co.uk>
|
||||
|
||||
commit ce9d419dbecc292cc3e06e8b1d6d123d3fa813a4 upstream.
|
||||
|
||||
Move the access control up from the fast paths, which are no longer
|
||||
universally taken first, up into the caller. This then duplicates some
|
||||
sanity checking along the slow paths, but is much simpler.
|
||||
Tracked as CVE-2010-2962.
|
||||
|
||||
Reported-by: Kees Cook <kees@ubuntu.com>
|
||||
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
|
||||
---
|
||||
drivers/gpu/drm/i915/i915_gem.c | 28 ++++++++++++++++++++--------
|
||||
1 file changed, 20 insertions(+), 8 deletions(-)
|
||||
|
||||
--- a/drivers/gpu/drm/i915/i915_gem.c
|
||||
+++ b/drivers/gpu/drm/i915/i915_gem.c
|
||||
@@ -465,8 +465,15 @@ i915_gem_pread_ioctl(struct drm_device *
|
||||
*/
|
||||
if (args->offset > obj->size || args->size > obj->size ||
|
||||
args->offset + args->size > obj->size) {
|
||||
- drm_gem_object_unreference_unlocked(obj);
|
||||
- return -EINVAL;
|
||||
+ ret = -EINVAL;
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ if (!access_ok(VERIFY_WRITE,
|
||||
+ (char __user *)(uintptr_t)args->data_ptr,
|
||||
+ args->size)) {
|
||||
+ ret = -EFAULT;
|
||||
+ goto err;
|
||||
}
|
||||
|
||||
if (i915_gem_object_needs_bit17_swizzle(obj)) {
|
||||
@@ -478,8 +485,8 @@ i915_gem_pread_ioctl(struct drm_device *
|
||||
file_priv);
|
||||
}
|
||||
|
||||
+err:
|
||||
drm_gem_object_unreference_unlocked(obj);
|
||||
-
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -568,8 +575,6 @@ i915_gem_gtt_pwrite_fast(struct drm_devi
|
||||
|
||||
user_data = (char __user *) (uintptr_t) args->data_ptr;
|
||||
remain = args->size;
|
||||
- if (!access_ok(VERIFY_READ, user_data, remain))
|
||||
- return -EFAULT;
|
||||
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
@@ -928,8 +933,15 @@ i915_gem_pwrite_ioctl(struct drm_device
|
||||
*/
|
||||
if (args->offset > obj->size || args->size > obj->size ||
|
||||
args->offset + args->size > obj->size) {
|
||||
- drm_gem_object_unreference_unlocked(obj);
|
||||
- return -EINVAL;
|
||||
+ ret = -EINVAL;
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ if (!access_ok(VERIFY_READ,
|
||||
+ (char __user *)(uintptr_t)args->data_ptr,
|
||||
+ args->size)) {
|
||||
+ ret = -EFAULT;
|
||||
+ goto err;
|
||||
}
|
||||
|
||||
/* We can only do the GTT pwrite on untiled buffers, as otherwise
|
||||
@@ -963,8 +975,8 @@ i915_gem_pwrite_ioctl(struct drm_device
|
||||
DRM_INFO("pwrite failed %d\n", ret);
|
||||
#endif
|
||||
|
||||
+err:
|
||||
drm_gem_object_unreference_unlocked(obj);
|
||||
-
|
||||
return ret;
|
||||
}
|
||||
|
21
kernel.spec
21
kernel.spec
|
@ -48,7 +48,7 @@ Summary: The Linux kernel
|
|||
# reset this by hand to 1 (or to 0 and then use rpmdev-bumpspec).
|
||||
# scripts/rebase.sh should be made to do that for you, actually.
|
||||
#
|
||||
%global baserelease 47
|
||||
%global baserelease 48
|
||||
%global fedora_build %{baserelease}
|
||||
|
||||
# base_sublevel is the kernel version we're starting with and patching
|
||||
|
@ -772,6 +772,10 @@ Patch13642: mmc-add-ricoh-e822-pci-id.patch
|
|||
Patch13645: tpm-autodetect-itpm-devices.patch
|
||||
Patch13646: depessimize-rds_copy_page_user.patch
|
||||
|
||||
Patch13650: drm-i915-sanity-check-pread-pwrite.patch
|
||||
Patch13651: kvm-fix-fs-gs-reload-oops-with-invalid-ldt.patch
|
||||
Patch13652: v4l1-fix-32-bit-compat-microcode-loading-translation.patch
|
||||
|
||||
%endif
|
||||
|
||||
BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root
|
||||
|
@ -1442,6 +1446,13 @@ ApplyPatch mmc-add-ricoh-e822-pci-id.patch
|
|||
ApplyPatch depessimize-rds_copy_page_user.patch
|
||||
ApplyPatch tpm-autodetect-itpm-devices.patch
|
||||
|
||||
# CVE-2010-2962
|
||||
ApplyPatch drm-i915-sanity-check-pread-pwrite.patch
|
||||
# CVE-2010-3698
|
||||
ApplyPatch kvm-fix-fs-gs-reload-oops-with-invalid-ldt.patch
|
||||
# CVE-2010-2963
|
||||
ApplyPatch v4l1-fix-32-bit-compat-microcode-loading-translation.patch
|
||||
|
||||
# END OF PATCH APPLICATIONS
|
||||
|
||||
%endif
|
||||
|
@ -2028,6 +2039,14 @@ fi
|
|||
# and build.
|
||||
|
||||
%changelog
|
||||
* Fri Oct 22 2010 Chuck Ebbert <cebbert@redhat.com> 2.6.35.6-48
|
||||
- drm-i915-sanity-check-pread-pwrite.patch;
|
||||
fix CVE-2010-2962, arbitrary kernel memory write via i915 GEM ioctl
|
||||
- kvm-fix-fs-gs-reload-oops-with-invalid-ldt.patch;
|
||||
fix CVE-2010-3698, kvm: invalid selector in fs/gs causes kernel panic
|
||||
- v4l1-fix-32-bit-compat-microcode-loading-translation.patch;
|
||||
fixes CVE-2010-2963, v4l: VIDIOCSMICROCODE arbitrary write
|
||||
|
||||
* Fri Oct 22 2010 Kyle McMartin <kyle@redhat.com> 2.6.35.6-47
|
||||
- tpm-autodetect-itpm-devices.patch: Auto-fix TPM issues on various
|
||||
laptops which prevented suspend/resume.
|
||||
|
|
|
@ -0,0 +1,164 @@
|
|||
From: Avi Kivity <avi@redhat.com>
|
||||
Date: Tue, 19 Oct 2010 14:46:55 +0000 (+0200)
|
||||
Subject: KVM: Fix fs/gs reload oops with invalid ldt
|
||||
X-Git-Tag: v2.6.36~4^2
|
||||
X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=9581d442b9058d3699b4be568b6e5eae38a41493
|
||||
|
||||
KVM: Fix fs/gs reload oops with invalid ldt
|
||||
|
||||
kvm reloads the host's fs and gs blindly, however the underlying segment
|
||||
descriptors may be invalid due to the user modifying the ldt after loading
|
||||
them.
|
||||
|
||||
Fix by using the safe accessors (loadsegment() and load_gs_index()) instead
|
||||
of home grown unsafe versions.
|
||||
|
||||
This is CVE-2010-3698.
|
||||
|
||||
KVM-Stable-Tag.
|
||||
Signed-off-by: Avi Kivity <avi@redhat.com>
|
||||
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
|
||||
---
|
||||
|
||||
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
|
||||
index 502e53f..c52e2eb 100644
|
||||
--- a/arch/x86/include/asm/kvm_host.h
|
||||
+++ b/arch/x86/include/asm/kvm_host.h
|
||||
@@ -652,20 +652,6 @@ static inline struct kvm_mmu_page *page_header(hpa_t shadow_page)
|
||||
return (struct kvm_mmu_page *)page_private(page);
|
||||
}
|
||||
|
||||
-static inline u16 kvm_read_fs(void)
|
||||
-{
|
||||
- u16 seg;
|
||||
- asm("mov %%fs, %0" : "=g"(seg));
|
||||
- return seg;
|
||||
-}
|
||||
-
|
||||
-static inline u16 kvm_read_gs(void)
|
||||
-{
|
||||
- u16 seg;
|
||||
- asm("mov %%gs, %0" : "=g"(seg));
|
||||
- return seg;
|
||||
-}
|
||||
-
|
||||
static inline u16 kvm_read_ldt(void)
|
||||
{
|
||||
u16 ldt;
|
||||
@@ -673,16 +659,6 @@ static inline u16 kvm_read_ldt(void)
|
||||
return ldt;
|
||||
}
|
||||
|
||||
-static inline void kvm_load_fs(u16 sel)
|
||||
-{
|
||||
- asm("mov %0, %%fs" : : "rm"(sel));
|
||||
-}
|
||||
-
|
||||
-static inline void kvm_load_gs(u16 sel)
|
||||
-{
|
||||
- asm("mov %0, %%gs" : : "rm"(sel));
|
||||
-}
|
||||
-
|
||||
static inline void kvm_load_ldt(u16 sel)
|
||||
{
|
||||
asm("lldt %0" : : "rm"(sel));
|
||||
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
|
||||
index 81ed28c..8a3f9f6 100644
|
||||
--- a/arch/x86/kvm/svm.c
|
||||
+++ b/arch/x86/kvm/svm.c
|
||||
@@ -3163,8 +3163,8 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu)
|
||||
sync_lapic_to_cr8(vcpu);
|
||||
|
||||
save_host_msrs(vcpu);
|
||||
- fs_selector = kvm_read_fs();
|
||||
- gs_selector = kvm_read_gs();
|
||||
+ savesegment(fs, fs_selector);
|
||||
+ savesegment(gs, gs_selector);
|
||||
ldt_selector = kvm_read_ldt();
|
||||
svm->vmcb->save.cr2 = vcpu->arch.cr2;
|
||||
/* required for live migration with NPT */
|
||||
@@ -3251,10 +3251,15 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu)
|
||||
vcpu->arch.regs[VCPU_REGS_RSP] = svm->vmcb->save.rsp;
|
||||
vcpu->arch.regs[VCPU_REGS_RIP] = svm->vmcb->save.rip;
|
||||
|
||||
- kvm_load_fs(fs_selector);
|
||||
- kvm_load_gs(gs_selector);
|
||||
- kvm_load_ldt(ldt_selector);
|
||||
load_host_msrs(vcpu);
|
||||
+ loadsegment(fs, fs_selector);
|
||||
+#ifdef CONFIG_X86_64
|
||||
+ load_gs_index(gs_selector);
|
||||
+ wrmsrl(MSR_KERNEL_GS_BASE, current->thread.gs);
|
||||
+#else
|
||||
+ loadsegment(gs, gs_selector);
|
||||
+#endif
|
||||
+ kvm_load_ldt(ldt_selector);
|
||||
|
||||
reload_tss(vcpu);
|
||||
|
||||
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
|
||||
index 49b25ee..7bddfab 100644
|
||||
--- a/arch/x86/kvm/vmx.c
|
||||
+++ b/arch/x86/kvm/vmx.c
|
||||
@@ -803,7 +803,7 @@ static void vmx_save_host_state(struct kvm_vcpu *vcpu)
|
||||
*/
|
||||
vmx->host_state.ldt_sel = kvm_read_ldt();
|
||||
vmx->host_state.gs_ldt_reload_needed = vmx->host_state.ldt_sel;
|
||||
- vmx->host_state.fs_sel = kvm_read_fs();
|
||||
+ savesegment(fs, vmx->host_state.fs_sel);
|
||||
if (!(vmx->host_state.fs_sel & 7)) {
|
||||
vmcs_write16(HOST_FS_SELECTOR, vmx->host_state.fs_sel);
|
||||
vmx->host_state.fs_reload_needed = 0;
|
||||
@@ -811,7 +811,7 @@ static void vmx_save_host_state(struct kvm_vcpu *vcpu)
|
||||
vmcs_write16(HOST_FS_SELECTOR, 0);
|
||||
vmx->host_state.fs_reload_needed = 1;
|
||||
}
|
||||
- vmx->host_state.gs_sel = kvm_read_gs();
|
||||
+ savesegment(gs, vmx->host_state.gs_sel);
|
||||
if (!(vmx->host_state.gs_sel & 7))
|
||||
vmcs_write16(HOST_GS_SELECTOR, vmx->host_state.gs_sel);
|
||||
else {
|
||||
@@ -841,27 +841,21 @@ static void vmx_save_host_state(struct kvm_vcpu *vcpu)
|
||||
|
||||
static void __vmx_load_host_state(struct vcpu_vmx *vmx)
|
||||
{
|
||||
- unsigned long flags;
|
||||
-
|
||||
if (!vmx->host_state.loaded)
|
||||
return;
|
||||
|
||||
++vmx->vcpu.stat.host_state_reload;
|
||||
vmx->host_state.loaded = 0;
|
||||
if (vmx->host_state.fs_reload_needed)
|
||||
- kvm_load_fs(vmx->host_state.fs_sel);
|
||||
+ loadsegment(fs, vmx->host_state.fs_sel);
|
||||
if (vmx->host_state.gs_ldt_reload_needed) {
|
||||
kvm_load_ldt(vmx->host_state.ldt_sel);
|
||||
- /*
|
||||
- * If we have to reload gs, we must take care to
|
||||
- * preserve our gs base.
|
||||
- */
|
||||
- local_irq_save(flags);
|
||||
- kvm_load_gs(vmx->host_state.gs_sel);
|
||||
#ifdef CONFIG_X86_64
|
||||
- wrmsrl(MSR_GS_BASE, vmcs_readl(HOST_GS_BASE));
|
||||
+ load_gs_index(vmx->host_state.gs_sel);
|
||||
+ wrmsrl(MSR_KERNEL_GS_BASE, current->thread.gs);
|
||||
+#else
|
||||
+ loadsegment(gs, vmx->host_state.gs_sel);
|
||||
#endif
|
||||
- local_irq_restore(flags);
|
||||
}
|
||||
reload_tss();
|
||||
#ifdef CONFIG_X86_64
|
||||
@@ -2589,8 +2583,8 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
|
||||
vmcs_write16(HOST_CS_SELECTOR, __KERNEL_CS); /* 22.2.4 */
|
||||
vmcs_write16(HOST_DS_SELECTOR, __KERNEL_DS); /* 22.2.4 */
|
||||
vmcs_write16(HOST_ES_SELECTOR, __KERNEL_DS); /* 22.2.4 */
|
||||
- vmcs_write16(HOST_FS_SELECTOR, kvm_read_fs()); /* 22.2.4 */
|
||||
- vmcs_write16(HOST_GS_SELECTOR, kvm_read_gs()); /* 22.2.4 */
|
||||
+ vmcs_write16(HOST_FS_SELECTOR, 0); /* 22.2.4 */
|
||||
+ vmcs_write16(HOST_GS_SELECTOR, 0); /* 22.2.4 */
|
||||
vmcs_write16(HOST_SS_SELECTOR, __KERNEL_DS); /* 22.2.4 */
|
||||
#ifdef CONFIG_X86_64
|
||||
rdmsrl(MSR_FS_BASE, a);
|
|
@ -0,0 +1,88 @@
|
|||
From 3e645d6b485446c54c6745c5e2cf5c528fe4deec Mon Sep 17 00:00:00 2001
|
||||
From: Linus Torvalds <torvalds@linux-foundation.org>
|
||||
Date: Fri, 15 Oct 2010 11:12:38 -0700
|
||||
Subject: v4l1: fix 32-bit compat microcode loading translation
|
||||
|
||||
From: Linus Torvalds <torvalds@linux-foundation.org>
|
||||
|
||||
commit 3e645d6b485446c54c6745c5e2cf5c528fe4deec upstream.
|
||||
|
||||
The compat code for the VIDIOCSMICROCODE ioctl is totally buggered.
|
||||
It's only used by the VIDEO_STRADIS driver, and that one is scheduled to
|
||||
staging and eventually removed unless somebody steps up to maintain it
|
||||
(at which point it should use request_firmware() rather than some magic
|
||||
ioctl). So we'll get rid of it eventually.
|
||||
|
||||
But in the meantime, the compatibility ioctl code is broken, and this
|
||||
tries to get it to at least limp along (even if Mauro suggested just
|
||||
deleting it entirely, which may be the right thing to do - I don't think
|
||||
the compatibility translation code has ever worked unless you were very
|
||||
lucky).
|
||||
|
||||
Reported-by: Kees Cook <kees.cook@canonical.com>
|
||||
Cc: Mauro Carvalho Chehab <mchehab@infradead.org>
|
||||
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
||||
|
||||
---
|
||||
drivers/media/video/v4l2-compat-ioctl32.c | 32 +++++++++++++++++++-----------
|
||||
1 file changed, 21 insertions(+), 11 deletions(-)
|
||||
|
||||
--- a/drivers/media/video/v4l2-compat-ioctl32.c
|
||||
+++ b/drivers/media/video/v4l2-compat-ioctl32.c
|
||||
@@ -193,17 +193,24 @@ static int put_video_window32(struct vid
|
||||
struct video_code32 {
|
||||
char loadwhat[16]; /* name or tag of file being passed */
|
||||
compat_int_t datasize;
|
||||
- unsigned char *data;
|
||||
+ compat_uptr_t data;
|
||||
};
|
||||
|
||||
-static int get_microcode32(struct video_code *kp, struct video_code32 __user *up)
|
||||
+static struct video_code __user *get_microcode32(struct video_code32 *kp)
|
||||
{
|
||||
- if (!access_ok(VERIFY_READ, up, sizeof(struct video_code32)) ||
|
||||
- copy_from_user(kp->loadwhat, up->loadwhat, sizeof(up->loadwhat)) ||
|
||||
- get_user(kp->datasize, &up->datasize) ||
|
||||
- copy_from_user(kp->data, up->data, up->datasize))
|
||||
- return -EFAULT;
|
||||
- return 0;
|
||||
+ struct video_code __user *up;
|
||||
+
|
||||
+ up = compat_alloc_user_space(sizeof(*up));
|
||||
+
|
||||
+ /*
|
||||
+ * NOTE! We don't actually care if these fail. If the
|
||||
+ * user address is invalid, the native ioctl will do
|
||||
+ * the error handling for us
|
||||
+ */
|
||||
+ (void) copy_to_user(up->loadwhat, kp->loadwhat, sizeof(up->loadwhat));
|
||||
+ (void) put_user(kp->datasize, &up->datasize);
|
||||
+ (void) put_user(compat_ptr(kp->data), &up->data);
|
||||
+ return up;
|
||||
}
|
||||
|
||||
#define VIDIOCGTUNER32 _IOWR('v', 4, struct video_tuner32)
|
||||
@@ -744,7 +751,7 @@ static long do_video_ioctl(struct file *
|
||||
struct video_tuner vt;
|
||||
struct video_buffer vb;
|
||||
struct video_window vw;
|
||||
- struct video_code vc;
|
||||
+ struct video_code32 vc;
|
||||
struct video_audio va;
|
||||
#endif
|
||||
struct v4l2_format v2f;
|
||||
@@ -823,8 +830,11 @@ static long do_video_ioctl(struct file *
|
||||
break;
|
||||
|
||||
case VIDIOCSMICROCODE:
|
||||
- err = get_microcode32(&karg.vc, up);
|
||||
- compatible_arg = 0;
|
||||
+ /* Copy the 32-bit "video_code32" to kernel space */
|
||||
+ if (copy_from_user(&karg.vc, up, sizeof(karg.vc)))
|
||||
+ return -EFAULT;
|
||||
+ /* Convert the 32-bit version to a 64-bit version in user space */
|
||||
+ up = get_microcode32(&karg.vc);
|
||||
break;
|
||||
|
||||
case VIDIOCSFREQ:
|
Loading…
Reference in New Issue