FAQ Search Today's Posts Mark Forums Read
» Video Reviews

» Linux Archive

Linux-archive is a website aiming to archive linux email lists and to make them easily accessible for linux users/developers.


» Sponsor

» Partners

» Sponsor

Go Back   Linux Archive > Redhat > Device-mapper Development

 
 
LinkBack Thread Tools
 
Old 12-13-2007, 01:44 PM
Alasdair G Kergon
 
Default dm crypt: use bio_add_page

From: Milan Broz <mbroz@redhat.com>

Fix possible max_phys_segments violation in cloned dm-crypt bio.

In write operation dm-crypt needs to allocate new bio request
and run crypto operation on this clone. Cloned request has always
the same size, but number of physical segments can be increased
and violate max_phys_segments restriction.

This can lead to data corruption and serious hardware malfunction.
This was observed when using XFS over dm-crypt and at least
two HBA controller drivers (arcmsr, cciss) recently.

Fix it by using bio_add_page() call (which tests for other
restrictions too) instead of constructing own biovec.

All versions of dm-crypt are affected by this bug.

Cc: stable@kernel.org
Cc: dm-crypt@saout.de
Signed-off-by: Milan Broz <mbroz@redhat.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>
---
drivers/md/dm-crypt.c | 24 +++++++++++-------------
1 files changed, 11 insertions(+), 13 deletions(-)

Index: linux-2.6.24-rc5/drivers/md/dm-crypt.c
================================================== =================
--- linux-2.6.24-rc5.orig/drivers/md/dm-crypt.c 2007-12-12 15:43:11.000000000 +0000
+++ linux-2.6.24-rc5/drivers/md/dm-crypt.c 2007-12-12 15:43:15.000000000 +0000
@@ -398,7 +398,8 @@ static struct bio *crypt_alloc_buffer(st
struct bio *clone;
unsigned int nr_iovecs = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
gfp_t gfp_mask = GFP_NOIO | __GFP_HIGHMEM;
- unsigned int i;
+ unsigned i, len;
+ struct page *page;

clone = bio_alloc_bioset(GFP_NOIO, nr_iovecs, cc->bs);
if (!clone)
@@ -407,10 +408,8 @@ static struct bio *crypt_alloc_buffer(st
clone_init(io, clone);

for (i = 0; i < nr_iovecs; i++) {
- struct bio_vec *bv = bio_iovec_idx(clone, i);
-
- bv->bv_page = mempool_alloc(cc->page_pool, gfp_mask);
- if (!bv->bv_page)
+ page = mempool_alloc(cc->page_pool, gfp_mask);
+ if (!page)
break;

/*
@@ -421,15 +420,14 @@ static struct bio *crypt_alloc_buffer(st
if (i == (MIN_BIO_PAGES - 1))
gfp_mask = (gfp_mask | __GFP_NOWARN) & ~__GFP_WAIT;

- bv->bv_offset = 0;
- if (size > PAGE_SIZE)
- bv->bv_len = PAGE_SIZE;
- else
- bv->bv_len = size;
+ len = (size > PAGE_SIZE) ? PAGE_SIZE : size;
+
+ if (!bio_add_page(clone, page, len, 0)) {
+ mempool_free(page, cc->page_pool);
+ break;
+ }

- clone->bi_size += bv->bv_len;
- clone->bi_vcnt++;
- size -= bv->bv_len;
+ size -= len;
}

if (!clone->bi_size) {

--
dm-devel mailing list
dm-devel@redhat.com
https://www.redhat.com/mailman/listinfo/dm-devel
 
Old 02-06-2008, 10:50 PM
Greg KH
 
Default dm crypt: use bio_add_page

2.6.23-stable review patch. If anyone has any objections, please let us know.
------------------
From: Milan Broz <mbroz@redhat.com>

patch 91e106259214b40e992a58fb9417da46868e19b2 in mainline.

Fix possible max_phys_segments violation in cloned dm-crypt bio.

In write operation dm-crypt needs to allocate new bio request
and run crypto operation on this clone. Cloned request has always
the same size, but number of physical segments can be increased
and violate max_phys_segments restriction.

This can lead to data corruption and serious hardware malfunction.
This was observed when using XFS over dm-crypt and at least
two HBA controller drivers (arcmsr, cciss) recently.

Fix it by using bio_add_page() call (which tests for other
restrictions too) instead of constructing own biovec.

All versions of dm-crypt are affected by this bug.

Signed-off-by: Milan Broz <mbroz@redhat.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

---
drivers/md/dm-crypt.c | 24 +++++++++++-------------
1 file changed, 11 insertions(+), 13 deletions(-)

--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -399,7 +399,8 @@ static struct bio *crypt_alloc_buffer(st
struct bio *clone;
unsigned int nr_iovecs = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
gfp_t gfp_mask = GFP_NOIO | __GFP_HIGHMEM;
- unsigned int i;
+ unsigned i, len;
+ struct page *page;

clone = bio_alloc_bioset(GFP_NOIO, nr_iovecs, cc->bs);
if (!clone)
@@ -408,10 +409,8 @@ static struct bio *crypt_alloc_buffer(st
clone_init(io, clone);

for (i = 0; i < nr_iovecs; i++) {
- struct bio_vec *bv = bio_iovec_idx(clone, i);
-
- bv->bv_page = mempool_alloc(cc->page_pool, gfp_mask);
- if (!bv->bv_page)
+ page = mempool_alloc(cc->page_pool, gfp_mask);
+ if (!page)
break;

/*
@@ -422,15 +421,14 @@ static struct bio *crypt_alloc_buffer(st
if (i == (MIN_BIO_PAGES - 1))
gfp_mask = (gfp_mask | __GFP_NOWARN) & ~__GFP_WAIT;

- bv->bv_offset = 0;
- if (size > PAGE_SIZE)
- bv->bv_len = PAGE_SIZE;
- else
- bv->bv_len = size;
+ len = (size > PAGE_SIZE) ? PAGE_SIZE : size;
+
+ if (!bio_add_page(clone, page, len, 0)) {
+ mempool_free(page, cc->page_pool);
+ break;
+ }

- clone->bi_size += bv->bv_len;
- clone->bi_vcnt++;
- size -= bv->bv_len;
+ size -= len;
}

if (!clone->bi_size) {

--

--
dm-devel mailing list
dm-devel@redhat.com
https://www.redhat.com/mailman/listinfo/dm-devel
 

Thread Tools




All times are GMT. The time now is 04:13 PM.

VBulletin, Copyright ©2000 - 2014, Jelsoft Enterprises Ltd.
Content Relevant URLs by vBSEO ©2007, Crawlability, Inc.
Copyright 2007 - 2008, www.linux-archive.org