`RewindBlockIndex` reads `chainActive` (via `ChainActive()`) without holding `cs_main`:

https://github.com/bitcoin/bitcoin/blob/b2a6b0216192b6e8428f1a80b47f5178fccb961a/src/validation.cpp#L4314-L4331

(Please note that callers of `RewindBlockIndex` are _not_ allowed to hold `cs_main` since `RewindBlockIndex` indirectly calls `LimitValidationInterfaceQueue`.)
if (!tx.IsCoinBase())
        {
            CAmount txfee = 0;
            if (!Consensus::CheckTxInputs(tx, state, view, pindex->nHeight, txfee)) {
                if (!IsBlockReason(state.GetReason())) {
                    
                    
                    
                    
                    state.Invalid(ValidationInvalidReason::CONSENSUS, false,
                            state.GetRejectCode(), state.GetRejectReason(), state.GetDebugMessage());
                }
                return error("%s: Consensus::CheckTxInputs: %s, %s", __func__, tx.GetHash().ToString(), FormatStateMessage(state));
            }
            nFees += txfee;
            if (!MoneyRange(nFees)) {
                return state.Invalid(ValidationInvalidReason::CONSENSUS, error("%s: accumulated fee in the block out of range.", __func__),
                                 REJECT_INVALID, "bad-txns-accumulated-fee-outofrange");
            }
            
            
            
            prevheights.resize(tx.vin.size());
            for (size_t j = 0; j < tx.vin.size(); j++) {
                prevheights[j] = view.AccessCoin(tx.vin[j].prevout).nHeight;
            }
            if (!SequenceLocks(tx, nLockTimeFlags, &prevheights, *pindex)) {
                return state.Invalid(ValidationInvalidReason::CONSENSUS, error("%s: contains a non-BIP68-final transaction", __func__),
                                 REJECT_INVALID, "bad-txns-nonfinal");
            }