summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSage Weil <sage@newdream.net>2012-01-27 10:39:49 -0800
committerSage Weil <sage@newdream.net>2012-01-27 10:39:49 -0800
commit0cc26a94c8b9724588951e19b264ad26146685a3 (patch)
treeb0f5a9e8612dfdbbb79ab8030270b997a0405088
parent9b554d4c7c3271b08e34d0f21bbc5922bc070bcb (diff)
downloadceph-0cc26a94c8b9724588951e19b264ad26146685a3.tar.gz
objecter: fix bounds checking on op reply demuxing
We can't assume that the size of out_ops (from the reply) matches the op->out_* vectors from our request state. In particular, the out_ops might be shorter than what we sent the OSD if the OSD was sloppy. Check them. We can assume that op->ops and op->out_* all match; assert as much in op_submit(). Fixes: #1986 Signed-off-by: Sage Weil <sage.weil@dreamhost.com> Reviewed-by: Greg Farnum <gregory.farnum@dreamhost.com>
-rw-r--r--src/osdc/Objecter.cc45
1 files changed, 23 insertions, 22 deletions
diff --git a/src/osdc/Objecter.cc b/src/osdc/Objecter.cc
index f33f33c914c..ddf60e52871 100644
--- a/src/osdc/Objecter.cc
+++ b/src/osdc/Objecter.cc
@@ -806,6 +806,10 @@ tid_t Objecter::op_submit(Op *op, OSDSession *s)
{
assert(client_lock.is_locked());
+ assert(op->ops.size() == op->out_bl.size());
+ assert(op->ops.size() == op->out_rval.size());
+ assert(op->ops.size() == op->out_handler.size());
+
// throttle. before we look at any state, because
// take_op_budget() may drop our lock while it blocks.
take_op_budget(op);
@@ -1173,29 +1177,26 @@ void Objecter::handle_osd_op_reply(MOSDOpReply *m)
// per-op result demuxing
vector<OSDOp> out_ops;
m->claim_ops(out_ops);
- unsigned i = 0;
- for (vector<bufferlist*>::iterator p = op->out_bl.begin();
- p != op->out_bl.end();
- ++p, ++i) {
- ldout(cct, 10) << " op " << i << " rval " << out_ops[i].rval
- << " len " << out_ops[i].outdata.length() << dendl;
- if (*p)
- **p = out_ops[i].outdata;
- }
- i = 0;
- for (vector<int*>::iterator p = op->out_rval.begin();
- p != op->out_rval.end();
- ++p, ++i)
- if (*p)
- **p = out_ops[i].rval;
- i = 0;
- for (vector<Context*>::iterator p = op->out_handler.begin();
- p != op->out_handler.end();
- ++p, ++i)
- if (*p) {
- ldout(cct, 10) << " op " << i << " handler " << *p << dendl;
- (*p)->complete(out_ops[i].rval);
+ vector<bufferlist*>::iterator pb = op->out_bl.begin();
+ vector<int*>::iterator pr = op->out_rval.begin();
+ vector<Context*>::iterator ph = op->out_handler.begin();
+ assert(op->out_bl.size() == op->out_rval.size());
+ assert(op->out_bl.size() == op->out_handler.size());
+ vector<OSDOp>::iterator p = out_ops.begin();
+ for (unsigned i = 0;
+ p != out_ops.end() && pb != op->out_bl.end();
+ ++i, ++p, ++pb, ++pr, ++ph) {
+ ldout(cct, 10) << " op " << i << " rval " << p->rval
+ << " len " << p->outdata.length() << dendl;
+ if (*pb)
+ **pb = p->outdata;
+ if (*pr)
+ **pr = p->rval;
+ if (*ph) {
+ ldout(cct, 10) << " op " << i << " handler " << *ph << dendl;
+ (*ph)->complete(p->rval);
}
+ }
// ack|commit -> ack
if (op->onack) {