Improper Resource Locking

The software does not lock or does not correctly lock a resource when the software must have exclusive access to the resource.


Description

When a resource is not properly locked, an attacker could modify the resource while it is being operated on by the software. This might violate the software's assumption that the resource will not change, potentially leading to unexpected behaviors.

Demonstrations

The following examples help to illustrate the nature of this weakness and describe methods or techniques which can be used to mitigate the risk.

Note that the examples here are by no means exhaustive and any given weakness may have many subtle varieties, each of which may require different detection methods or runtime controls.

Example One

The following function attempts to acquire a lock in order to perform operations on a shared resource.

void f(pthread_mutex_t *mutex) {

  pthread_mutex_lock(mutex);

  /* access shared resource */


  pthread_mutex_unlock(mutex);

}

However, the code does not check the value returned by pthread_mutex_lock() for errors. If pthread_mutex_lock() cannot acquire the mutex for any reason the function may introduce a race condition into the program and result in undefined behavior.

In order to avoid data races correctly written programs must check the result of thread synchronization functions and appropriately handle all errors, either by attempting to recover from them or reporting it to higher levels.

int f(pthread_mutex_t *mutex) {

  int result;

  result = pthread_mutex_lock(mutex);
  if (0 != result)
    return result;


  /* access shared resource */


  return pthread_mutex_unlock(mutex);

}

Example Two

This Java example shows a simple BankAccount class with deposit and withdraw methods.

public class BankAccount {


  // variable for bank account balance
  private double accountBalance;

  // constructor for BankAccount
  public BankAccount() {
    accountBalance = 0;
  }

  // method to deposit amount into BankAccount
  public void deposit(double depositAmount) {


    double newBalance = accountBalance + depositAmount;
    accountBalance = newBalance;

  }

  // method to withdraw amount from BankAccount
  public void withdraw(double withdrawAmount) {


    double newBalance = accountBalance - withdrawAmount;
    accountBalance = newBalance;

  }

  // other methods for accessing the BankAccount object
  ...

}

However, the deposit and withdraw methods have shared access to the account balance private class variable. This can result in a race condition if multiple threads attempt to call the deposit and withdraw methods simultaneously where the account balance is modified by one thread before another thread has completed modifying the account balance. For example, if a thread attempts to withdraw funds using the withdraw method before another thread that is depositing funds using the deposit method completes the deposit then there may not be sufficient funds for the withdraw transaction.

To prevent multiple threads from having simultaneous access to the account balance variable the deposit and withdraw methods should be synchronized using the synchronized modifier.

public class BankAccount {

  ...
  // synchronized method to deposit amount into BankAccount
  public synchronized void deposit(double depositAmount) {
    ...
  }

  // synchronized method to withdraw amount from BankAccount
  public synchronized void withdraw(double withdrawAmount) {
    ...
  }

  ...

}

An alternative solution is to use a lock object to ensure exclusive access to the bank account balance variable. As shown below, the deposit and withdraw methods use the lock object to set a lock to block access to the BankAccount object from other threads until the method has completed updating the bank account balance variable.

public class BankAccount {

  ...
  // lock object for thread access to methods
  private ReentrantLock balanceChangeLock;

  // condition object to temporarily release lock to other threads
  private Condition sufficientFundsCondition;

  // method to deposit amount into BankAccount
  public void deposit(double amount) {


    // set lock to block access to BankAccount from other threads
    balanceChangeLock.lock();
    try {

      double newBalance = balance + amount;
      balance = newBalance;

      // inform other threads that funds are available
      sufficientFundsCondition.signalAll();


    } catch (Exception e) {...}
    finally {
      // unlock lock object
      balanceChangeLock.unlock();
    }

  }

  // method to withdraw amount from bank account
  public void withdraw(double amount) {


    // set lock to block access to BankAccount from other threads
    balanceChangeLock.lock();
    try {

      while (balance < amount) {


        // temporarily unblock access

        // until sufficient funds are available
        sufficientFundsCondition.await();

      }
      double newBalance = balance - amount;
      balance = newBalance;


    } catch (Exception e) {...}
    finally {
      // unlock lock object
      balanceChangeLock.unlock();
    }

  }
  ...

}

See Also

SEI CERT Oracle Secure Coding Standard for Java - Guidelines 08. Visibility and Atomicity (VNA)

Weaknesses in this category are related to the rules and recommendations in the Visibility and Atomicity (VNA) section of the SEI CERT Oracle Secure Coding Standard fo...

SFP Secondary Cluster: Missing Lock

This category identifies Software Fault Patterns (SFPs) within the Missing Lock cluster (SFP19).

Resource Locking Problems

Weaknesses in this category are related to improper handling of locks that are used to control access to resources.

Comprehensive CWE Dictionary

This view (slice) covers all the elements in CWE.

Weaknesses Introduced During Implementation

This view (slice) lists weaknesses that can be introduced during implementation.

Weaknesses Introduced During Design

This view (slice) lists weaknesses that can be introduced during design.


Common Weakness Enumeration content on this website is copyright of The MITRE Corporation unless otherwise specified. Use of the Common Weakness Enumeration and the associated references on this website are subject to the Terms of Use as specified by The MITRE Corporation.