Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1616325 > unrolled thread
| Started by | Dmitry Monakhov <dmonakhov@openvz.org> |
|---|---|
| First post | 2017-04-04 21:00 +0200 |
| Last post | 2017-04-06 13:50 +0200 |
| Articles | 3 — 3 participants |
Back to article view | Back to linux.kernel
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
[PATCH 7/9] Guard bvec iteration logic v3 Dmitry Monakhov <dmonakhov@openvz.org> - 2017-04-04 21:00 +0200
Re: [PATCH 7/9] Guard bvec iteration logic v3 Hannes Reinecke <hare@suse.de> - 2017-04-05 08:40 +0200
Re: [PATCH 7/9] Guard bvec iteration logic v3 Christoph Hellwig <hch@infradead.org> - 2017-04-06 13:50 +0200
| From | Dmitry Monakhov <dmonakhov@openvz.org> |
|---|---|
| Date | 2017-04-04 21:00 +0200 |
| Subject | [PATCH 7/9] Guard bvec iteration logic v3 |
| Message-ID | <tsBQl-hL-1@gated-at.bofh.it> |
Currently if some one try to advance bvec beyond it's size we simply
dump WARN_ONCE and continue to iterate beyond bvec array boundaries.
This simply means that we endup dereferencing/corrupting random memory
region.
Sane reaction would be to propagate error back to calling context
But bvec_iter_advance's calling context is not always good for error
handling. For safity reason let truncate iterator size to zero which
will break external iteration loop which prevent us from unpredictable
memory range corruption. And even it caller ignores an error, it will
corrupt it's own bvecs, not others.
This patch does:
- Return error back to caller with hope that it will react on this
- Truncate iterator size
Code was added long time ago here 4550dd6c, luckily no one hit it
in real life :)
changes since V1:
- Replace BUG_ON with error logic.
Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org>
---
drivers/nvdimm/blk.c | 4 +++-
drivers/nvdimm/btt.c | 4 +++-
include/linux/bio.h | 8 ++++++--
include/linux/bvec.h | 11 ++++++++---
4 files changed, 20 insertions(+), 7 deletions(-)
diff --git a/drivers/nvdimm/blk.c b/drivers/nvdimm/blk.c
index 0b49336..c82331b 100644
--- a/drivers/nvdimm/blk.c
+++ b/drivers/nvdimm/blk.c
@@ -106,7 +106,9 @@ static int nd_blk_rw_integrity(struct nd_namespace_blk *nsblk,
len -= cur_len;
dev_offset += cur_len;
- bvec_iter_advance(bip->bip_vec, &bip->bip_iter, cur_len);
+ err = bvec_iter_advance(bip->bip_vec, &bip->bip_iter, cur_len);
+ if (err)
+ return err;
}
return err;
diff --git a/drivers/nvdimm/btt.c b/drivers/nvdimm/btt.c
index 3d7a9fe..5a68681 100644
--- a/drivers/nvdimm/btt.c
+++ b/drivers/nvdimm/btt.c
@@ -942,7 +942,9 @@ static int btt_rw_integrity(struct btt *btt, struct bio_integrity_payload *bip,
len -= cur_len;
meta_nsoff += cur_len;
- bvec_iter_advance(bip->bip_vec, &bip->bip_iter, cur_len);
+ ret = bvec_iter_advance(bip->bip_vec, &bip->bip_iter, cur_len);
+ if (ret)
+ return ret;
}
return ret;
diff --git a/include/linux/bio.h b/include/linux/bio.h
index 65445c0..12b7fcd 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -168,8 +168,12 @@ static inline void bio_advance_iter(struct bio *bio, struct bvec_iter *iter,
if (bio_no_advance_iter(bio))
iter->bi_size -= bytes;
- else
- bvec_iter_advance(bio->bi_io_vec, iter, bytes);
+ else {
+ int err;
+ err = bvec_iter_advance(bio->bi_io_vec, iter, bytes);
+ if (unlikely(err))
+ bio->bi_error = err;
+ }
}
#define __bio_for_each_segment(bvl, bio, iter, start) \
diff --git a/include/linux/bvec.h b/include/linux/bvec.h
index 89b65b8..984a7a8 100644
--- a/include/linux/bvec.h
+++ b/include/linux/bvec.h
@@ -22,6 +22,7 @@
#include <linux/kernel.h>
#include <linux/bug.h>
+#include <linux/errno.h>
/*
* was unsigned short, but we might as well be ready for > 64kB I/O pages
@@ -66,12 +67,15 @@ struct bvec_iter {
.bv_offset = bvec_iter_offset((bvec), (iter)), \
})
-static inline void bvec_iter_advance(const struct bio_vec *bv,
+static inline int bvec_iter_advance(const struct bio_vec *bv,
struct bvec_iter *iter,
unsigned bytes)
{
- WARN_ONCE(bytes > iter->bi_size,
- "Attempted to advance past end of bvec iter\n");
+ if (WARN_ONCE(bytes > iter->bi_size,
+ "Attempted to advance past end of bvec iter\n")) {
+ iter->bi_size = 0;
+ return -EINVAL;
+ }
while (bytes) {
unsigned iter_len = bvec_iter_len(bv, *iter);
@@ -86,6 +90,7 @@ static inline void bvec_iter_advance(const struct bio_vec *bv,
iter->bi_idx++;
}
}
+ return 0;
}
#define for_each_bvec(bvl, bio_vec, iter, start) \
--
2.9.3
[toc] | [next] | [standalone]
| From | Hannes Reinecke <hare@suse.de> |
|---|---|
| Date | 2017-04-05 08:40 +0200 |
| Message-ID | <tsMLM-7sG-13@gated-at.bofh.it> |
| In reply to | #1616325 |
On 04/04/2017 08:56 PM, Dmitry Monakhov wrote: > Currently if some one try to advance bvec beyond it's size we simply > dump WARN_ONCE and continue to iterate beyond bvec array boundaries. > This simply means that we endup dereferencing/corrupting random memory > region. > > Sane reaction would be to propagate error back to calling context > But bvec_iter_advance's calling context is not always good for error > handling. For safity reason let truncate iterator size to zero which > will break external iteration loop which prevent us from unpredictable > memory range corruption. And even it caller ignores an error, it will > corrupt it's own bvecs, not others. > > This patch does: > - Return error back to caller with hope that it will react on this > - Truncate iterator size > > Code was added long time ago here 4550dd6c, luckily no one hit it > in real life :) > > changes since V1: > - Replace BUG_ON with error logic. > > Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org> > --- > drivers/nvdimm/blk.c | 4 +++- > drivers/nvdimm/btt.c | 4 +++- > include/linux/bio.h | 8 ++++++-- > include/linux/bvec.h | 11 ++++++++--- > 4 files changed, 20 insertions(+), 7 deletions(-) > Reviewed-by: Hannes Reinecke <hare@suse.com> Cheers, Hannes -- Dr. Hannes Reinecke Teamlead Storage & Networking hare@suse.de +49 911 74053 688 SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg GF: F. Imendörffer, J. Smithard, J. Guild, D. Upmanyu, G. Norton HRB 21284 (AG Nürnberg)
[toc] | [prev] | [next] | [standalone]
| From | Christoph Hellwig <hch@infradead.org> |
|---|---|
| Date | 2017-04-06 13:50 +0200 |
| Message-ID | <tte5k-7Y4-17@gated-at.bofh.it> |
| In reply to | #1616325 |
> if (bio_no_advance_iter(bio))
> iter->bi_size -= bytes;
> - else
> - bvec_iter_advance(bio->bi_io_vec, iter, bytes);
> + else {
> + int err;
> + err = bvec_iter_advance(bio->bi_io_vec, iter, bytes);
> + if (unlikely(err))
> + bio->bi_error = err;
> + }
I don't think that setting bi_error here is a good idea without actually
completing the bio, which would be a much bigger change.
Maybe leave the error ignored here for now with a fixme comment, and
then we can look into proper error handling in a separate series.
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web