Bug 62141 - ABA bug in defer_linger_chain
Summary: ABA bug in defer_linger_chain
Status: NEW
Alias: None
Product: Apache httpd-2
Classification: Unclassified
Component: mpm_event (show other bugs)
Version: 2.4.29
Hardware: PC All
: P2 normal (vote)
Target Milestone: ---
Assignee: Apache HTTPD Bugs Mailing List
Depends on:
Reported: 2018-02-27 21:12 UTC by Xinhao Yuan
Modified: 2018-03-03 12:53 UTC (History)
0 users


Note You need to log in before you can comment on or make changes to this bug.
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...