Bug 62141

Summary: ABA bug in defer_linger_chain
Product: Apache httpd-2 Reporter: Xinhao Yuan <xinhaoyuan>
Component: mpm_eventAssignee: Apache HTTPD Bugs Mailing List <bugs>
Status: NEW ---    
Severity: normal    
Priority: P2    
Version: 2.4.29   
Target Milestone: ---   
Hardware: PC   
OS: All   

Description Xinhao Yuan 2018-02-27 21:12:18 UTC
The atomic compare-and-swap operations on defer_linger_chain seems vulnerable to ABA problems under multiple worker threads.

In event.c:2025

2021         cs = defer_linger_chain;                                                                                                                                                                                                                                        
2022         if (!cs) {                                                                                                                                                                                                                                                      
2023             break;                                                                                                                                                                                                                                                      
2024         }                                                                                                                                                                                                                                                               
2025         if (apr_atomic_casptr((void *)&defer_linger_chain, cs->chain,                                                                                                                                                                                                   
2026                               cs) != cs) {                                                                                                                                                                                                                              
2027             /* Race lost, try again */                                                                                                                                                                                                                                  
2028             continue;                                                                                                                                                                                                                                                   
2029         }

Consider the following sequence of events with the chain v0 -> v1:

1. A worker thread runs to line 2025, reads cs as v0, and cs->chain as v1, but gets preempted before executing the CAS.

2. Other threads pop defer_linger_chain twice, get v0 and v1, now defer_linger_chain is NULL. v0 and v1 now get freed.

3. A new connection gets associated with a event_conn_state_t that have the same address of v0. Later v0 (with new content) gets pushed into defer_linger_chain again. Now the chain is just v0 and v0->chain is NULL.

4. The worker thread get resumed and the CAS operation succeed (as the head is still v0).

Now defer_linger_chain points to v1, which is now invalid. Further operations on defer_linger_chain will be undefined.
Comment 1 Yann Ylavic 2018-03-03 12:53:41 UTC
Hmm, right, quite unlikely but still.

I'll work on using the low 3-bits of the pointer (always zeros thanks to alignement) as a counter, such that odds are (hopefully) negligible...