summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@suse.de>2011-05-30 08:46:09 +0800
committerGreg Kroah-Hartman <gregkh@suse.de>2011-05-30 08:46:09 +0800
commitf57869216f4bc1b752114c16973a8785999f35f9 (patch)
tree11d46b4b34be12c7f8458248b13c454b146ebf12
parent36678c489f06618d4736cf850128dff32b5714fd (diff)
downloadlongterm-queue-2.6.33-f57869216f4bc1b752114c16973a8785999f35f9.tar.gz
.33 patches
-rw-r--r--queue-2.6.33/libata-use-maximum-write-same-length-to-report-discard-size.patch38
-rw-r--r--queue-2.6.33/series2
-rw-r--r--queue-2.6.33/x86-64-bit-fix-copy__user-checks-for-the.patch118
3 files changed, 158 insertions, 0 deletions
diff --git a/queue-2.6.33/libata-use-maximum-write-same-length-to-report-discard-size.patch b/queue-2.6.33/libata-use-maximum-write-same-length-to-report-discard-size.patch
new file mode 100644
index 0000000..471af6b
--- /dev/null
+++ b/queue-2.6.33/libata-use-maximum-write-same-length-to-report-discard-size.patch
@@ -0,0 +1,38 @@
+From 5f4e206666f834340b69ddb43f86de3851c8675a Mon Sep 17 00:00:00 2001
+From: "Martin K. Petersen" <martin.petersen@oracle.com>
+Date: Tue, 17 May 2011 22:13:23 -0400
+Subject: libata: Use Maximum Write Same Length to report discard size
+ limit
+
+From: "Martin K. Petersen" <martin.petersen@oracle.com>
+
+commit 5f4e206666f834340b69ddb43f86de3851c8675a upstream.
+
+Previously we used Maximum Unmap LBA Count in the Block Limits VPD to
+signal the maximum number of sectors we could handle in a single Write
+Same command.
+
+Starting with SBC3r26 the Block Limits VPD has an explicit limit on the
+number of blocks in a Write Same. This means we can stop abusing a field
+related to the Unmap command and let our SAT use the proper value in the
+VPD (Maximum Write Same Length).
+
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/ata/libata-scsi.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/ata/libata-scsi.c
++++ b/drivers/ata/libata-scsi.c
+@@ -2133,7 +2133,7 @@ static unsigned int ata_scsiop_inq_b0(st
+ * with the unmap bit set.
+ */
+ if (ata_id_has_trim(args->id)) {
+- put_unaligned_be32(65535 * 512 / 8, &rbuf[20]);
++ put_unaligned_be64(65535 * 512 / 8, &rbuf[36]);
+ put_unaligned_be32(1, &rbuf[28]);
+ }
+
diff --git a/queue-2.6.33/series b/queue-2.6.33/series
index 9ddf2c0..20ec2d1 100644
--- a/queue-2.6.33/series
+++ b/queue-2.6.33/series
@@ -7,3 +7,5 @@ block-rescan-partitions-on-invalidated-devices-on-enomedia.patch
block-add-proper-state-guards-to-__elv_next_request.patch
mtd-mtdconcat-fix-nand-oob-write.patch
mtd-return-badblockbits-back.patch
+x86-64-bit-fix-copy__user-checks-for-the.patch
+libata-use-maximum-write-same-length-to-report-discard-size.patch
diff --git a/queue-2.6.33/x86-64-bit-fix-copy__user-checks-for-the.patch b/queue-2.6.33/x86-64-bit-fix-copy__user-checks-for-the.patch
new file mode 100644
index 0000000..4c0ce52
--- /dev/null
+++ b/queue-2.6.33/x86-64-bit-fix-copy__user-checks-for-the.patch
@@ -0,0 +1,118 @@
+From 26afb7c661080ae3f1f13ddf7f0c58c4f931c22b Mon Sep 17 00:00:00 2001
+From: Jiri Olsa <jolsa@redhat.com>
+Date: Thu, 12 May 2011 16:30:30 +0200
+Subject: x86, 64-bit: Fix copy_[to/from]_user() checks for the
+ userspace address limit
+
+From: Jiri Olsa <jolsa@redhat.com>
+
+commit 26afb7c661080ae3f1f13ddf7f0c58c4f931c22b upstream.
+
+As reported in BZ #30352:
+
+ https://bugzilla.kernel.org/show_bug.cgi?id=30352
+
+there's a kernel bug related to reading the last allowed page on x86_64.
+
+The _copy_to_user() and _copy_from_user() functions use the following
+check for address limit:
+
+ if (buf + size >= limit)
+ fail();
+
+while it should be more permissive:
+
+ if (buf + size > limit)
+ fail();
+
+That's because the size represents the number of bytes being
+read/write from/to buf address AND including the buf address.
+So the copy function will actually never touch the limit
+address even if "buf + size == limit".
+
+Following program fails to use the last page as buffer
+due to the wrong limit check:
+
+ #include <sys/mman.h>
+ #include <sys/socket.h>
+ #include <assert.h>
+
+ #define PAGE_SIZE (4096)
+ #define LAST_PAGE ((void*)(0x7fffffffe000))
+
+ int main()
+ {
+ int fds[2], err;
+ void * ptr = mmap(LAST_PAGE, PAGE_SIZE, PROT_READ | PROT_WRITE,
+ MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0);
+ assert(ptr == LAST_PAGE);
+ err = socketpair(AF_LOCAL, SOCK_STREAM, 0, fds);
+ assert(err == 0);
+ err = send(fds[0], ptr, PAGE_SIZE, 0);
+ perror("send");
+ assert(err == PAGE_SIZE);
+ err = recv(fds[1], ptr, PAGE_SIZE, MSG_WAITALL);
+ perror("recv");
+ assert(err == PAGE_SIZE);
+ return 0;
+ }
+
+The other place checking the addr limit is the access_ok() function,
+which is working properly. There's just a misleading comment
+for the __range_not_ok() macro - which this patch fixes as well.
+
+The last page of the user-space address range is a guard page and
+Brian Gerst observed that the guard page itself due to an erratum on K8 cpus
+(#121 Sequential Execution Across Non-Canonical Boundary Causes Processor
+Hang).
+
+However, the test code is using the last valid page before the guard page.
+The bug is that the last byte before the guard page can't be read
+because of the off-by-one error. The guard page is left in place.
+
+This bug would normally not show up because the last page is
+part of the process stack and never accessed via syscalls.
+
+Signed-off-by: Jiri Olsa <jolsa@redhat.com>
+Acked-by: Brian Gerst <brgerst@gmail.com>
+Acked-by: Linus Torvalds <torvalds@linux-foundation.org>
+Link: http://lkml.kernel.org/r/1305210630-7136-1-git-send-email-jolsa@redhat.com
+Signed-off-by: Ingo Molnar <mingo@elte.hu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/x86/include/asm/uaccess.h | 2 +-
+ arch/x86/lib/copy_user_64.S | 4 ++--
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+--- a/arch/x86/include/asm/uaccess.h
++++ b/arch/x86/include/asm/uaccess.h
+@@ -42,7 +42,7 @@
+ * Returns 0 if the range is valid, nonzero otherwise.
+ *
+ * This is equivalent to the following test:
+- * (u33)addr + (u33)size >= (u33)current->addr_limit.seg (u65 for x86_64)
++ * (u33)addr + (u33)size > (u33)current->addr_limit.seg (u65 for x86_64)
+ *
+ * This needs 33-bit (65-bit for x86_64) arithmetic. We have a carry...
+ */
+--- a/arch/x86/lib/copy_user_64.S
++++ b/arch/x86/lib/copy_user_64.S
+@@ -72,7 +72,7 @@ ENTRY(_copy_to_user)
+ addq %rdx,%rcx
+ jc bad_to_user
+ cmpq TI_addr_limit(%rax),%rcx
+- jae bad_to_user
++ ja bad_to_user
+ ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,copy_user_generic_unrolled,copy_user_generic_string
+ CFI_ENDPROC
+ ENDPROC(_copy_to_user)
+@@ -85,7 +85,7 @@ ENTRY(_copy_from_user)
+ addq %rdx,%rcx
+ jc bad_from_user
+ cmpq TI_addr_limit(%rax),%rcx
+- jae bad_from_user
++ ja bad_from_user
+ ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,copy_user_generic_unrolled,copy_user_generic_string
+ CFI_ENDPROC
+ ENDPROC(_copy_from_user)