From: Greg Kroah-Hartman Date: Fri, 22 Feb 2008 23:09:21 +0000 (-0800) Subject: .23 patches added X-Git-Tag: v2.6.22.19~8 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=ba34d6e8ddaa271df8311e8f11ef1fe27a4e4e1a;p=thirdparty%2Fkernel%2Fstable-queue.git .23 patches added --- diff --git a/queue-2.6.23/be-more-robust-about-bad-arguments-in-get_user_pages.patch b/queue-2.6.23/be-more-robust-about-bad-arguments-in-get_user_pages.patch new file mode 100644 index 00000000000..4f72d716e1a --- /dev/null +++ b/queue-2.6.23/be-more-robust-about-bad-arguments-in-get_user_pages.patch @@ -0,0 +1,47 @@ +From 900cf086fd2fbad07f72f4575449e0d0958f860f Mon Sep 17 00:00:00 2001 +From: Jonathan Corbet +Date: Mon, 11 Feb 2008 16:17:33 -0700 +Subject: [PATCH] Be more robust about bad arguments in get_user_pages() + +From: Jonathan Corbet + +patch 900cf086fd2fbad07f72f4575449e0d0958f860f in mainline. + +So I spent a while pounding my head against my monitor trying to figure +out the vmsplice() vulnerability - how could a failure to check for +*read* access turn into a root exploit? It turns out that it's a buffer +overflow problem which is made easy by the way get_user_pages() is +coded. + +In particular, "len" is a signed int, and it is only checked at the +*end* of a do {} while() loop. So, if it is passed in as zero, the loop +will execute once and decrement len to -1. At that point, the loop will +proceed until the next invalid address is found; in the process, it will +likely overflow the pages array passed in to get_user_pages(). + +I think that, if get_user_pages() has been asked to grab zero pages, +that's what it should do. Thus this patch; it is, among other things, +enough to block the (already fixed) root exploit and any others which +might be lurking in similar code. I also think that the number of pages +should be unsigned, but changing the prototype of this function probably +requires some more careful review. + +Signed-off-by: Jonathan Corbet +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + mm/memory.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/mm/memory.c ++++ b/mm/memory.c +@@ -981,6 +981,8 @@ int get_user_pages(struct task_struct *t + int i; + unsigned int vm_flags; + ++ if (len <= 0) ++ return 0; + /* + * Require read or write permissions. + * If 'force' is set, we only require the "MAY" flags. diff --git a/queue-2.6.23/disable-g5-nap-mode-during-smu-commands-on-u3.patch b/queue-2.6.23/disable-g5-nap-mode-during-smu-commands-on-u3.patch new file mode 100644 index 00000000000..b5f9f9df45d --- /dev/null +++ b/queue-2.6.23/disable-g5-nap-mode-during-smu-commands-on-u3.patch @@ -0,0 +1,144 @@ +From 592a607bbc053bc6f614a0e619326009f4b3829e Mon Sep 17 00:00:00 2001 +From: Benjamin Herrenschmidt +Date: Thu, 7 Feb 2008 14:29:43 +1100 +Subject: [PATCH] [POWERPC] Disable G5 NAP mode during SMU commands on U3 + +From: Benjamin Herrenschmidt + +patch 592a607bbc053bc6f614a0e619326009f4b3829e in mainline. + +It appears that with the U3 northbridge, if the processor is in NAP +mode the whole time while waiting for an SMU command to complete, +then the SMU will fail. It could be related to the weird backward +mechanism the SMU uses to get to system memory via i2c to the +northbridge that doesn't operate properly when the said bridge is +in napping along with the CPU. That is on U3 at least, U4 doesn't +seem to be affected. + +This didn't show before NO_HZ as the timer wakeup was enough to make +it work it seems, but that is no longer the case. + +This fixes it by disabling NAP mode on those machines while +an SMU command is in flight. + +Signed-off-by: Benjamin Herrenschmidt +Signed-off-by: Paul Mackerras +Signed-off-by: Greg Kroah-Hartman + +--- + arch/powerpc/platforms/powermac/feature.c | 11 ++++++++++- + drivers/macintosh/smu.c | 25 ++++++++++++++++++++++++- + include/asm-powerpc/pmac_feature.h | 8 ++++++++ + 3 files changed, 42 insertions(+), 2 deletions(-) + +--- a/arch/powerpc/platforms/powermac/feature.c ++++ b/arch/powerpc/platforms/powermac/feature.c +@@ -2565,6 +2565,8 @@ static void __init probe_uninorth(void) + + /* Locate core99 Uni-N */ + uninorth_node = of_find_node_by_name(NULL, "uni-n"); ++ uninorth_maj = 1; ++ + /* Locate G5 u3 */ + if (uninorth_node == NULL) { + uninorth_node = of_find_node_by_name(NULL, "u3"); +@@ -2575,8 +2577,10 @@ static void __init probe_uninorth(void) + uninorth_node = of_find_node_by_name(NULL, "u4"); + uninorth_maj = 4; + } +- if (uninorth_node == NULL) ++ if (uninorth_node == NULL) { ++ uninorth_maj = 0; + return; ++ } + + addrp = of_get_property(uninorth_node, "reg", NULL); + if (addrp == NULL) +@@ -3029,3 +3033,8 @@ void pmac_resume_agp_for_card(struct pci + pmac_agp_resume(pmac_agp_bridge); + } + EXPORT_SYMBOL(pmac_resume_agp_for_card); ++ ++int pmac_get_uninorth_variant(void) ++{ ++ return uninorth_maj; ++} +--- a/drivers/macintosh/smu.c ++++ b/drivers/macintosh/smu.c +@@ -85,6 +85,7 @@ struct smu_device { + u32 cmd_buf_abs; /* command buffer absolute */ + struct list_head cmd_list; + struct smu_cmd *cmd_cur; /* pending command */ ++ int broken_nap; + struct list_head cmd_i2c_list; + struct smu_i2c_cmd *cmd_i2c_cur; /* pending i2c command */ + struct timer_list i2c_timer; +@@ -135,6 +136,19 @@ static void smu_start_cmd(void) + fend = faddr + smu->cmd_buf->length + 2; + flush_inval_dcache_range(faddr, fend); + ++ ++ /* We also disable NAP mode for the duration of the command ++ * on U3 based machines. ++ * This is slightly racy as it can be written back to 1 by a sysctl ++ * but that never happens in practice. There seem to be an issue with ++ * U3 based machines such as the iMac G5 where napping for the ++ * whole duration of the command prevents the SMU from fetching it ++ * from memory. This might be related to the strange i2c based ++ * mechanism the SMU uses to access memory. ++ */ ++ if (smu->broken_nap) ++ powersave_nap = 0; ++ + /* This isn't exactly a DMA mapping here, I suspect + * the SMU is actually communicating with us via i2c to the + * northbridge or the CPU to access RAM. +@@ -211,6 +225,10 @@ static irqreturn_t smu_db_intr(int irq, + misc = cmd->misc; + mb(); + cmd->status = rc; ++ ++ /* Re-enable NAP mode */ ++ if (smu->broken_nap) ++ powersave_nap = 1; + bail: + /* Start next command if any */ + smu_start_cmd(); +@@ -461,7 +479,7 @@ int __init smu_init (void) + if (np == NULL) + return -ENODEV; + +- printk(KERN_INFO "SMU driver %s %s\n", VERSION, AUTHOR); ++ printk(KERN_INFO "SMU: Driver %s %s\n", VERSION, AUTHOR); + + if (smu_cmdbuf_abs == 0) { + printk(KERN_ERR "SMU: Command buffer not allocated !\n"); +@@ -533,6 +551,11 @@ int __init smu_init (void) + goto fail; + } + ++ /* U3 has an issue with NAP mode when issuing SMU commands */ ++ smu->broken_nap = pmac_get_uninorth_variant() < 4; ++ if (smu->broken_nap) ++ printk(KERN_INFO "SMU: using NAP mode workaround\n"); ++ + sys_ctrler = SYS_CTRLER_SMU; + return 0; + +--- a/include/asm-powerpc/pmac_feature.h ++++ b/include/asm-powerpc/pmac_feature.h +@@ -392,6 +392,14 @@ extern u32 __iomem *uninorth_base; + #define UN_BIS(r,v) (UN_OUT((r), UN_IN(r) | (v))) + #define UN_BIC(r,v) (UN_OUT((r), UN_IN(r) & ~(v))) + ++/* Uninorth variant: ++ * ++ * 0 = not uninorth ++ * 1 = U1.x or U2.x ++ * 3 = U3 ++ * 4 = U4 ++ */ ++extern int pmac_get_uninorth_variant(void); + + #endif /* __ASM_POWERPC_PMAC_FEATURE_H */ + #endif /* __KERNEL__ */ diff --git a/queue-2.6.23/genirq-do-not-leave-interupts-enabled-on-free_irq.patch b/queue-2.6.23/genirq-do-not-leave-interupts-enabled-on-free_irq.patch new file mode 100644 index 00000000000..958e6f0ef2c --- /dev/null +++ b/queue-2.6.23/genirq-do-not-leave-interupts-enabled-on-free_irq.patch @@ -0,0 +1,76 @@ +From stable-bounces@linux.kernel.org Tue Feb 19 15:29:28 2008 +From: Thomas Gleixner +Date: Wed, 20 Feb 2008 00:29:02 +0100 (CET) +Subject: genirq: do not leave interupts enabled on free_irq +To: Stable Team +Message-ID: + +From: Thomas Gleixner + +commit 89d694b9dbe769ca1004e01db0ca43964806a611 + +The default_disable() function was changed in commit: + + 76d2160147f43f982dfe881404cfde9fd0a9da21 + genirq: do not mask interrupts by default + +It removed the mask function in favour of the default delayed +interrupt disabling. Unfortunately this also broke the shutdown in +free_irq() when the last handler is removed from the interrupt for +those architectures which rely on the default implementations. Now we +can end up with a enabled interrupt line after the last handler was +removed, which can result in spurious interrupts. + +Fix this by adding a default_shutdown function, which is only +installed, when the irqchip implementation does provide neither a +shutdown nor a disable function. + + +Pointed-out-by: Michael Hennerich +Signed-off-by: Thomas Gleixner +Acked-by: Ingo Molnar +Tested-by: Michael Hennerich +Signed-off-by: Greg Kroah-Hartman + + +--- + kernel/irq/chip.c | 20 +++++++++++++++++++- + 1 file changed, 19 insertions(+), 1 deletion(-) + +--- a/kernel/irq/chip.c ++++ b/kernel/irq/chip.c +@@ -246,6 +246,17 @@ static unsigned int default_startup(unsi + } + + /* ++ * default shutdown function ++ */ ++static void default_shutdown(unsigned int irq) ++{ ++ struct irq_desc *desc = irq_desc + irq; ++ ++ desc->chip->mask(irq); ++ desc->status |= IRQ_MASKED; ++} ++ ++/* + * Fixup enable/disable function pointers + */ + void irq_chip_set_defaults(struct irq_chip *chip) +@@ -256,8 +267,15 @@ void irq_chip_set_defaults(struct irq_ch + chip->disable = default_disable; + if (!chip->startup) + chip->startup = default_startup; ++ /* ++ * We use chip->disable, when the user provided its own. When ++ * we have default_disable set for chip->disable, then we need ++ * to use default_shutdown, otherwise the irq line is not ++ * disabled on free_irq(): ++ */ + if (!chip->shutdown) +- chip->shutdown = chip->disable; ++ chip->shutdown = chip->disable != default_disable ? ++ chip->disable : default_shutdown; + if (!chip->name) + chip->name = chip->typename; + if (!chip->end) diff --git a/queue-2.6.23/hrtimer-check-relative-timeouts-for-overflow.patch b/queue-2.6.23/hrtimer-check-relative-timeouts-for-overflow.patch new file mode 100644 index 00000000000..288da16157c --- /dev/null +++ b/queue-2.6.23/hrtimer-check-relative-timeouts-for-overflow.patch @@ -0,0 +1,154 @@ +From stable-bounces@linux.kernel.org Tue Feb 19 16:03:26 2008 +From: Thomas Gleixner +Date: Wed, 20 Feb 2008 01:03:00 +0100 (CET) +Subject: hrtimer: check relative timeouts for overflow +To: Stable Team +Message-ID: + +From: Thomas Gleixner + +commit: 5a7780e725d1bb4c3094fcc12f1c5c5faea1e988 + +Various user space callers ask for relative timeouts. While we fixed +that overflow issue in hrtimer_start(), the sites which convert +relative user space values to absolute timeouts themself were uncovered. + +Instead of putting overflow checks into each place add a function +which does the sanity checking and convert all affected callers to use +it. + +Thanks to Frans Pop, who reported the problem and tested the fixes. + +Signed-off-by: Thomas Gleixner +Acked-by: Ingo Molnar +Tested-by: Frans Pop +Signed-off-by: Greg Kroah-Hartman + + +--- + include/linux/ktime.h | 2 ++ + kernel/futex.c | 2 +- + kernel/futex_compat.c | 2 +- + kernel/hrtimer.c | 38 +++++++++++++++++++++----------------- + kernel/posix-timers.c | 8 +++++--- + 5 files changed, 30 insertions(+), 22 deletions(-) + +--- a/include/linux/ktime.h ++++ b/include/linux/ktime.h +@@ -289,6 +289,8 @@ static inline ktime_t ktime_add_us(const + return ktime_add_ns(kt, usec * 1000); + } + ++extern ktime_t ktime_add_safe(const ktime_t lhs, const ktime_t rhs); ++ + /* + * The resolution of the clocks. The resolution value is returned in + * the clock_getres() system call to give application programmers an +--- a/kernel/futex.c ++++ b/kernel/futex.c +@@ -2063,7 +2063,7 @@ asmlinkage long sys_futex(u32 __user *ua + + t = timespec_to_ktime(ts); + if (cmd == FUTEX_WAIT) +- t = ktime_add(ktime_get(), t); ++ t = ktime_add_safe(ktime_get(), t); + tp = &t; + } + /* +--- a/kernel/futex_compat.c ++++ b/kernel/futex_compat.c +@@ -175,7 +175,7 @@ asmlinkage long compat_sys_futex(u32 __u + + t = timespec_to_ktime(ts); + if (cmd == FUTEX_WAIT) +- t = ktime_add(ktime_get(), t); ++ t = ktime_add_safe(ktime_get(), t); + tp = &t; + } + if (cmd == FUTEX_REQUEUE || cmd == FUTEX_CMP_REQUEUE) +--- a/kernel/hrtimer.c ++++ b/kernel/hrtimer.c +@@ -301,6 +301,24 @@ unsigned long ktime_divns(const ktime_t + } + #endif /* BITS_PER_LONG >= 64 */ + ++/* ++ * Add two ktime values and do a safety check for overflow: ++ */ ++ ++ktime_t ktime_add_safe(const ktime_t lhs, const ktime_t rhs) ++{ ++ ktime_t res = ktime_add(lhs, rhs); ++ ++ /* ++ * We use KTIME_SEC_MAX here, the maximum timeout which we can ++ * return to user space in a timespec: ++ */ ++ if (res.tv64 < 0 || res.tv64 < lhs.tv64 || res.tv64 < rhs.tv64) ++ res = ktime_set(KTIME_SEC_MAX, 0); ++ ++ return res; ++} ++ + /* High resolution timer related functions */ + #ifdef CONFIG_HIGH_RES_TIMERS + +@@ -658,13 +676,7 @@ hrtimer_forward(struct hrtimer *timer, k + */ + orun++; + } +- timer->expires = ktime_add(timer->expires, interval); +- /* +- * Make sure, that the result did not wrap with a very large +- * interval. +- */ +- if (timer->expires.tv64 < 0) +- timer->expires = ktime_set(KTIME_SEC_MAX, 0); ++ timer->expires = ktime_add_safe(timer->expires, interval); + + return orun; + } +@@ -815,7 +827,7 @@ hrtimer_start(struct hrtimer *timer, kti + new_base = switch_hrtimer_base(timer, base); + + if (mode == HRTIMER_MODE_REL) { +- tim = ktime_add(tim, new_base->get_time()); ++ tim = ktime_add_safe(tim, new_base->get_time()); + /* + * CONFIG_TIME_LOW_RES is a temporary way for architectures + * to signal that they simply return xtime in +@@ -824,16 +836,8 @@ hrtimer_start(struct hrtimer *timer, kti + * timeouts. This will go away with the GTOD framework. + */ + #ifdef CONFIG_TIME_LOW_RES +- tim = ktime_add(tim, base->resolution); ++ tim = ktime_add_safe(tim, base->resolution); + #endif +- /* +- * Careful here: User space might have asked for a +- * very long sleep, so the add above might result in a +- * negative number, which enqueues the timer in front +- * of the queue. +- */ +- if (tim.tv64 < 0) +- tim.tv64 = KTIME_MAX; + } + timer->expires = tim; + +--- a/kernel/posix-timers.c ++++ b/kernel/posix-timers.c +@@ -765,9 +765,11 @@ common_timer_set(struct k_itimer *timr, + /* SIGEV_NONE timers are not queued ! See common_timer_get */ + if (((timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE)) { + /* Setup correct expiry time for relative timers */ +- if (mode == HRTIMER_MODE_REL) +- timer->expires = ktime_add(timer->expires, +- timer->base->get_time()); ++ if (mode == HRTIMER_MODE_REL) { ++ timer->expires = ++ ktime_add_safe(timer->expires, ++ timer->base->get_time()); ++ } + return 0; + } + diff --git a/queue-2.6.23/series b/queue-2.6.23/series index 208cf470b63..3a2747b9496 100644 --- a/queue-2.6.23/series +++ b/queue-2.6.23/series @@ -1,3 +1,7 @@ scsi-sd-handle-bad-lba-in-sense-information.patch nfs-fix-a-potential-file-corruption-issue-when-writing.patch netfilter-nf_conntrack_tcp-conntrack-reopening-fix.patch +hrtimer-check-relative-timeouts-for-overflow.patch +genirq-do-not-leave-interupts-enabled-on-free_irq.patch +disable-g5-nap-mode-during-smu-commands-on-u3.patch +be-more-robust-about-bad-arguments-in-get_user_pages.patch