|
Forums -> Security Library Forum
Race condition with ChangeSecurityProtocol |
|
|
by Martin Plante [plantem at xceedsoft dot com] posted on 2004/02/05 |
|
There is a race condition in ChangeSecurityProtocol that can cause a NullReferenceException in (e.g.) BeginReceive.
Let's say a BeginReceive's callback gets called, and in that callback we set a manual event another thread is waiting upon to do a ChangeSecurityOptions. If in that callback we continue by calling BeginReceive again, threads can end-up there:
Thread A (in SecureSocket.ChangeSecurityOptions, line 109)
106: m_Options = (SecurityOptions)options.Clone();
107: if (options.Protocol != SecureProtocol.None) {
108: if (this.Connected)
109> m_Controller = new SocketController(this, base.InternalSocket, options);
Thread B (in SecureSocket.BeginReceive, line 472)
472> return m_Controller.BeginReceive(buffer, offset, size, callback, state);
I believe access to m_Controler should be protected (locked). The cost is minor compared with encryption. |
by Martin Plante [plantem at xceedsoft dot com] posted on 2004/02/05 |
|
More on this. Locking wouldn't be enough. As it turns out, there's a catch with async operations and ChangeSecurityOptions.
My application does an early BeginReceive, accumulates replies in a queue, and keeps calling BeginReceive.
Another part of my application can call ChangeSecurityOptions upon a particular condition.
The SecureSocket works directly with the Socket when the SecureProtocol is None, and with a SocketControler when otherwise.
So it can happen BeginReceive is called BEFORE ChangeSecurityOptions, but data is received AFTER ChangeSecurityOptions was called. Thus the controler's m_ActiveReceive is null, and you get a NullReferenceException when you call EndReceive from your callback (SocketControler.EndReceive, line 235).
Conclusion: With the current design, you must make sure no pending async operation is in the pipe when you call ChangeSecurityOptions. |
by Pieter Philippaerts [Pieter at mentalis dot org] posted on 2004/03/06 |
|
That's correct, the documentation says "Programs should only call this method if there is no active Connect, Accept, Send or Receive!" [this also includes their asynchronous counterparts]. |
|
|