From e411b22225cc0a7467173cc72a772bbac007dccd Mon Sep 17 00:00:00 2001 From: Robert Buchholz Date: Wed, 10 Oct 2007 09:49:41 +0000 Subject: Debian 2.6.18 1-13etch4 security patches svn path=/patches/; revision=47 --- trunk/2.6.18/00000_README | 20 ++++ .../30037_amd64-zero-extend-32bit-ptrace-xen.patch | 50 +++++++++ ...0038_don-t-leak-nt-bit-into-next-task-xen.patch | 32 ++++++ .../2.6.18/30039_hugetlb-prio_tree-unit-fix.patch | 85 ++++++++++++++ trunk/2.6.18/30040_usb-pwc-disconnect-block.patch | 124 +++++++++++++++++++++ 5 files changed, 311 insertions(+) create mode 100644 trunk/2.6.18/30037_amd64-zero-extend-32bit-ptrace-xen.patch create mode 100644 trunk/2.6.18/30038_don-t-leak-nt-bit-into-next-task-xen.patch create mode 100644 trunk/2.6.18/30039_hugetlb-prio_tree-unit-fix.patch create mode 100644 trunk/2.6.18/30040_usb-pwc-disconnect-block.patch diff --git a/trunk/2.6.18/00000_README b/trunk/2.6.18/00000_README index e49351c..27868b4 100644 --- a/trunk/2.6.18/00000_README +++ b/trunk/2.6.18/00000_README @@ -186,6 +186,26 @@ Patches prevent incorrect permissions upon remount. See CVE-2007-4849 +30037_amd64-zero-extend-32bit-ptrace-xen.patch + [SECURITY] Zero extend all registers after ptrace in 32-bit entry path + (Xen). + See CVE-2007-4573 + +30038_don-t-leak-nt-bit-into-next-task-xen.patch + [SECURITY] Don't leak NT bit into next task (Xen). + See CVE-2006-5755 + +30039_hugetlb-prio_tree-unit-fix.patch + [SECURITY] Fix misconversion of hugetlb_vmtruncate_list to prio_tree + which could be used to trigger a BUG_ON() call in exit_mmap. + See CVE-2007-4133 + +30040_usb-pwc-disconnect-block.patch + [SECURITY] Fix issue with unplugging webcams that use the pwc driver. + If userspace still has the device open it can result, the driver would + wait for the device to close, blocking the USB subsystem. + See CVE-2007-5093 + 50001_make-install.patch Handle make install in a semi-sane way that plays nice with split domU/dom0 kernels. diff --git a/trunk/2.6.18/30037_amd64-zero-extend-32bit-ptrace-xen.patch b/trunk/2.6.18/30037_amd64-zero-extend-32bit-ptrace-xen.patch new file mode 100644 index 0000000..25e56d3 --- /dev/null +++ b/trunk/2.6.18/30037_amd64-zero-extend-32bit-ptrace-xen.patch @@ -0,0 +1,50 @@ +Adjusted to apply to Debian's 2.6.18 Xen + +--- linux-source-2.6.18.orig/arch/x86_64/ia32/ia32entry-xen.S 2006-09-19 21:42:06.000000000 -0600 ++++ linux-source-2.6.18/arch/x86_64/ia32/ia32entry-xen.S 2007-09-25 00:10:16.089100799 -0600 +@@ -38,6 +38,18 @@ + #define __sti sti + #endif + ++ .macro LOAD_ARGS32 offset ++ movl \offset(%rsp),%r11d ++ movl \offset+8(%rsp),%r10d ++ movl \offset+16(%rsp),%r9d ++ movl \offset+24(%rsp),%r8d ++ movl \offset+40(%rsp),%ecx ++ movl \offset+48(%rsp),%edx ++ movl \offset+56(%rsp),%esi ++ movl \offset+64(%rsp),%edi ++ movl \offset+72(%rsp),%eax ++ .endm ++ + .macro CFI_STARTPROC32 simple + CFI_STARTPROC \simple + CFI_UNDEFINED r8 +@@ -151,7 +163,7 @@ sysenter_tracesys: + movq $-ENOSYS,RAX(%rsp) /* really needed? */ + movq %rsp,%rdi /* &pt_regs -> arg1 */ + call syscall_trace_enter +- LOAD_ARGS ARGOFFSET /* reload args from stack in case ptrace changed it */ ++ LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */ + RESTORE_REST + movl %ebp, %ebp + /* no need to do an access_ok check here because rbp has been +@@ -253,7 +265,7 @@ cstar_tracesys: + movq $-ENOSYS,RAX(%rsp) /* really needed? */ + movq %rsp,%rdi /* &pt_regs -> arg1 */ + call syscall_trace_enter +- LOAD_ARGS ARGOFFSET /* reload args from stack in case ptrace changed it */ ++ LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */ + RESTORE_REST + movl RSP-ARGOFFSET(%rsp), %r8d + /* no need to do an access_ok check here because r8 has been +@@ -330,7 +342,7 @@ ia32_tracesys: + movq $-ENOSYS,RAX(%rsp) /* really needed? */ + movq %rsp,%rdi /* &pt_regs -> arg1 */ + call syscall_trace_enter +- LOAD_ARGS ARGOFFSET /* reload args from stack in case ptrace changed it */ ++ LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */ + RESTORE_REST + jmp ia32_do_syscall + END(ia32_syscall) diff --git a/trunk/2.6.18/30038_don-t-leak-nt-bit-into-next-task-xen.patch b/trunk/2.6.18/30038_don-t-leak-nt-bit-into-next-task-xen.patch new file mode 100644 index 0000000..8ee7bc0 --- /dev/null +++ b/trunk/2.6.18/30038_don-t-leak-nt-bit-into-next-task-xen.patch @@ -0,0 +1,32 @@ + +--- linux-2.6.18.6.orig/arch/x86_64/kernel/entry-xen.S ++++ linux-2.6.18.6/arch/x86_64/kernel/entry-xen.S +@@ -146,6 +146,10 @@ + /* rdi: prev */ + ENTRY(ret_from_fork) + CFI_DEFAULT_STACK ++ push kernel_eflags(%rip) ++ CFI_ADJUST_CFA_OFFSET 4 ++ popf # reset kernel eflags ++ CFI_ADJUST_CFA_OFFSET -4 + call schedule_tail + GET_THREAD_INFO(%rcx) + testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),threadinfo_flags(%rcx) +--- linux-2.6.18.6.orig/arch/x86_64/kernel/setup64-xen.c ++++ linux-2.6.18.6/arch/x86_64/kernel/setup64-xen.c +@@ -178,6 +178,8 @@ void __cpuinit check_efer(void) + } + } + ++unsigned long kernel_eflags; ++ + /* + * cpu_init() initializes state that is per-CPU. Some data is already + * initialized (naturally) in the bootstrap process, such as the GDT +@@ -290,4 +292,6 @@ void __cpuinit cpu_init (void) + set_debugreg(0UL, 7); + + fpu_init(); ++ ++ raw_local_save_flags(kernel_eflags); + } diff --git a/trunk/2.6.18/30039_hugetlb-prio_tree-unit-fix.patch b/trunk/2.6.18/30039_hugetlb-prio_tree-unit-fix.patch new file mode 100644 index 0000000..2b92bf0 --- /dev/null +++ b/trunk/2.6.18/30039_hugetlb-prio_tree-unit-fix.patch @@ -0,0 +1,85 @@ +From: Hugh Dickins +Date: Sat, 28 Oct 2006 17:38:43 +0000 (-0700) +Subject: [PATCH] hugetlb: fix prio_tree unit +X-Git-Tag: v2.6.19-rc4~50 +X-Git-Url: http://git.kernel.org/gitweb.cgi?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=856fc29505556cf263f3dcda2533cf3766c14ab6 + +[PATCH] hugetlb: fix prio_tree unit + +hugetlb_vmtruncate_list was misconverted to prio_tree: its prio_tree is in +units of PAGE_SIZE (PAGE_CACHE_SIZE) like any other, not HPAGE_SIZE (whereas +its radix_tree is kept in units of HPAGE_SIZE, otherwise slots would be +absurdly sparse). + +At first I thought the error benign, just calling __unmap_hugepage_range on +more vmas than necessary; but on 32-bit machines, when the prio_tree is +searched correctly, it happens to ensure the v_offset calculation won't +overflow. As it stood, when truncating at or beyond 4GB, it was liable to +discard pages COWed from lower offsets; or even to clear pmd entries of +preceding vmas, triggering exit_mmap's BUG_ON(nr_ptes). + +Signed-off-by: Hugh Dickins +Cc: Adam Litke +Cc: David Gibson +Cc: "Chen, Kenneth W" +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +--- + +diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c +index 0b23b96..0bea6a6 100644 +--- a/fs/hugetlbfs/inode.c ++++ b/fs/hugetlbfs/inode.c +@@ -271,26 +271,24 @@ static void hugetlbfs_drop_inode(struct inode *inode) + hugetlbfs_forget_inode(inode); + } + +-/* +- * h_pgoff is in HPAGE_SIZE units. +- * vma->vm_pgoff is in PAGE_SIZE units. +- */ + static inline void +-hugetlb_vmtruncate_list(struct prio_tree_root *root, unsigned long h_pgoff) ++hugetlb_vmtruncate_list(struct prio_tree_root *root, pgoff_t pgoff) + { + struct vm_area_struct *vma; + struct prio_tree_iter iter; + +- vma_prio_tree_foreach(vma, &iter, root, h_pgoff, ULONG_MAX) { +- unsigned long h_vm_pgoff; ++ vma_prio_tree_foreach(vma, &iter, root, pgoff, ULONG_MAX) { + unsigned long v_offset; + +- h_vm_pgoff = vma->vm_pgoff >> (HPAGE_SHIFT - PAGE_SHIFT); +- v_offset = (h_pgoff - h_vm_pgoff) << HPAGE_SHIFT; + /* +- * Is this VMA fully outside the truncation point? ++ * Can the expression below overflow on 32-bit arches? ++ * No, because the prio_tree returns us only those vmas ++ * which overlap the truncated area starting at pgoff, ++ * and no vma on a 32-bit arch can span beyond the 4GB. + */ +- if (h_vm_pgoff >= h_pgoff) ++ if (vma->vm_pgoff < pgoff) ++ v_offset = (pgoff - vma->vm_pgoff) << PAGE_SHIFT; ++ else + v_offset = 0; + + __unmap_hugepage_range(vma, +@@ -303,14 +301,14 @@ hugetlb_vmtruncate_list(struct prio_tree_root *root, unsigned long h_pgoff) + */ + static int hugetlb_vmtruncate(struct inode *inode, loff_t offset) + { +- unsigned long pgoff; ++ pgoff_t pgoff; + struct address_space *mapping = inode->i_mapping; + + if (offset > inode->i_size) + return -EINVAL; + + BUG_ON(offset & ~HPAGE_MASK); +- pgoff = offset >> HPAGE_SHIFT; ++ pgoff = offset >> PAGE_SHIFT; + + inode->i_size = offset; + spin_lock(&mapping->i_mmap_lock); diff --git a/trunk/2.6.18/30040_usb-pwc-disconnect-block.patch b/trunk/2.6.18/30040_usb-pwc-disconnect-block.patch new file mode 100644 index 0000000..679c7bc --- /dev/null +++ b/trunk/2.6.18/30040_usb-pwc-disconnect-block.patch @@ -0,0 +1,124 @@ +From: Oliver Neukum +Date: Tue, 21 Aug 2007 05:10:42 +0000 (+0200) +Subject: USB: fix DoS in pwc USB video driver +X-Git-Tag: v2.6.23-rc4~29^2~8 +X-Git-Url: http://git.kernel.org/gitweb.cgi?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=85237f202d46d55c1bffe0c5b1aa3ddc0f1dce4d + +USB: fix DoS in pwc USB video driver + +the pwc driver has a disconnect method that waits for user space to +close the device. This opens up an opportunity for a DoS attack, +blocking the USB subsystem and making khubd's task busy wait in +kernel space. This patch shifts freeing resources to close if an opened +device is disconnected. + +Signed-off-by: Oliver Neukum +CC: stable +Signed-off-by: Greg Kroah-Hartman +--- + +Backported to Debian's 2.6.18 by dann frazier + +diff -urpN linux-source-2.6.18.orig/drivers/media/video/pwc/pwc-if.c linux-source-2.6.18/drivers/media/video/pwc/pwc-if.c +--- linux-source-2.6.18.orig/drivers/media/video/pwc/pwc-if.c 2006-09-19 21:42:06.000000000 -0600 ++++ linux-source-2.6.18/drivers/media/video/pwc/pwc-if.c 2007-10-02 10:23:54.471131296 -0600 +@@ -1186,12 +1186,19 @@ static int pwc_video_open(struct inode * + return 0; + } + ++ ++static void pwc_cleanup(struct pwc_device *pdev) ++{ ++ pwc_remove_sysfs_files(pdev->vdev); ++ video_unregister_device(pdev->vdev); ++} ++ + /* Note that all cleanup is done in the reverse order as in _open */ + static int pwc_video_close(struct inode *inode, struct file *file) + { + struct video_device *vdev = file->private_data; + struct pwc_device *pdev; +- int i; ++ int i, hint; + + PWC_DEBUG_OPEN(">> video_close called(vdev = 0x%p).\n", vdev); + +@@ -1214,8 +1221,9 @@ static int pwc_video_close(struct inode + pwc_isoc_cleanup(pdev); + pwc_free_buffers(pdev); + ++ lock_kernel(); + /* Turn off LEDS and power down camera, but only when not unplugged */ +- if (pdev->error_status != EPIPE) { ++ if (!pdev->unplugged) { + /* Turn LEDs off */ + if (pwc_set_leds(pdev, 0, 0) < 0) + PWC_DEBUG_MODULE("Failed to set LED on/off time.\n"); +@@ -1224,9 +1232,19 @@ static int pwc_video_close(struct inode + if (i < 0) + PWC_ERROR("Failed to power down camera (%d)\n", i); + } ++ pdev->vopen--; ++ PWC_DEBUG_OPEN("<< video_close() vopen=%d\n", i); ++ } else { ++ pwc_cleanup(pdev); ++ /* Free memory (don't set pdev to 0 just yet) */ ++ kfree(pdev); ++ /* search device_hint[] table if we occupy a slot, by any chance */ ++ for (hint = 0; hint < MAX_DEV_HINTS; hint++) ++ if (device_hint[hint].pdev == pdev) ++ device_hint[hint].pdev = NULL; + } +- pdev->vopen--; +- PWC_DEBUG_OPEN("<< video_close() vopen=%d\n", pdev->vopen); ++ unlock_kernel(); ++ + return 0; + } + +@@ -1763,21 +1781,21 @@ static void usb_pwc_disconnect(struct us + /* Alert waiting processes */ + wake_up_interruptible(&pdev->frameq); + /* Wait until device is closed */ +- while (pdev->vopen) +- schedule(); +- /* Device is now closed, so we can safely unregister it */ +- PWC_DEBUG_PROBE("Unregistering video device in disconnect().\n"); +- pwc_remove_sysfs_files(pdev->vdev); +- video_unregister_device(pdev->vdev); +- +- /* Free memory (don't set pdev to 0 just yet) */ +- kfree(pdev); ++ if(pdev->vopen) { ++ pdev->unplugged = 1; ++ } else { ++ /* Device is closed, so we can safely unregister it */ ++ PWC_DEBUG_PROBE("Unregistering video device in disconnect().\n"); ++ pwc_cleanup(pdev); ++ /* Free memory (don't set pdev to 0 just yet) */ ++ kfree(pdev); + + disconnect_out: +- /* search device_hint[] table if we occupy a slot, by any chance */ +- for (hint = 0; hint < MAX_DEV_HINTS; hint++) +- if (device_hint[hint].pdev == pdev) +- device_hint[hint].pdev = NULL; ++ /* search device_hint[] table if we occupy a slot, by any chance */ ++ for (hint = 0; hint < MAX_DEV_HINTS; hint++) ++ if (device_hint[hint].pdev == pdev) ++ device_hint[hint].pdev = NULL; ++ } + + unlock_kernel(); + } +diff -urpN linux-source-2.6.18.orig/drivers/media/video/pwc/pwc.h linux-source-2.6.18/drivers/media/video/pwc/pwc.h +--- linux-source-2.6.18.orig/drivers/media/video/pwc/pwc.h 2006-09-19 21:42:06.000000000 -0600 ++++ linux-source-2.6.18/drivers/media/video/pwc/pwc.h 2007-10-02 10:23:54.471131296 -0600 +@@ -198,6 +198,7 @@ struct pwc_device + char vsnapshot; /* snapshot mode */ + char vsync; /* used by isoc handler */ + char vmirror; /* for ToUCaM series */ ++ char unplugged; + + int cmd_len; + unsigned char cmd_buf[13]; -- cgit v1.2.3-65-gdbad