2

I have been building a network application with a Client/Server model, where a central server handles multiple client threads.

I did my best to ensure that no matter what context the program is run it won't deadlock as part of a security requirement.

My question is about deadlocks and concurrency in a networked application serving multiple threads. A deadlock is effectively a denial-of-service, but can you actually exploit a deadlock to do anything malicious? Are there security considerations, other than deadlocks, that I must make when building a concurrent application?

pjmil
  • 133
  • 4

3 Answers3

2

A deadlock, by itself, would not generally allow an attacker to affect program flow. By definition, at a deadlock, the program stops making forward progress, so at that point, nothing is happening: desirable or undesirable.

There are many other security issues possible in multithreaded applications:

  • Ensure that threads are only reading/writing memory intended for them. (This is very broad, of course, but depends so much on your application.)
  • If you depend on random data (such as for crypto keys) ensure that the RNGs for your threads are not at the same point. Using the same RNGs for multiple threads may result in cryptographic weaknesses.
  • Race conditions are more likely to occur in multi-threaded programs. These race conditions may result in various vulnerabilities, such as TOCTOU (time-of-check to time-of-use) issues or other types of security vulnerabilities.

There's plenty that can go wrong, and the specific issues you need to look for depends heavily on the type of application you're building.

David
  • 16,074
  • 3
  • 51
  • 74
1

No you cannot exploit deadlocks directly for malicious intent. However if an important security procedure is somehow forced into a deadlock, then it can lead to a possibility of a larger attack. A deadlock is defined as a condition which a program is no longer making progress whether it's because the program is waiting for an unavailable resource or similar reasons. You have to understand that deadlocks are usually caused by 2 (or more) competing actions/processes and is a condition possible in most operating systems and therefor must be handled appropriately. The image below is a simple example of what happens in a deadlock:

  • Process 1 needs resource 1 which is owned by process 2
  • Process 2 needs resource 2 which is owned by process 1

(both process's are waiting for the desired resource in whats called an "infinite circular-wait cycle")

Deadlock cycle

Regarding concurrent threads in you application:

If you are using multiple hardware for simultaneous processing then in some cases you have to manually manage "mutual exclusion" otherwise race occurrence is highly probable. However on a single platform, mutual exclusion is usually provided by the OS and race conditions do not occur.

Abbas Javan Jafari
  • 1,916
  • 14
  • 31
1

When a deadlock occurs, processing stops. This is a denial-of-service, which, like any other DoS, may serve as an intermediate step for a larger attack. For instance, if an Intrusion Detection System stops working (e.g. it enters a deadlock), then intrusions will be able to proceed undetected. Hollywood, in its infinite wisdom, has come up with very graphic expositions of such scenarios (that one is a classic).

Deadlocks are a classical issue in concurrent programming. They are so classical that some systems include "resurrection" safety mechanisms which try to reanimate a process past a deadlock. For instance, when a thread tries to acquire a lock which closes the deadlock circle, the locking system may detect it and not acquire the lock, instead reporting an error. If the caller does not properly check the error condition, it may proceed without the lock, modifying the data without synchronization with other callers. Data corruption and other undesirable consequences may then happen.

Avoiding deadlocks is a matter of correctness: a deadlock occurs because of a flaw in the overall application design (deadlocks are considered to be a "hard" type of bug because they cannot be pinpointed to a single location where a programmer forgot to put a test or miscomputed a constant; deadlock bugs appear at the architecture level). The relation to security is the generic one: it is not sufficient to ensure that bugs are not triggered under normal conditions, because attackers can often enforce abnormal conditions. For instance, even though the name of a normal user fits in less than 100 characters, you should still check that the name as entered by the user is not too big before trying to copy it into a 100-character buffer. Similarly, even if a deadlock cannot occur in a given application when external events happen at a "normal pace", an attacker can trigger unusual timings, e.g. launching 15 "password change" operations simultaneously on the same account.

Thomas Pornin
  • 326,555
  • 60
  • 792
  • 962