Facebook Pixel

Race Condition Vulnerability

When two or more processes are running at the same time and sharing data, the order in which their instructions execute can make a huge difference to the outcome. If that order is unpredictable, you have a race condition.

The processes are essentially racing each other to access the shared resource, and whoever gets there first in any given run determines what the final result looks like. The problem is that the result changes depending on timing, which means it can be wrong, and wrong in ways that are hard to reproduce or debug.

A Concrete Example

Say you have a shared variable C stored in memory, initialized to 10. Process P1 wants to increment it. Process P2 wants to decrement it. If they run one after the other without interruption, the final value should still be 10, since one adds 1 and the other subtracts 1.

But incrementing and decrementing are not single-step operations. Each one involves loading the value into a register, performing the arithmetic, and writing it back. That is three steps, and any of them can be interrupted by the other process.

text
P1's steps (increment):           P2's steps (decrement):
  R1 = M(C)    // Load C            R2 = M(C)    // Load C
  R1 = R1 + 1  // Add 1             R2 = R2 - 1  // Subtract 1
  M(C) = R1    // Write back         M(C) = R2    // Write back

Scenario 1: P1's Increment Gets Lost

TimeProcessActionState
T1P1R1 = M(C)R1=10, M(C)=10
T2P2R2 = M(C)R2=10, M(C)=10
T3P2R2 = R2 - 1R2=9, M(C)=10
T4P1R1 = R1 + 1R1=11, M(C)=10
T5P1M(C) = R1M(C)=11
T6P2M(C) = R2M(C)=9

Final value is 9. P1's increment happened but then got overwritten by P2's write, which was based on the original value of 10. P1's work is completely gone.

Scenario 2: P2's Decrement Gets Lost

TimeProcessActionState
T1P1R1 = M(C)R1=10, M(C)=10
T2P1R1 = R1 + 1R1=11, M(C)=10
T3P2R2 = M(C)R2=10, M(C)=10
T4P2R2 = R2 - 1R2=9, M(C)=10
T5P2M(C) = R2M(C)=9
T6P1M(C) = R1M(C)=11

Final value is 11. P2's decrement happened but P1 wrote over it with a value computed before P2 did anything. P2's work is gone this time.

Both results are wrong. The correct answer is 10, but depending on the timing you get either 9 or 11.

When Race Conditions Become Security Vulnerabilities

A race condition that just gives wrong results is bad enough in a regular program. But when a race condition exists in security-sensitive code, it becomes a vulnerability that attackers can actively exploit. This is formally recognized as CWE-362 in the Common Weakness Enumeration.

The attack usually targets the window between when a check is performed and when the result of that check is actually used. This window is called the TOCTOU gap, which stands for Time of Check to Time of Use.

TOCTOU: Time of Check to Time of Use
A TOCTOU attack exploits the gap between verifying a condition and acting on it. For example, a program checks if a file exists, then opens it. In between those two steps, an attacker replaces the file with a malicious one. The program opens the attacker's file thinking it passed the safety check. The smaller this gap, the harder the attack. Eliminating the gap entirely (atomic check-and-use) makes it impossible.

Common Attack Surfaces

TargetHow It Is Exploited
Login SystemsAttacker slips malicious code into the gap between credential verification and access grant, potentially authenticating without valid credentials.
Temporary FilesA program creates a temp file with a predictable name. An attacker replaces it with a symbolic link before the program writes to it, redirecting sensitive data.
File Permission ChecksA program checks file accessibility, then uses the file. Between those moments, an attacker swaps it for a different file with different content.
Database RecordsTwo transactions update the same record. An attacker manipulates the race to alter salary records, account balances, or access permissions.

What Can Go Wrong at a Larger Scale

  • Data corruption in shared files or database tables can quietly spread without anyone noticing until the damage is severe.
  • If a race condition affects kernel-level processes, it can cause them to loop indefinitely, eventually crashing the entire system.
  • Deadlocks can emerge when multiple processes are each holding a resource and waiting for another resource held by a different process.
  • Unauthorized access during active login sessions, where an attacker slips through a security check that should have blocked them.

How to Protect Against It

DefenseHow It Helps
Atomic OperationsIf a sequence of instructions runs from start to finish without interruption, no other process can slip in. Hardware instructions like compare-and-swap are designed for this.
Synchronization MechanismsLocks, semaphores, mutexes, and monitors ensure only one process at a time accesses the critical section. Properly placed, they eliminate the race window.
Minimizing TOCTOU WindowThe less time between a check and its use, the harder it is for an attacker to exploit the gap. Combine check and use into a single atomic step when possible.
Automated Testing ToolsStatic analysis and dynamic testing under concurrent conditions catch race condition patterns that developers might miss.
System LoggingLogs that track access to shared resources and record out-of-order operations make it easier to diagnose race condition exploits after the fact.
Web Application FirewallsBlock known attack patterns that attempt to exploit TOCTOU vulnerabilities in web-facing systems.

Race conditions are one of those bugs that can lie dormant for a long time because they only show up under specific timing conditions that might not appear during normal testing. The fact that they can also be deliberately triggered by an attacker makes them especially important to take seriously. Getting synchronization right from the start is far easier than hunting down a race condition that only appears occasionally in production.

Sort the Concepts

Classify each item as either a CAUSE of race conditions or a DEFENSE against them.

Causes Race Conditions
Defends Against Race Conditions
Unsorted Items:
Non-atomic read-modify-write operations
Mutex locks around critical sections
Gap between checking a condition and acting on it
Hardware atomic instructions like compare-and-swap
Multiple processes accessing shared data without synchronization
Semaphores controlling access to shared resources
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.
Please Login.