Merge changes from sid up to 3.2.41-2

svn path=/dists/trunk/linux/; revision=19951
This commit is contained in:
Ben Hutchings 2013-03-27 03:51:48 +00:00
commit 55da5d676a
10 changed files with 321 additions and 4 deletions

17
debian/changelog vendored
View File

@ -427,6 +427,23 @@ linux-2.6 (3.3~rc6-1~experimental.1) experimental; urgency=low
-- Ben Hutchings <ben@decadent.org.uk> Sun, 04 Mar 2012 20:27:42 +0000
linux (3.2.41-2) unstable; urgency=low
* [ia64] udeb: Remove efi-modules package; make kernel-image provide
efi-modules (fixes FTBFS)
* linux-headers: Fix file installation on architectures without
Kbuild.platforms (Closes: #703800)
* [x86] drm/i915: bounds check execbuffer relocation count (CVE-2013-0913)
* [x86] drm: Enable DRM_GMA500 as module, replacing DRM_PSB (Closes: #703506)
- Enable DRM_GMA600, DRM_GMA3600, DRM_MEDFIELD
* [x86] KVM: x86: fix for buffer overflow in handling of MSR_KVM_SYSTEM_TIME
(CVE-2013-1796)
* [x86] KVM: x86: Convert MSR_KVM_SYSTEM_TIME to use gfn_to_hva_cache
functions (CVE-2013-1797)
* KVM: Fix bounds checking in ioapic indirect register reads (CVE-2013-1798)
-- Ben Hutchings <ben@decadent.org.uk> Mon, 25 Mar 2013 15:17:44 +0000
linux (3.2.41-1) unstable; urgency=low
* New upstream stable update:

View File

@ -450,6 +450,7 @@ CONFIG_DRM_AST=m
CONFIG_DRM_GMA500=m
CONFIG_DRM_GMA600=y
CONFIG_DRM_GMA3600=y
CONFIG_DRM_MEDFIELD=y
##
## file: drivers/gpu/drm/mgag200/Kconfig

View File

@ -1 +0,0 @@
#include <efi-modules>

View File

@ -32,3 +32,6 @@ Depends: kernel-image, core-modules
Package: nbd-modules
Depends: kernel-image
Package: kernel-image
Provides: efi-modules

View File

@ -0,0 +1,42 @@
From: Andy Honig <ahonig@google.com>
Date: Wed, 20 Feb 2013 14:49:16 -0800
Subject: KVM: Fix bounds checking in ioapic indirect register reads
(CVE-2013-1798)
commit a2c118bfab8bc6b8bb213abfc35201e441693d55 upstream.
If the guest specifies a IOAPIC_REG_SELECT with an invalid value and follows
that with a read of the IOAPIC_REG_WINDOW KVM does not properly validate
that request. ioapic_read_indirect contains an
ASSERT(redir_index < IOAPIC_NUM_PINS), but the ASSERT has no effect in
non-debug builds. In recent kernels this allows a guest to cause a kernel
oops by reading invalid memory. In older kernels (pre-3.3) this allows a
guest to read from large ranges of host memory.
Tested: tested against apic unit tests.
Signed-off-by: Andrew Honig <ahonig@google.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
---
virt/kvm/ioapic.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c
index ce82b94..5ba005c 100644
--- a/virt/kvm/ioapic.c
+++ b/virt/kvm/ioapic.c
@@ -74,9 +74,12 @@ static unsigned long ioapic_read_indirect(struct kvm_ioapic *ioapic,
u32 redir_index = (ioapic->ioregsel - 0x10) >> 1;
u64 redir_content;
- ASSERT(redir_index < IOAPIC_NUM_PINS);
+ if (redir_index < IOAPIC_NUM_PINS)
+ redir_content =
+ ioapic->redirtbl[redir_index].bits;
+ else
+ redir_content = ~0ULL;
- redir_content = ioapic->redirtbl[redir_index].bits;
result = (ioapic->ioregsel & 0x1) ?
(redir_content >> 32) & 0xffffffff :
redir_content & 0xffffffff;

View File

@ -0,0 +1,161 @@
From: Andy Honig <ahonig@google.com>
Date: Wed, 20 Feb 2013 14:48:10 -0800
Subject: KVM: x86: Convert MSR_KVM_SYSTEM_TIME to use gfn_to_hva_cache
functions (CVE-2013-1797)
commit 0b79459b482e85cb7426aa7da683a9f2c97aeae1 upstream.
There is a potential use after free issue with the handling of
MSR_KVM_SYSTEM_TIME. If the guest specifies a GPA in a movable or removable
memory such as frame buffers then KVM might continue to write to that
address even after it's removed via KVM_SET_USER_MEMORY_REGION. KVM pins
the page in memory so it's unlikely to cause an issue, but if the user
space component re-purposes the memory previously used for the guest, then
the guest will be able to corrupt that memory.
Tested: Tested against kvmclock unit test
Signed-off-by: Andrew Honig <ahonig@google.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
---
arch/x86/include/asm/kvm_host.h | 4 ++--
arch/x86/kvm/x86.c | 47 +++++++++++++++++----------------------
2 files changed, 22 insertions(+), 29 deletions(-)
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 635a74d..4979778 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -414,8 +414,8 @@ struct kvm_vcpu_arch {
gpa_t time;
struct pvclock_vcpu_time_info hv_clock;
unsigned int hw_tsc_khz;
- unsigned int time_offset;
- struct page *time_page;
+ struct gfn_to_hva_cache pv_time;
+ bool pv_time_enabled;
/* set guest stopped flag in pvclock flags field */
bool pvclock_set_guest_stopped_request;
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 2ade60c..f19ac0a 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -1406,10 +1406,9 @@ static int kvm_guest_time_update(struct kvm_vcpu *v)
unsigned long flags, this_tsc_khz;
struct kvm_vcpu_arch *vcpu = &v->arch;
struct kvm_arch *ka = &v->kvm->arch;
- void *shared_kaddr;
s64 kernel_ns, max_kernel_ns;
u64 tsc_timestamp, host_tsc;
- struct pvclock_vcpu_time_info *guest_hv_clock;
+ struct pvclock_vcpu_time_info guest_hv_clock;
u8 pvclock_flags;
bool use_master_clock;
@@ -1463,7 +1462,7 @@ static int kvm_guest_time_update(struct kvm_vcpu *v)
local_irq_restore(flags);
- if (!vcpu->time_page)
+ if (!vcpu->pv_time_enabled)
return 0;
/*
@@ -1525,12 +1524,12 @@ static int kvm_guest_time_update(struct kvm_vcpu *v)
*/
vcpu->hv_clock.version += 2;
- shared_kaddr = kmap_atomic(vcpu->time_page);
-
- guest_hv_clock = shared_kaddr + vcpu->time_offset;
+ if (unlikely(kvm_read_guest_cached(v->kvm, &vcpu->pv_time,
+ &guest_hv_clock, sizeof(guest_hv_clock))))
+ return 0;
/* retain PVCLOCK_GUEST_STOPPED if set in guest copy */
- pvclock_flags = (guest_hv_clock->flags & PVCLOCK_GUEST_STOPPED);
+ pvclock_flags = (guest_hv_clock.flags & PVCLOCK_GUEST_STOPPED);
if (vcpu->pvclock_set_guest_stopped_request) {
pvclock_flags |= PVCLOCK_GUEST_STOPPED;
@@ -1543,12 +1542,9 @@ static int kvm_guest_time_update(struct kvm_vcpu *v)
vcpu->hv_clock.flags = pvclock_flags;
- memcpy(shared_kaddr + vcpu->time_offset, &vcpu->hv_clock,
- sizeof(vcpu->hv_clock));
-
- kunmap_atomic(shared_kaddr);
-
- mark_page_dirty(v->kvm, vcpu->time >> PAGE_SHIFT);
+ kvm_write_guest_cached(v->kvm, &vcpu->pv_time,
+ &vcpu->hv_clock,
+ sizeof(vcpu->hv_clock));
return 0;
}
@@ -1837,10 +1833,7 @@ static int kvm_pv_enable_async_pf(struct kvm_vcpu *vcpu, u64 data)
static void kvmclock_reset(struct kvm_vcpu *vcpu)
{
- if (vcpu->arch.time_page) {
- kvm_release_page_dirty(vcpu->arch.time_page);
- vcpu->arch.time_page = NULL;
- }
+ vcpu->arch.pv_time_enabled = false;
}
static void accumulate_steal_time(struct kvm_vcpu *vcpu)
@@ -1947,6 +1940,7 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
break;
case MSR_KVM_SYSTEM_TIME_NEW:
case MSR_KVM_SYSTEM_TIME: {
+ u64 gpa_offset;
kvmclock_reset(vcpu);
vcpu->arch.time = data;
@@ -1956,19 +1950,17 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
if (!(data & 1))
break;
- /* ...but clean it before doing the actual write */
- vcpu->arch.time_offset = data & ~(PAGE_MASK | 1);
+ gpa_offset = data & ~(PAGE_MASK | 1);
/* Check that the address is 32-byte aligned. */
- if (vcpu->arch.time_offset &
- (sizeof(struct pvclock_vcpu_time_info) - 1))
+ if (gpa_offset & (sizeof(struct pvclock_vcpu_time_info) - 1))
break;
- vcpu->arch.time_page =
- gfn_to_page(vcpu->kvm, data >> PAGE_SHIFT);
-
- if (is_error_page(vcpu->arch.time_page))
- vcpu->arch.time_page = NULL;
+ if (kvm_gfn_to_hva_cache_init(vcpu->kvm,
+ &vcpu->arch.pv_time, data & ~1ULL))
+ vcpu->arch.pv_time_enabled = false;
+ else
+ vcpu->arch.pv_time_enabled = true;
break;
}
@@ -2972,7 +2964,7 @@ static int kvm_vcpu_ioctl_x86_set_xcrs(struct kvm_vcpu *vcpu,
*/
static int kvm_set_guest_paused(struct kvm_vcpu *vcpu)
{
- if (!vcpu->arch.time_page)
+ if (!vcpu->arch.pv_time_enabled)
return -EINVAL;
vcpu->arch.pvclock_set_guest_stopped_request = true;
kvm_make_request(KVM_REQ_CLOCK_UPDATE, vcpu);
@@ -6723,6 +6715,7 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
goto fail_free_wbinvd_dirty_mask;
vcpu->arch.ia32_tsc_adjust_msr = 0x0;
+ vcpu->arch.pv_time_enabled = false;
kvm_async_pf_hash_reset(vcpu);
kvm_pmu_init(vcpu);

View File

@ -0,0 +1,39 @@
From: Andy Honig <ahonig@google.com>
Date: Mon, 11 Mar 2013 09:34:52 -0700
Subject: KVM: x86: fix for buffer overflow in handling of MSR_KVM_SYSTEM_TIME
(CVE-2013-1796)
commit c300aa64ddf57d9c5d9c898a64b36877345dd4a9 upstream.
If the guest sets the GPA of the time_page so that the request to update the
time straddles a page then KVM will write onto an incorrect page. The
write is done byusing kmap atomic to get a pointer to the page for the time
structure and then performing a memcpy to that page starting at an offset
that the guest controls. Well behaved guests always provide a 32-byte aligned
address, however a malicious guest could use this to corrupt host kernel
memory.
Tested: Tested against kvmclock unit test.
Signed-off-by: Andrew Honig <ahonig@google.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
---
arch/x86/kvm/x86.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index f7c850b..2ade60c 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -1959,6 +1959,11 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
/* ...but clean it before doing the actual write */
vcpu->arch.time_offset = data & ~(PAGE_MASK | 1);
+ /* Check that the address is 32-byte aligned. */
+ if (vcpu->arch.time_offset &
+ (sizeof(struct pvclock_vcpu_time_info) - 1))
+ break;
+
vcpu->arch.time_page =
gfn_to_page(vcpu->kvm, data >> PAGE_SHIFT);

View File

@ -0,0 +1,49 @@
From: Kees Cook <keescook@chromium.org>
Date: Mon, 11 Mar 2013 17:31:45 -0700
Subject: drm/i915: bounds check execbuffer relocation count
commit 3118a4f652c7b12c752f3222af0447008f9b2368 upstream.
It is possible to wrap the counter used to allocate the buffer for
relocation copies. This could lead to heap writing overflows.
CVE-2013-0913
v3: collapse test, improve comment
v2: move check into validate_exec_list
Signed-off-by: Kees Cook <keescook@chromium.org>
Reported-by: Pinkie Pie
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
drivers/gpu/drm/i915/i915_gem_execbuffer.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -907,15 +907,20 @@ validate_exec_list(struct drm_i915_gem_e
int count)
{
int i;
+ int relocs_total = 0;
+ int relocs_max = INT_MAX / sizeof(struct drm_i915_gem_relocation_entry);
for (i = 0; i < count; i++) {
char __user *ptr = (char __user *)(uintptr_t)exec[i].relocs_ptr;
int length; /* limited by fault_in_pages_readable() */
- /* First check for malicious input causing overflow */
- if (exec[i].relocation_count >
- INT_MAX / sizeof(struct drm_i915_gem_relocation_entry))
+ /* First check for malicious input causing overflow in
+ * the worst case where we need to allocate the entire
+ * relocation tree as a single array.
+ */
+ if (exec[i].relocation_count > relocs_max - relocs_total)
return -EINVAL;
+ relocs_total += exec[i].relocation_count;
length = exec[i].relocation_count *
sizeof(struct drm_i915_gem_relocation_entry);

View File

@ -88,3 +88,7 @@ bugfix/all/efi_pstore-Introducing-workqueue-updating-sysfs.patch
bugfix/all/efivars-explicitly-calculate-length-of-VariableName.patch
bugfix/all/efivars-Handle-duplicate-names-from-get_next_variabl.patch
debian/efivars-remove-check-for-50-full-on-write.patch
bugfix/x86/drm-i915-bounds-check-execbuffer-relocation-count.patch
bugfix/x86/KVM-x86-fix-for-buffer-overflow-in-handling-of-MSR_K.patch
bugfix/x86/KVM-x86-Convert-MSR_KVM_SYSTEM_TIME-to-use-gfn_to_hv.patch
bugfix/all/KVM-Fix-bounds-checking-in-ioapic-indirect-register-.patch

8
debian/rules.real vendored
View File

@ -196,6 +196,7 @@ install-doc: $(STAMPS_DIR)/build-doc
mkdir -p $(OUT_DIR)
cp -a CREDITS MAINTAINERS README REPORTING-BUGS Documentation $(OUT_DIR)
rm -rf $(OUT_DIR)/Documentation/DocBook
set -o pipefail; \
cd $(DIR)/Documentation/DocBook; \
find * -name '*.html' -print \
| \
@ -208,6 +209,7 @@ install-manual: DIR=$(BUILD_DIR)/build-doc
install-manual: DH_OPTIONS = -p$(PACKAGE_NAME)
install-manual: $(STAMPS_DIR)/build-doc
dh_prep
set -o pipefail; \
find $(DIR)/Documentation/DocBook/man/ -name '*.9' | xargs dh_installman
+$(MAKE_SELF) install-base GENCONTROL_ARGS='$(call DEFINE_MULTIARCH,foreign)'
@ -229,13 +231,12 @@ install-headers_$(ARCH)_$(FEATURESET): $(STAMPS_DIR)/source_$(FEATURESET)
dh_testroot
dh_prep
set -o pipefail; \
cd $(SOURCE_DIR); \
( \
echo Makefile; \
find arch/$(KERNEL_ARCH) -maxdepth 1 -name 'Makefile*' -print; \
find arch/$(KERNEL_ARCH) -name 'module.lds' -print; \
find arch/$(KERNEL_ARCH)/Kbuild.platforms -print; \
find arch/$(KERNEL_ARCH) -name 'Platform' -print; \
find arch/$(KERNEL_ARCH) \( -name 'module.lds' -o -name 'Kbuild.platforms' -o -name 'Platform' \) -print; \
find $$(find arch/$(KERNEL_ARCH) \( -name include -o -name scripts \) -type d -print) -print; \
find include -print; \
) \
@ -358,6 +359,7 @@ install-image_$(ARCH)_$(FEATURESET)_$(FLAVOUR)_plain:
ifeq ($(MODULES),True)
+$(MAKE_CLEAN) -C $(DIR) modules_install DEPMOD='$(CURDIR)/debian/bin/no-depmod' INSTALL_MOD_PATH='$(CURDIR)'/$(PACKAGE_DIR) INSTALL_MOD_STRIP=1
ifeq ($(DEBUG),True)
set -o pipefail; \
find $(PACKAGE_DIR) -name '*.ko' | sed 's|$(PACKAGE_DIR)/lib/modules/$(REAL_VERSION)/kernel/||' | while read module ; do \
objcopy --add-gnu-debuglink=$(DIR)/$$module $(PACKAGE_DIR)/lib/modules/$(REAL_VERSION)/kernel/$$module || exit; \
done