Skip to content

Commit 0dd246f

Browse files
jimwwalkertrondn
authored andcommitted
MB-35937: Don't re-check an already authorized command
1) A command passed authorization and is executed, e.g. a sync-write ADD 2) The command returns "would block" (and has set engine-specific) 3) some time passes and ns_server disconnects 4) The engine calls notifyIOComplete 5) The command resumes and is authorized, this time because ns_server is down authorization fails and the command returns "no access". 6) ns_server resumes 7) A new sync-write ADD passes authorization and is executed, it observes that the engine-specific is set and "short-cuts" the actual ADD, it returns success. In this scenario we have now returned success for the ADD at step 7, yet the key has not been stored. To address this issue, update the Cookie object so it can track when authorization was successful, allowing the resumption of the command to skip authorization and complete within the engine. Change-Id: I8e077786b8aadfead849d4f72b8c93450c8dd437 Reviewed-on: http://review.couchbase.org/114815 Tested-by: Build Bot <[email protected]> Reviewed-by: Trond Norbye <[email protected]>
1 parent 7559f21 commit 0dd246f

File tree

3 files changed

+31
-1
lines changed

3 files changed

+31
-1
lines changed

daemon/cookie.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -522,6 +522,7 @@ void Cookie::initialize(cb::const_byte_buffer header, bool tracing_enabled) {
522522
tracer.begin(cb::tracing::TraceCode::REQUEST, start);
523523
ewouldblock = false;
524524
openTracingContext.clear();
525+
authorized = false;
525526
}
526527

527528
void Cookie::reset() {
@@ -536,6 +537,7 @@ void Cookie::reset() {
536537
tracer.clear();
537538
ewouldblock = false;
538539
openTracingContext.clear();
540+
authorized = false;
539541
}
540542

541543
void Cookie::setOpenTracingContext(cb::const_byte_buffer context) {

daemon/cookie.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,26 @@ class Cookie {
520520
validated = value;
521521
}
522522

523+
/**
524+
* @return true is setAuthorized has been called
525+
*/
526+
bool isAuthorized() const {
527+
return authorized;
528+
}
529+
530+
/**
531+
* This method should be used when the command has successfully passed
532+
* authorization check(s).
533+
*
534+
* This exists to assist with correct "would block" command processing,
535+
* this method should be used to tag that the authorization process has
536+
* returned "success| and the command shouldn't get a second authorization
537+
* test when unblocked and re-executed.
538+
*/
539+
void setAuthorized() {
540+
authorized = true;
541+
}
542+
523543
protected:
524544
bool enableTracing = false;
525545
cb::tracing::Tracer tracer;
@@ -608,4 +628,7 @@ class Cookie {
608628
/// might have multiple cookies in flight and needs to be able to
609629
/// lock them independently
610630
uint8_t refcount = 0;
631+
632+
/// see isAuthorized/setAuthorized
633+
bool authorized = false;
611634
};

daemon/mcbp_executors.cc

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -833,7 +833,11 @@ void execute_client_request_packet(Cookie& cookie,
833833
static McbpPrivilegeChains privilegeChains;
834834

835835
const auto opcode = request.getClientOpcode();
836-
const auto res = privilegeChains.invoke(opcode, cookie);
836+
auto res = cb::rbac::PrivilegeAccess::Ok;
837+
if (!cookie.isAuthorized()) {
838+
res = privilegeChains.invoke(opcode, cookie);
839+
}
840+
837841
switch (res) {
838842
case cb::rbac::PrivilegeAccess::Fail:
839843
LOG_WARNING("{} {}: no access to command {}",
@@ -849,6 +853,7 @@ void execute_client_request_packet(Cookie& cookie,
849853
}
850854
return;
851855
case cb::rbac::PrivilegeAccess::Ok:
856+
cookie.setAuthorized();
852857
handlers[std::underlying_type<cb::mcbp::ClientOpcode>::type(opcode)](
853858
cookie);
854859
return;

0 commit comments

Comments
 (0)