Bugs caused by race conditions in multithreaded code can result in security vulnerabilities and generally unstable code that is subject to timing- related bugs. If you develop multithreaded assemblies, consider the following recommendations:
Do not cache the results of security checks .
Consider impersonation tokens .
Synchronize static class constructors .
Synchronize Dispose methods .
If your multithreaded code caches the results of a security check, perhaps in a static variable, the code is potentially vulnerable as shown in the following code sample.
public void AccessSecureResource() { _callerOK = PerformSecurityDemand(); OpenAndWorkWithResource(); _callerOK = false; } private void OpenAndWorkWithResource() { if (_callerOK) PerformTrustedOperation(); else { PerformSecurityDemand(); PerformTrustedOperation(); } }
If there are other paths to OpenAndWorkWithResource , and a separate thread calls the method on the same object, it is possible for the second thread to omit the security demand, because it sees _callerOK=true , set by another thread.
When you create a new thread, it assumes the security context defined by the process level token. If a parent thread is impersonating while it creates a new thread, the impersonation token is not passed to the new thread.
If you use static class constructors, make sure they are not vulnerable to race conditions. If, for example, they manipulate static state, add thread synchronization to avoid potential vulnerabilities.
If you develop non-synchronized Dispose implementations , the Dispose code may be called more than once on separate threads. The following code sample shows an example of this.
void Dispose() { if (null != _theObject) { ReleaseResources(_theObject); _theObject = null; } }
In this example, it is possible for two threads to execute the code before the first thread has set _ theObject reference to null. Depending on the functionality provided by the ReleaseResources method, security vulnerabilities may occur.