On Fri, 21 Sep 2012 11:04:40 -0700 <[email protected]> wrote:

> 
> The patch below does not apply to the 3.4-stable tree.
> If someone wants it applied there, or to any other stable or longterm
> tree, then please email the backport, including the original git commit
> id to <[email protected]>.
> 

Here is 3.4-stable version that patch.

Thanks!
NeilBrown

From 28f65065d75c4cbfcc74c2c03f627ce41fee60a7 Mon Sep 17 00:00:00 2001
From: NeilBrown <[email protected]>
Date: Sat, 18 Aug 2012 09:51:42 +1000
Subject: [PATCH] md/raid10: fix problem with on-stack allocation of r10bio
 structure.

commit e0ee778528bbaad28a5c69d2e219269a3a096607 upstream

A 'struct r10bio' has an array of per-copy information at the end.
This array is declared with size [0] and r10bio_pool_alloc allocates
enough extra space to store the per-copy information depending on the
number of copies needed.

So declaring a 'struct r10bio on the stack isn't going to work.  It
won't allocate enough space, and memory corruption will ensue.

So in the two places where this is done, declare a sufficiently large
structure and use that instead.

The two call-sites of this bug were introduced in 3.4 and 3.5
so this is suitable for both those kernels.  The patch will have to
be (and now has been) modified for 3.4 as it only has one bug.

Cc: [email protected]
Reported-by: Ivan Vasilyev <[email protected]>
Tested-by: Ivan Vasilyev <[email protected]>
Signed-off-by: NeilBrown <[email protected]>

Conflicts:
        drivers/md/raid10.c

diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index a954c95..1f7e8cd 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -612,20 +612,24 @@ static int raid10_mergeable_bvec(struct request_queue *q,
                max = biovec->bv_len;
 
        if (mddev->merge_check_needed) {
-               struct r10bio r10_bio;
+               struct {
+                       struct r10bio r10_bio;
+                       struct r10dev devs[conf->copies];
+               } on_stack;
+               struct r10bio *r10_bio = &on_stack.r10_bio;
                int s;
-               r10_bio.sector = sector;
-               raid10_find_phys(conf, &r10_bio);
+               r10_bio->sector = sector;
+               raid10_find_phys(conf, r10_bio);
                rcu_read_lock();
                for (s = 0; s < conf->copies; s++) {
-                       int disk = r10_bio.devs[s].devnum;
+                       int disk = r10_bio->devs[s].devnum;
                        struct md_rdev *rdev = rcu_dereference(
                                conf->mirrors[disk].rdev);
                        if (rdev && !test_bit(Faulty, &rdev->flags)) {
                                struct request_queue *q =
                                        bdev_get_queue(rdev->bdev);
                                if (q->merge_bvec_fn) {
-                                       bvm->bi_sector = r10_bio.devs[s].addr
+                                       bvm->bi_sector = r10_bio->devs[s].addr
                                                + rdev->data_offset;
                                        bvm->bi_bdev = rdev->bdev;
                                        max = min(max, q->merge_bvec_fn(
@@ -637,7 +641,7 @@ static int raid10_mergeable_bvec(struct request_queue *q,
                                struct request_queue *q =
                                        bdev_get_queue(rdev->bdev);
                                if (q->merge_bvec_fn) {
-                                       bvm->bi_sector = r10_bio.devs[s].addr
+                                       bvm->bi_sector = r10_bio->devs[s].addr
                                                + rdev->data_offset;
                                        bvm->bi_bdev = rdev->bdev;
                                        max = min(max, q->merge_bvec_fn(
diff --git a/drivers/md/raid10.h b/drivers/md/raid10.h
index 7c615613..24d45b8 100644
--- a/drivers/md/raid10.h
+++ b/drivers/md/raid10.h
@@ -104,7 +104,7 @@ struct r10bio {
         * We choose the number when they are allocated.
         * We sometimes need an extra bio to write to the replacement.
         */
-       struct {
+       struct r10dev {
                struct bio      *bio;
                union {
                        struct bio      *repl_bio; /* used for resync and

Attachment: signature.asc
Description: PGP signature

Reply via email to