chenBright opened a new pull request, #3347:
URL: https://github.com/apache/brpc/pull/3347

   ### What problem does this PR solve?
   
   Issue Number: resolve 
   
   Problem Summary:
   
   `RdmaEndpoint::_state` is a plain (non-atomic) enum, but it is written
   by the RDMA handshake bthread and read concurrently by the
   event dispatcher bthread in `OnNewDataFromTcp`. This is a data race, 
   and on a weak memory model (ARM / POWER / RISC-V) it can let the two 
   threads concurrently mutate `_socket->_read_buf` and corrupt an `IOBuf`.
   
   
   ```
   time   bthread A (OnNewDataFromTcp)                    bthread B 
(ProcessHandshakeAtServer)
   ────   ─────────────────────────                       
─────────────────────────────────────
    T0                                                    Program order:
                                                            
_read_buf.append(magic, ...)
                                                            _state = 
FALLBACK_TCP
                                                            TryReadOnTcp()  
(fetch_add acq_rel)
   
          ═════════════════════════════ Actual order after CPU reordering 
══════════════════════
   
    T1                                                    ep->_state = 
FALLBACK_TCP
                                                            ← hoisted: this 
store takes effect FIRST
                                                            (_nevent is still 0,
                                                             _read_buf still 
has no magic in it)
   
    T2   (new bytes arrive on the fd,
           epoll edge-trigger fires)
          Socket::StartInputEvent
            _nevent.fetch_add(acq_rel): 0 → 1, == 0
            → spawn bthread A: OnEdge → OnNewDataFromTcp
   
    T3   read ep->_state (plain read, no acquire)
          => observes FALLBACK_TCP ✓ (T1 is visible)
   
    T4   else if (_state == FALLBACK_TCP) ✓
          → InputMessenger::OnNewMessages(m)
            └─ DoRead →
                 _read_buf.append_from_file_descriptor(fd, ...)
            ⚠ A is now WRITING into _read_buf
   
    T5                                                    
s->_read_buf.append(magic, MAGIC_STR_LEN)
                                                            ← reordered: this 
append happens NOW
                                                            ⚠⚠⚠ A and B are 
concurrently mutating
                                                                 the SAME IOBuf 
object!
   
                                                          Consequences:
                                                            • IOBuf internal 
linked list /
                                                              _ref_array / 
_data pointer / refcount
                                                              are mutated 
concurrently
                                                            • memory 
corruption, use-after-free,
                                                              refcount drift, 
crash
                                                            • or — more 
insidious — the bytes
                                                              appear to be 
accepted but the
                                                              internal state of 
_read_buf is
                                                              already corrupted
   
   ```
   
   ### What is changed and the side effects?
   
   Changed:
   
   Make `_state` a `butil::atomic<State>`.
   
   - Terminal-state stores use `memory_order_release` and the corresponding 
loads use 
      `memory_order_acquire`, so that everything published before a terminal 
state becomes 
      visible to the reader:
      - the magic bytes appended back into _socket->_read_buf before 
FALLBACK_TCP;
      - the RDMA window/resource setup done before ESTABLISHED.
   - All other (non-terminal) handshake transitions use `memory_order_relaxed`.
   
   Side effects:
   - Performance effects:
   
   - Breaking backward compatibility: 
   
   ---
   ### Check List:
   - Please make sure your changes are compilable.
   - When providing us with a new feature, it is best to add related tests.
   - Please follow [Contributor Covenant Code of 
Conduct](https://github.com/apache/brpc/blob/master/CODE_OF_CONDUCT.md).
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to