...
Wiki Markup |
---|
However, the pattern also introduces additional overheads not seen in sequential execution, including the time and resourceresources required for thread- creation and scheduling, for task processing, for resource allocation and deallocation, and for frequent context switching \[[Lea 2000|AA. Bibliography#Lea 00]\]. Furthermore, an attacker can cause a denial of service (DoS) by overwhelming the system with too many requests all at once, causing the system to become unresponsive rather than degrading gracefully. From a safety perspective, one component can exhaust all resources because of an intermittent error, consequently starving all other components. |
Thread pools allow a system to limit the maximum number of simultaneous requests that it processes to a number that it can comfortably serve , rather than terminating all services when presented with a deluge of requests. Thread pools overcome these issues by controlling the maximum number of worker threads that can execute concurrently. Each object that supports thread pools accepts a Runnable
or Callable<T>
task and stores it in a temporary queue until resources become available. Additionally, thread life-cycle management overhead is minimized because the threads in a thread pool can be reused and can be efficiently added to or removed from the pool.
Programs that use multiple threads to serve requests should — and security-sensitive programs programs that may be subjected to DoS attacks must — ensure graceful degradation of service during traffic bursts. Use of thread pools is one acceptable approach to meeting this requirement.
...
This noncompliant code example demonstrates the thread-per-message design pattern. The RequestHandler
class provides a public static factory method so that callers can obtain its a RequestHandler
instance. The handleRequest()
method is subsequently invoked to handle each request in its own thread.
Code Block | ||
---|---|---|
| ||
class Helper { public void handle(Socket socket) { //... } } final class RequestHandler { private final Helper helper = new Helper(); private final ServerSocket server; private RequestHandler(int port) throws IOException { server = new ServerSocket(port); } public static RequestHandler newInstance() throws IOException { return new RequestHandler(0); // Selects next available port } public void handleRequest() { new Thread(new Runnable() { public void run() { try { helper.handle(server.accept()); } catch (IOException e) { // Forward to handler } } }).start(); } } |
The thread-per-message strategy fails to provide graceful degradation of service. As threads are created, processing continues normally until some scarce resource is exhausted. For example, a system may allow only a limited number of open file descriptors , even though additional threads can be created to serve requests. When the scarce resource is memory, the system may fail abruptly, resulting in a denial of serviceDoS.
Compliant Solution (Thread Pool)
...
Code Block | ||
---|---|---|
| ||
// class Helper remains unchanged final class RequestHandler { private final Helper helper = new Helper(); private final ServerSocket server; private final ExecutorService exec; private RequestHandler(int port, int poolSize) throws IOException { server = new ServerSocket(port); exec = Executors.newFixedThreadPool(poolSize); } public static RequestHandler newInstance(int poolSize) throws IOException { return new RequestHandler(0, poolSize); } public void handleRequest() { Future<?> future = exec.submit(new Runnable() { @Override public void run() { try { helper.handle(server.accept()); } catch (IOException e) { // Forward to handler } } }); } // ... other methods such as shutting down the thread pool // and task cancellation ... } |
Wiki Markup |
---|
According to the Java API documentation for the {{Executor}} interface \[[API 2006|AA. Bibliography#API 06]\] |
Wiki Markup \[The Interfaceinterface {{Executor}} is\] Anan object that executes submitted {{Runnable}} tasks. This interface provides a way of decoupling task submission from the mechanics of how each task will be run, including details of thread use, scheduling, etc. An {{Executor}} is normally used instead of explicitly creating threads.
...
Wiki Markup |
---|
The choice of the unbounded {{newFixedThreadPool}} may be inappropriate. Refer to the Java API documentation for guidance on choosing betweenamong the following methods to meet specific design requirements \[[API 2006|AA. Bibliography#API 06]\]: |
...
Using simplistic concurrency primitives to process an unbounded number of requests could result in severe performance degradation, deadlock, or system resource exhaustion and denial of serviceDoS.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
TPS00-J | low | probable | high | P2 | L3 |
Related Guidelines
CWE-405, "Asymmetric Resource Consumption (Amplification)" . Asymmetric resource consumption (amplification) | |
| CWE-410, "Insufficient Resource Pool" . Insufficient resource pool |
Bibliography
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="1ba0ea6495428ca1-bab78608-439742eb-abd0a965-c84ec9d20ce84c05390d538c"><ac:plain-text-body><![CDATA[ | [[API 2006 | AA. Bibliography#API 06]] | [Interface Executor | http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/Executor.html] | ]]></ac:plain-text-body></ac:structured-macro> |
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="8123283e7924c4ee-c0cc07de-47664455-9469b597-a038bc86e03ed9572a060010"><ac:plain-text-body><![CDATA[ | [[Lea 2000 | AA. Bibliography#Lea 00]] | Section 4.1.3, Thread-Per-Message and ; 4.1.4, Worker Threads | ]]></ac:plain-text-body></ac:structured-macro> | |
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="ec5a0f0af6ca2c08-61e94f3e-4908478a-b7e2964e-cac0c6270f9c0fba8abaf879"><ac:plain-text-body><![CDATA[ | [[Tutorials 2008 | AA. Bibliography#Tutorials 08]] | [Thread Pools | http://java.sun.com/docs/books/tutorial/essential/concurrency/pools.html] | ]]></ac:plain-text-body></ac:structured-macro> |
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="5d87248c0391d638-51780cd4-4e874d18-971fbdf7-6ea8dfb3543df2a238efdcf8"><ac:plain-text-body><![CDATA[ | [[Goetz 2006 | AA. Bibliography#Goetz 06]] | Chapter 8, Applying Thread Pools | ]]></ac:plain-text-body></ac:structured-macro> |
...