Code Smell 260 - Crowdstrike NULL

Maxi Contieri - Jul 20 - - Dev Community

Avoiding the Null Trap in Privilege Mode Drivers

TL;DR: Using null pointers in critical code can crash your system

Problems

  • Memory access violation

  • Unpredictable behavior

  • Null Pointer Dereference

  • Unexpected program termination

  • System instability

  • No healing/recovery strategy

  • Security Risk

Solutions

  1. Avoid using NULLs

  2. Use address sanitizers

  3. Make controlled releases to mission-critical software

  4. Create better rollback strategies instead of BSOD

  5. Use Smart Pointers: Manage memory automatically and avoid null pointers with smart pointers

  6. Create self-healing software.

  7. Apply defensive programming

  8. Improve your QA tests before deploying to production.

BSOD

Context

When you use nulls in a privileged driver, you risk causing serious issues.

Privilege mode drivers run with high permissions, and if you use a null pointer, the system might try to access an invalid memory address.

For example, trying to read from address 0x9c (156) or using 0x0 as a special value can lead to critical errors.

You can't just abort the program in privileged mode, so you must handle these cases carefully.

In privileged drivers, null pointer usage poses significant risks. You can mitigate these risks using modern C++ features like std::optional.

This problem caused one of the worst software blackouts in 2024.

Sample Code

Wrong



// This case is not exactly what happened with Crowdstrike
// It is here for illustration purposes
void* get_data() {
  if (data_available) {
    return data_ptr;  // This could be null!
  } else {
    // Uh oh, what if data_ptr is null here?
    return NULL;  
    // Using Null to indicate no data
    // knowing Null is schizophrenic
  }
}

int process_data(void* data) {
  if (data != NULL) { 
    // Maybe a null check, but not guaranteed!
    // Accessing data... (crash if data is Null)
    return *data;
  }
  // No check? Silent failure or unexpected behavior.
  return -1;
}


Enter fullscreen mode Exit fullscreen mode

Right



// You should ideally replace the null with a polymorphic call
// You can see the technique in related articles

std::unique_ptr<int> get_data() { 
  if (data_available) {
    return std::make_unique<int>(data_value);
  } else {
    return nullptr;  // Explicitly return nullptr
  }
}

int process_data(const std::unique_ptr<int>& data) {
  if (data) { // Check for valid pointer
    return *data;
  } else {
    // Handle no data case (e.g., return default value)
    return 0;
  }
}


Enter fullscreen mode Exit fullscreen mode

Detection

[X] Semi-Automatic

You can detect this smell by checking for null pointer usage in critical parts of your code. Look for functions that process pointers and see if they handle null pointers safely.

Human code reviews are good for checking this kind of problem.

Tags

  • Null

Level

[x] Advanced

AI Generation

AI generators can sometimes produce this smell, especially if they generate code without context about the environment where the code will run.

AI generators are fed with code with NULL usage even though his creator told us to avoid it altogether.

AI Detection

AI tools can detect this smell with specific instructions.

AI can be trained to identify code patterns.

Teaching it the nuances of privileged driver development and null safety best practices might require more advanced techniques.

Use static analysis tools to flag null pointer dereferences.

Conclusion

Voyager 1's software has been running for more than 50 years.

It was designed to be robust, reliable, and redundant which is sadly uncommon in some immature systems in 2024.

Avoid using null pointers in privileged mode drivers.

I have written a book on clean code and a whole chapter #15 on how to avoid NULL and all the consequences it carries.

Hopefully, Crowdstrike engineers will read it!

Relations

More Info


This article is part of the CodeSmell Series.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .