From: Greg Kroah-Hartman Date: Sat, 4 Dec 2010 00:00:17 +0000 (-0800) Subject: .36 patches X-Git-Tag: v2.6.27.57~57 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b5d7ff57e8a20d5e1c0ec17a4a8f2fd25ce19e72;p=thirdparty%2Fkernel%2Fstable-queue.git .36 patches --- diff --git a/queue-2.6.36/intel-gtt-fix-gtt_total_entries-detection.patch b/queue-2.6.36/intel-gtt-fix-gtt_total_entries-detection.patch deleted file mode 100644 index b088d904e98..00000000000 --- a/queue-2.6.36/intel-gtt-fix-gtt_total_entries-detection.patch +++ /dev/null @@ -1,128 +0,0 @@ -From e5e408fc94595aab897f613b6f4e2f5b36870a6f Mon Sep 17 00:00:00 2001 -From: Daniel Vetter -Date: Sat, 28 Aug 2010 11:04:32 +0200 -Subject: intel-gtt: fix gtt_total_entries detection - -From: Daniel Vetter - -commit e5e408fc94595aab897f613b6f4e2f5b36870a6f upstream. - -In commit f1befe71 Chris Wilson added some code to clear the full gtt -on g33/pineview instead of just the mappable part. The code looks like -it was copy-pasted from agp/intel-gtt.c, at least an identical piece -of code is still there (in intel_i830_init_gtt_entries). This lead to -a regression in 2.6.35 which was supposedly fixed in commit e7b96f28 - -Now this commit makes absolutely no sense to me. It seems to be -slightly confused about chipset generations - it references docs for -4th gen but the regression concerns 3rd gen g33. Luckily the the g33 -gmch docs are available with the GMCH Graphics Control pci config -register definitions. The other (bigger problem) is that the new -check in there uses the i830 stolen mem bits (.5M, 1M or 8M of stolen -mem). They are different since the i855GM. - -The most likely case is that it hits the 512M fallback, which was -probably the right thing for the boxes this was tested on. - -So the original approach by Chris Wilson seems to be wrong and the -current code is definitely wrong. There is a third approach by Jesse -Barnes from his RFC patch "Who wants a bigger GTT mapping range?" -where he simply shoves g33 in the same clause like later chipset -generations. - -I've asked him and Jesse confirmed that this should work. So implement -it. - -Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=16891$ -Tested-by: Anisse Astier -Signed-off-by: Daniel Vetter -Signed-off-by: Chris Wilson -Signed-off-by: Greg Kroah-Hartman - -diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c -index 56bcf27..3b84d84 100644 ---- a/drivers/char/agp/intel-gtt.c -+++ b/drivers/char/agp/intel-gtt.c -@@ -699,71 +699,43 @@ static unsigned int intel_gtt_stolen_entries(void) - static unsigned int intel_gtt_total_entries(void) - { - int size; -- u16 gmch_ctrl; - -- if (IS_I965) { -+ if (IS_G33 || IS_I965 || IS_G4X) { - u32 pgetbl_ctl; - pgetbl_ctl = readl(intel_private.registers+I810_PGETBL_CTL); - -- /* The 965 has a field telling us the size of the GTT, -- * which may be larger than what is necessary to map the -- * aperture. -- */ - switch (pgetbl_ctl & I965_PGETBL_SIZE_MASK) { - case I965_PGETBL_SIZE_128KB: -- size = 128; -+ size = KB(128); - break; - case I965_PGETBL_SIZE_256KB: -- size = 256; -+ size = KB(256); - break; - case I965_PGETBL_SIZE_512KB: -- size = 512; -+ size = KB(512); - break; - case I965_PGETBL_SIZE_1MB: -- size = 1024; -+ size = KB(1024); - break; - case I965_PGETBL_SIZE_2MB: -- size = 2048; -+ size = KB(2048); - break; - case I965_PGETBL_SIZE_1_5MB: -- size = 1024 + 512; -+ size = KB(1024 + 512); - break; - default: - dev_info(&intel_private.pcidev->dev, - "unknown page table size, assuming 512KB\n"); -- size = 512; -- } -- size += 4; /* add in BIOS popup space */ -- } else if (IS_G33 && !IS_PINEVIEW) { -- /* G33's GTT size defined in gmch_ctrl */ -- switch (gmch_ctrl & G33_PGETBL_SIZE_MASK) { -- case G33_PGETBL_SIZE_1M: -- size = 1024; -- break; -- case G33_PGETBL_SIZE_2M: -- size = 2048; -- break; -- default: -- dev_info(&intel_private.bridge_dev->dev, -- "unknown page table size 0x%x, assuming 512KB\n", -- (gmch_ctrl & G33_PGETBL_SIZE_MASK)); -- size = 512; -+ size = KB(512); - } -- size += 4; -- } else if (IS_G4X || IS_PINEVIEW) { -- /* On 4 series hardware, GTT stolen is separate from graphics -- * stolen, ignore it in stolen gtt entries counting. However, -- * 4KB of the stolen memory doesn't get mapped to the GTT. -- */ -- size = 4; -+ -+ return size/4; - } else { - /* On previous hardware, the GTT size was just what was - * required to map the aperture. - */ -- size = agp_bridge->driver->fetch_size() + 4; -+ return intel_private.base.gtt_mappable_entries; - } -- -- return size/KB(4); - } - #endif - diff --git a/queue-2.6.36/series b/queue-2.6.36/series index cf20172a751..fcc39826cd4 100644 --- a/queue-2.6.36/series +++ b/queue-2.6.36/series @@ -134,5 +134,6 @@ md-fix-regression-with-raid1-arrays-without-persistent-metadata.patch md-raid1-really-fix-recovery-looping-when-single-good-device-fails.patch md-fix-return-value-of-rdev_size_change.patch alsa-hda-use-bios-auto-parsing-instead-of-existing-model-quirk-for-medion-md2.patch -intel-gtt-fix-gtt_total_entries-detection.patch -sgi-xp-incoming-xpc-channel-messages-can-come-in-after-the-channel-s-partition-structures-have-been-torn-down.patch +tty-prevent-dos-in-the-flush_to_ldisc.patch +tty-restore-tty_ldisc_wait_idle.patch +tty_ldisc-fix-bug-on-hangup.patch diff --git a/queue-2.6.36/sgi-xp-incoming-xpc-channel-messages-can-come-in-after-the-channel-s-partition-structures-have-been-torn-down.patch b/queue-2.6.36/sgi-xp-incoming-xpc-channel-messages-can-come-in-after-the-channel-s-partition-structures-have-been-torn-down.patch deleted file mode 100644 index a81e5d16d28..00000000000 --- a/queue-2.6.36/sgi-xp-incoming-xpc-channel-messages-can-come-in-after-the-channel-s-partition-structures-have-been-torn-down.patch +++ /dev/null @@ -1,93 +0,0 @@ -From 09358972bff5ce99de496bbba97c85d417b3c054 Mon Sep 17 00:00:00 2001 -From: Robin Holt -Date: Tue, 26 Oct 2010 14:21:15 -0700 -Subject: sgi-xp: incoming XPC channel messages can come in after the channel's partition structures have been torn down - -From: Robin Holt - -commit 09358972bff5ce99de496bbba97c85d417b3c054 upstream. - -Under some workloads, some channel messages have been observed being -delayed on the sending side past the point where the receiving side has -been able to tear down its partition structures. - -This condition is already detected in xpc_handle_activate_IRQ_uv(), but -that information is not given to xpc_handle_activate_mq_msg_uv(). As a -result, xpc_handle_activate_mq_msg_uv() assumes the structures still exist -and references them, causing a NULL-pointer deref. - -Signed-off-by: Robin Holt -Signed-off-by: Andrew Morton -Signed-off-by: Linus Torvalds -Signed-off-by: Greg Kroah-Hartman - -diff --git a/drivers/misc/sgi-xp/xpc_uv.c b/drivers/misc/sgi-xp/xpc_uv.c -index 1f59ee2..17bbacb 100644 ---- a/drivers/misc/sgi-xp/xpc_uv.c -+++ b/drivers/misc/sgi-xp/xpc_uv.c -@@ -417,6 +417,7 @@ xpc_process_activate_IRQ_rcvd_uv(void) - static void - xpc_handle_activate_mq_msg_uv(struct xpc_partition *part, - struct xpc_activate_mq_msghdr_uv *msg_hdr, -+ int part_setup, - int *wakeup_hb_checker) - { - unsigned long irq_flags; -@@ -481,6 +482,9 @@ xpc_handle_activate_mq_msg_uv(struct xpc_partition *part, - case XPC_ACTIVATE_MQ_MSG_CHCTL_CLOSEREQUEST_UV: { - struct xpc_activate_mq_msg_chctl_closerequest_uv *msg; - -+ if (!part_setup) -+ break; -+ - msg = container_of(msg_hdr, struct - xpc_activate_mq_msg_chctl_closerequest_uv, - hdr); -@@ -497,6 +501,9 @@ xpc_handle_activate_mq_msg_uv(struct xpc_partition *part, - case XPC_ACTIVATE_MQ_MSG_CHCTL_CLOSEREPLY_UV: { - struct xpc_activate_mq_msg_chctl_closereply_uv *msg; - -+ if (!part_setup) -+ break; -+ - msg = container_of(msg_hdr, struct - xpc_activate_mq_msg_chctl_closereply_uv, - hdr); -@@ -511,6 +518,9 @@ xpc_handle_activate_mq_msg_uv(struct xpc_partition *part, - case XPC_ACTIVATE_MQ_MSG_CHCTL_OPENREQUEST_UV: { - struct xpc_activate_mq_msg_chctl_openrequest_uv *msg; - -+ if (!part_setup) -+ break; -+ - msg = container_of(msg_hdr, struct - xpc_activate_mq_msg_chctl_openrequest_uv, - hdr); -@@ -528,6 +538,9 @@ xpc_handle_activate_mq_msg_uv(struct xpc_partition *part, - case XPC_ACTIVATE_MQ_MSG_CHCTL_OPENREPLY_UV: { - struct xpc_activate_mq_msg_chctl_openreply_uv *msg; - -+ if (!part_setup) -+ break; -+ - msg = container_of(msg_hdr, struct - xpc_activate_mq_msg_chctl_openreply_uv, hdr); - args = &part->remote_openclose_args[msg->ch_number]; -@@ -545,6 +558,9 @@ xpc_handle_activate_mq_msg_uv(struct xpc_partition *part, - case XPC_ACTIVATE_MQ_MSG_CHCTL_OPENCOMPLETE_UV: { - struct xpc_activate_mq_msg_chctl_opencomplete_uv *msg; - -+ if (!part_setup) -+ break; -+ - msg = container_of(msg_hdr, struct - xpc_activate_mq_msg_chctl_opencomplete_uv, hdr); - spin_lock_irqsave(&part->chctl_lock, irq_flags); -@@ -621,6 +637,7 @@ xpc_handle_activate_IRQ_uv(int irq, void *dev_id) - - part_referenced = xpc_part_ref(part); - xpc_handle_activate_mq_msg_uv(part, msg_hdr, -+ part_referenced, - &wakeup_hb_checker); - if (part_referenced) - xpc_part_deref(part); diff --git a/queue-2.6.36/tty-prevent-dos-in-the-flush_to_ldisc.patch b/queue-2.6.36/tty-prevent-dos-in-the-flush_to_ldisc.patch new file mode 100644 index 00000000000..a05acb00502 --- /dev/null +++ b/queue-2.6.36/tty-prevent-dos-in-the-flush_to_ldisc.patch @@ -0,0 +1,107 @@ +From e045fec48970df84647a47930fcf7a22ff7229c0 Mon Sep 17 00:00:00 2001 +From: Jiri Olsa +Date: Mon, 8 Nov 2010 19:01:47 +0100 +Subject: tty: prevent DOS in the flush_to_ldisc + +From: Jiri Olsa + +commit e045fec48970df84647a47930fcf7a22ff7229c0 upstream. + +There's a small window inside the flush_to_ldisc function, +where the tty is unlocked and calling ldisc's receive_buf +function. If in this window new buffer is added to the tty, +the processing might never leave the flush_to_ldisc function. + +This scenario will hog the cpu, causing other tty processing +starving, and making it impossible to interface the computer +via tty. + +I was able to exploit this via pty interface by sending only +control characters to the master input, causing the flush_to_ldisc +to be scheduled, but never actually generate any output. + +To reproduce, please run multiple instances of following code. + +- SNIP +#define _XOPEN_SOURCE +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + int i, slave, master = getpt(); + char buf[8192]; + + sprintf(buf, "%s", ptsname(master)); + grantpt(master); + unlockpt(master); + + slave = open(buf, O_RDWR); + if (slave < 0) { + perror("open slave failed"); + return 1; + } + + for(i = 0; i < sizeof(buf); i++) + buf[i] = rand() % 32; + + while(1) { + write(master, buf, sizeof(buf)); + } + + return 0; +} +- SNIP + +The attached patch (based on -next tree) fixes this by checking on the +tty buffer tail. Once it's reached, the current work is rescheduled +and another could run. + +Signed-off-by: Jiri Olsa +Acked-by: Alan Cox +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/char/tty_buffer.c | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +--- a/drivers/char/tty_buffer.c ++++ b/drivers/char/tty_buffer.c +@@ -413,7 +413,8 @@ static void flush_to_ldisc(struct work_s + spin_lock_irqsave(&tty->buf.lock, flags); + + if (!test_and_set_bit(TTY_FLUSHING, &tty->flags)) { +- struct tty_buffer *head; ++ struct tty_buffer *head, *tail = tty->buf.tail; ++ int seen_tail = 0; + while ((head = tty->buf.head) != NULL) { + int count; + char *char_buf; +@@ -423,6 +424,15 @@ static void flush_to_ldisc(struct work_s + if (!count) { + if (head->next == NULL) + break; ++ /* ++ There's a possibility tty might get new buffer ++ added during the unlock window below. We could ++ end up spinning in here forever hogging the CPU ++ completely. To avoid this let's have a rest each ++ time we processed the tail buffer. ++ */ ++ if (tail == head) ++ seen_tail = 1; + tty->buf.head = head->next; + tty_buffer_free(tty, head); + continue; +@@ -432,7 +442,7 @@ static void flush_to_ldisc(struct work_s + line discipline as we want to empty the queue */ + if (test_bit(TTY_FLUSHPENDING, &tty->flags)) + break; +- if (!tty->receive_room) { ++ if (!tty->receive_room || seen_tail) { + schedule_delayed_work(&tty->buf.work, 1); + break; + } diff --git a/queue-2.6.36/tty-restore-tty_ldisc_wait_idle.patch b/queue-2.6.36/tty-restore-tty_ldisc_wait_idle.patch new file mode 100644 index 00000000000..164d4f80cd2 --- /dev/null +++ b/queue-2.6.36/tty-restore-tty_ldisc_wait_idle.patch @@ -0,0 +1,116 @@ +From 100eeae2c5ce23b4db93ff320ee330ef1d740151 Mon Sep 17 00:00:00 2001 +From: Jiri Slaby +Date: Sun, 31 Oct 2010 23:17:51 +0100 +Subject: TTY: restore tty_ldisc_wait_idle + +From: Jiri Slaby + +commit 100eeae2c5ce23b4db93ff320ee330ef1d740151 upstream. + +It was removed in 65b770468e98 (tty-ldisc: turn ldisc user count into +a proper refcount), but we need to wait for last user to quit the +ldisc before we close it in tty_set_ldisc. + +Otherwise weird things start to happen. There might be processes +waiting in tty_read->n_tty_read on tty->read_wait for input to appear +and at that moment, a change of ldisc is fatal. n_tty_close is called, +it frees read_buf and the waiting process is still in the middle of +reading and goes nuts after it is woken. + +Previously we prevented close to happen when others are in ldisc ops +by tty_ldisc_wait_idle in tty_set_ldisc. But the commit above removed +that. So revoke the change and test whether there is 1 user (=we), and +allow the close then. + +We can do that without ldisc/tty locks, because nobody else can open +the device due to TTY_LDISC_CHANGING bit set, so we in fact wait for +everybody to leave. + +I don't understand why tty_ldisc_lock would be needed either when the +counter is an atomic variable, so this is a lockless +tty_ldisc_wait_idle. + +On the other hand, if we fail to wait (timeout or signal), we have to +reenable the halted ldiscs, so we take ldisc lock and reuse the setup +path at the end of tty_set_ldisc. + +Signed-off-by: Jiri Slaby +Acked-by: Linus Torvalds +Tested-by: Sebastian Andrzej Siewior +LKML-Reference: <20101031104136.GA511@Chamillionaire.breakpoint.cc> +LKML-Reference: <1287669539-22644-1-git-send-email-jslaby@suse.cz> +Cc: Alan Cox +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/char/tty_ldisc.c | 29 +++++++++++++++++++++++++++++ + 1 file changed, 29 insertions(+) + +--- a/drivers/char/tty_ldisc.c ++++ b/drivers/char/tty_ldisc.c +@@ -47,6 +47,7 @@ + + static DEFINE_SPINLOCK(tty_ldisc_lock); + static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait); ++static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_idle); + /* Line disc dispatch table */ + static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS]; + +@@ -83,6 +84,7 @@ static void put_ldisc(struct tty_ldisc * + return; + } + local_irq_restore(flags); ++ wake_up(&tty_ldisc_idle); + } + + /** +@@ -531,6 +533,23 @@ static int tty_ldisc_halt(struct tty_str + } + + /** ++ * tty_ldisc_wait_idle - wait for the ldisc to become idle ++ * @tty: tty to wait for ++ * ++ * Wait for the line discipline to become idle. The discipline must ++ * have been halted for this to guarantee it remains idle. ++ */ ++static int tty_ldisc_wait_idle(struct tty_struct *tty) ++{ ++ int ret; ++ ret = wait_event_interruptible_timeout(tty_ldisc_idle, ++ atomic_read(&tty->ldisc->users) == 1, 5 * HZ); ++ if (ret < 0) ++ return ret; ++ return ret > 0 ? 0 : -EBUSY; ++} ++ ++/** + * tty_set_ldisc - set line discipline + * @tty: the terminal to set + * @ldisc: the line discipline +@@ -634,8 +653,17 @@ int tty_set_ldisc(struct tty_struct *tty + + flush_scheduled_work(); + ++ retval = tty_ldisc_wait_idle(tty); ++ + tty_lock(); + mutex_lock(&tty->ldisc_mutex); ++ ++ /* handle wait idle failure locked */ ++ if (retval) { ++ tty_ldisc_put(new_ldisc); ++ goto enable; ++ } ++ + if (test_bit(TTY_HUPPED, &tty->flags)) { + /* We were raced by the hangup method. It will have stomped + the ldisc data and closed the ldisc down */ +@@ -669,6 +697,7 @@ int tty_set_ldisc(struct tty_struct *tty + + tty_ldisc_put(o_ldisc); + ++enable: + /* + * Allow ldisc referencing to occur again + */ diff --git a/queue-2.6.36/tty_ldisc-fix-bug-on-hangup.patch b/queue-2.6.36/tty_ldisc-fix-bug-on-hangup.patch new file mode 100644 index 00000000000..9f6f4110adf --- /dev/null +++ b/queue-2.6.36/tty_ldisc-fix-bug-on-hangup.patch @@ -0,0 +1,74 @@ +From 1c95ba1e1de7edffc0c4e275e147f1a9eb1f81ae Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20R=C3=A9tornaz?= +Date: Wed, 27 Oct 2010 17:13:21 +0200 +Subject: tty_ldisc: Fix BUG() on hangup + +From: =?UTF-8?q?Philippe=20R=C3=A9tornaz?= + +commit 1c95ba1e1de7edffc0c4e275e147f1a9eb1f81ae upstream. + +A kernel BUG when bluetooth rfcomm connection drop while the associated +serial port is open is sometime triggered. + +It seems that the line discipline can disappear between the +tty_ldisc_put and tty_ldisc_get. This patch fall back to the N_TTY line +discipline if the previous discipline is not available anymore. + +Signed-off-by: Philippe Retornaz +Acked-by: Alan Cox +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/char/tty_ldisc.c | 20 +++++++++++++------- + 1 file changed, 13 insertions(+), 7 deletions(-) + +--- a/drivers/char/tty_ldisc.c ++++ b/drivers/char/tty_ldisc.c +@@ -743,9 +743,12 @@ static void tty_reset_termios(struct tty + * state closed + */ + +-static void tty_ldisc_reinit(struct tty_struct *tty, int ldisc) ++static int tty_ldisc_reinit(struct tty_struct *tty, int ldisc) + { +- struct tty_ldisc *ld; ++ struct tty_ldisc *ld = tty_ldisc_get(ldisc); ++ ++ if (IS_ERR(ld)) ++ return -1; + + tty_ldisc_close(tty, tty->ldisc); + tty_ldisc_put(tty->ldisc); +@@ -753,10 +756,10 @@ static void tty_ldisc_reinit(struct tty_ + /* + * Switch the line discipline back + */ +- ld = tty_ldisc_get(ldisc); +- BUG_ON(IS_ERR(ld)); + tty_ldisc_assign(tty, ld); + tty_set_termios_ldisc(tty, ldisc); ++ ++ return 0; + } + + /** +@@ -831,13 +834,16 @@ void tty_ldisc_hangup(struct tty_struct + a FIXME */ + if (tty->ldisc) { /* Not yet closed */ + if (reset == 0) { +- tty_ldisc_reinit(tty, tty->termios->c_line); +- err = tty_ldisc_open(tty, tty->ldisc); ++ ++ if (!tty_ldisc_reinit(tty, tty->termios->c_line)) ++ err = tty_ldisc_open(tty, tty->ldisc); ++ else ++ err = 1; + } + /* If the re-open fails or we reset then go to N_TTY. The + N_TTY open cannot fail */ + if (reset || err) { +- tty_ldisc_reinit(tty, N_TTY); ++ BUG_ON(tty_ldisc_reinit(tty, N_TTY)); + WARN_ON(tty_ldisc_open(tty, tty->ldisc)); + } + tty_ldisc_enable(tty);