Missing Synchronization

Description

Missing Synchronization is a concurrency weakness where software uses a shared resource in a concurrent manner but does not implement any synchronization mechanism to control access to that resource. When multiple threads, processes, or execution contexts access shared data simultaneously without coordination, the resource may reach unexpected or inconsistent states. This differs from incorrect synchronization (CWE-821) where synchronization is attempted but implemented improperly—here, no synchronization is attempted at all, leaving concurrent access completely uncontrolled.

Risk

Without synchronization, race conditions become inevitable when shared resources are accessed concurrently. The consequences range from corrupted data and inconsistent state to security vulnerabilities when attackers can influence timing. Data integrity is compromised when multiple writers modify the same resource simultaneously, potentially leaving it in a partially updated state. Confidentiality can be violated when readers access data during updates, seeing inconsistent or sensitive intermediate values. In security contexts, attackers may exploit the lack of synchronization to bypass checks, modify critical variables, or trigger dangerous execution paths by carefully timing their interactions with the system.

Solution

Identify all shared resources that may be accessed concurrently and implement appropriate synchronization mechanisms. Use mutexes, semaphores, or critical sections to protect shared data. In object-oriented languages, use synchronized methods or blocks. Apply the principle of minimum shared state—prefer thread-local storage or immutable data when possible. Use atomic operations for simple counters or flags. When using condition variables, always pair them with proper mutex protection. Consider using higher-level concurrency abstractions like concurrent collections or message passing. Review code for all shared resources and ensure each has documented synchronization requirements.

Common Consequences

ImpactDetails
IntegrityScope: Integrity

Modify Application Data - Concurrent unsynchronized writes can corrupt shared data, leaving it in inconsistent states.
ConfidentialityScope: Confidentiality

Read Application Data - Readers may observe partial updates or sensitive intermediate values during unsynchronized access.
OtherScope: Other

Alter Execution Logic - Race conditions may allow attackers to influence control flow by manipulating timing of shared resource access.

Example Code

Vulnerable Code

// Vulnerable: No synchronization on shared stdout
#include <stdio.h>
#include <unistd.h>

int main(void) {
    pid_t pid = fork();

    if (pid == 0) {
        // Child process
        // Vulnerable: Unsynchronized writes to shared stdout
        printf("c");
        printf("h");
        printf("i");
        printf("l");
        printf("d");
        printf("\n");
    } else {
        // Parent process
        // Vulnerable: Unsynchronized writes to shared stdout
        printf("P");
        printf("A");
        printf("R");
        printf("E");
        printf("N");
        printf("T");
        printf("\n");
    }
    return 0;
}

// Output may be interleaved: "PcAhRiElNdT\n" instead of proper lines
// Vulnerable: Shared counter without synchronization
public class VulnerableCounter {
    private int count = 0;  // Shared state

    // Vulnerable: No synchronization
    public void increment() {
        count++;  // Not atomic: read-modify-write race condition
    }

    public int getCount() {
        return count;
    }
}

// With multiple threads, final count may be less than expected
// Thread 1: reads count=5
// Thread 2: reads count=5
// Thread 1: writes count=6
// Thread 2: writes count=6  (should be 7!)
# Vulnerable: Shared list without synchronization
import threading

shared_list = []

def vulnerable_append(item):
    # Vulnerable: No lock protection
    if item not in shared_list:  # Check
        shared_list.append(item)  # Then act - race condition!

# Two threads may both see item not in list and both append it
// Vulnerable: Shared flag without synchronization
#include <pthread.h>

int shutdown_flag = 0;  // Shared between threads
int sensitive_data_processed = 0;

void* worker_thread(void* arg) {
    // Vulnerable: Reading shared flag without synchronization
    while (!shutdown_flag) {
        process_data();
        sensitive_data_processed++;
    }
    return NULL;
}

void* control_thread(void* arg) {
    sleep(10);
    // Vulnerable: Writing shared flag without synchronization
    shutdown_flag = 1;
    return NULL;
}
// Vulnerable: Singleton without synchronization
class VulnerableSingleton {
private:
    static VulnerableSingleton* instance;

    VulnerableSingleton() {}

public:
    // Vulnerable: Multiple threads may create multiple instances
    static VulnerableSingleton* getInstance() {
        if (instance == nullptr) {  // Check
            instance = new VulnerableSingleton();  // Create - race!
        }
        return instance;
    }
};

VulnerableSingleton* VulnerableSingleton::instance = nullptr;
// Vulnerable: Shared map without synchronization
package main

var cache = make(map[string]string)  // Shared state

// Vulnerable: Concurrent map access without sync
func vulnerableGet(key string) string {
    return cache[key]  // Unsafe concurrent read
}

func vulnerableSet(key, value string) {
    cache[key] = value  // Unsafe concurrent write - panic risk!
}

Fixed Code

// Fixed: Use mutex to synchronize output
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/wait.h>

pthread_mutex_t stdout_mutex = PTHREAD_MUTEX_INITIALIZER;

void safe_print(const char* message) {
    pthread_mutex_lock(&stdout_mutex);
    printf("%s\n", message);
    fflush(stdout);
    pthread_mutex_unlock(&stdout_mutex);
}

// For fork(), use file locks instead
#include <fcntl.h>

void safe_print_fork(const char* message) {
    struct flock lock = {.l_type = F_WRLCK, .l_whence = SEEK_SET};

    // Lock stdout file descriptor
    fcntl(STDOUT_FILENO, F_SETLKW, &lock);

    printf("%s\n", message);
    fflush(stdout);

    lock.l_type = F_UNLCK;
    fcntl(STDOUT_FILENO, F_SETLK, &lock);
}
// Fixed: Synchronized counter
public class FixedCounter {
    private int count = 0;

    // Fixed: Synchronized method
    public synchronized void increment() {
        count++;
    }

    public synchronized int getCount() {
        return count;
    }
}

// Or use AtomicInteger for better performance
import java.util.concurrent.atomic.AtomicInteger;

public class AtomicCounter {
    private final AtomicInteger count = new AtomicInteger(0);

    public void increment() {
        count.incrementAndGet();  // Atomic operation
    }

    public int getCount() {
        return count.get();
    }
}
# Fixed: Use lock for shared list access
import threading

shared_list = []
list_lock = threading.Lock()

def fixed_append(item):
    # Fixed: Lock protects check-then-act
    with list_lock:
        if item not in shared_list:
            shared_list.append(item)

# Or use thread-safe collections
from queue import Queue

thread_safe_queue = Queue()

def fixed_queue_append(item):
    thread_safe_queue.put(item)  # Thread-safe by design
// Fixed: Shared flag with proper synchronization
#include <pthread.h>
#include <stdatomic.h>

// Option 1: Use atomic type
atomic_int shutdown_flag = 0;

void* worker_thread_fixed(void* arg) {
    while (!atomic_load(&shutdown_flag)) {
        process_data();
    }
    return NULL;
}

void* control_thread_fixed(void* arg) {
    sleep(10);
    atomic_store(&shutdown_flag, 1);
    return NULL;
}

// Option 2: Use mutex and condition variable
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int shutdown_requested = 0;

void request_shutdown() {
    pthread_mutex_lock(&mutex);
    shutdown_requested = 1;
    pthread_cond_broadcast(&cond);
    pthread_mutex_unlock(&mutex);
}
// Fixed: Thread-safe singleton
#include <mutex>

class FixedSingleton {
private:
    static FixedSingleton* instance;
    static std::mutex mutex;

    FixedSingleton() {}

public:
    // Fixed: Double-checked locking with mutex
    static FixedSingleton* getInstance() {
        if (instance == nullptr) {
            std::lock_guard<std::mutex> lock(mutex);
            if (instance == nullptr) {
                instance = new FixedSingleton();
            }
        }
        return instance;
    }
};

// Better: Use C++11 magic statics (thread-safe by standard)
class BetterSingleton {
public:
    static BetterSingleton& getInstance() {
        static BetterSingleton instance;  // Thread-safe in C++11+
        return instance;
    }
};
// Fixed: Use sync.Map or mutex for concurrent map access
package main

import "sync"

// Option 1: sync.Map for concurrent access
var safeCache sync.Map

func fixedGet(key string) (string, bool) {
    value, ok := safeCache.Load(key)
    if ok {
        return value.(string), true
    }
    return "", false
}

func fixedSet(key, value string) {
    safeCache.Store(key, value)
}

// Option 2: Regular map with mutex
type SafeMap struct {
    mu    sync.RWMutex
    items map[string]string
}

func (m *SafeMap) Get(key string) string {
    m.mu.RLock()
    defer m.mu.RUnlock()
    return m.items[key]
}

func (m *SafeMap) Set(key, value string) {
    m.mu.Lock()
    defer m.mu.Unlock()
    m.items[key] = value
}

  • CWE-662: Improper Synchronization (parent)
  • CWE-821: Incorrect Synchronization (sibling)
  • CWE-362: Concurrent Execution Using Shared Resource with Improper Synchronization (related)
  • CWE-543: Use of Singleton Pattern Without Synchronization in a Multithreaded Context (related)
  • CWE-567: Unsynchronized Access to Shared Data in a Multithreaded Context (related)

References

  1. MITRE Corporation. "CWE-820: Missing Synchronization." https://cwe.mitre.org/data/definitions/820.html
  2. CERT Oracle Secure Coding Standard. "LCK05-J. Synchronize access to static fields that can be modified by untrusted code."
  3. CERT C Secure Coding Standard. "CON32-C. Prevent data races when accessing bit-fields from multiple threads."