diff options
author | Sage Weil <sage@newdream.net> | 2012-01-27 10:39:49 -0800 |
---|---|---|
committer | Sage Weil <sage@newdream.net> | 2012-01-27 10:39:49 -0800 |
commit | 0cc26a94c8b9724588951e19b264ad26146685a3 (patch) | |
tree | b0f5a9e8612dfdbbb79ab8030270b997a0405088 | |
parent | 9b554d4c7c3271b08e34d0f21bbc5922bc070bcb (diff) | |
download | ceph-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.cc | 45 |
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) { |