F-5714: hold WolfSSLX509Name lock across setSubjectName native call
parent
e6fb3844a4
commit
844c9a9013
|
|
@ -127,7 +127,8 @@ public class WolfSSLCertRequest {
|
|||
* @param name Initialized and populated WolfSSLX509 name to be set into
|
||||
* Subject Name of WolfSSLCertRequest for cert generation.
|
||||
*
|
||||
* @throws IllegalStateException if WolfSSLCertRequest has been freed.
|
||||
* @throws IllegalStateException if WolfSSLCertRequest has been freed, or
|
||||
* if the provided WolfSSLX509Name has been freed.
|
||||
* @throws WolfSSLException if native JNI error occurs.
|
||||
*/
|
||||
public void setSubjectName(WolfSSLX509Name name)
|
||||
|
|
@ -142,9 +143,12 @@ public class WolfSSLCertRequest {
|
|||
WolfSSLDebug.INFO, this.x509ReqPtr,
|
||||
() -> "entered setSubjectName(" + name + ")");
|
||||
|
||||
/* TODO somehow lock WolfSSLX509Name object while using pointer? */
|
||||
ret = X509_REQ_set_subject_name(this.x509ReqPtr,
|
||||
/* Synchronize on the name so its free() can't release the native
|
||||
* pointer during the call below. */
|
||||
synchronized (name) {
|
||||
ret = X509_REQ_set_subject_name(this.x509ReqPtr,
|
||||
name.getNativeX509NamePtr());
|
||||
}
|
||||
}
|
||||
|
||||
if (ret != WolfSSL.SSL_SUCCESS) {
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@ import java.io.File;
|
|||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import java.security.PublicKey;
|
||||
import java.security.PrivateKey;
|
||||
|
|
@ -725,4 +727,64 @@ public class WolfSSLCertRequestTest {
|
|||
throws IOException {
|
||||
Files.write(new File(path).toPath(), csr);
|
||||
}
|
||||
|
||||
/* setSubjectName() holds the WolfSSLX509Name lock across the native call
|
||||
* so a concurrent free() cannot free the pointer mid-call. Races the two
|
||||
* operations to check concurrency safety and deadlock-freedom of the added
|
||||
* locking, tolerating the expected exceptions when free() wins the race. */
|
||||
@Test(timeout = 60000)
|
||||
public void testSetSubjectNameFreeRace()
|
||||
throws WolfSSLException, WolfSSLJNIException, InterruptedException {
|
||||
|
||||
Assume.assumeTrue(WolfSSL.certReqEnabled());
|
||||
|
||||
final int iterations = 200;
|
||||
final AtomicReference<Throwable> failure =
|
||||
new AtomicReference<Throwable>();
|
||||
|
||||
for (int i = 0; i < iterations && failure.get() == null; i++) {
|
||||
|
||||
final WolfSSLCertRequest req = new WolfSSLCertRequest();
|
||||
final WolfSSLX509Name name = GenerateTestSubjectName();
|
||||
final CountDownLatch start = new CountDownLatch(1);
|
||||
|
||||
Thread setter = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
start.await();
|
||||
req.setSubjectName(name);
|
||||
} catch (IllegalStateException | WolfSSLException e) {
|
||||
/* expected if free() won the race */
|
||||
} catch (Throwable t) {
|
||||
failure.compareAndSet(null, t);
|
||||
}
|
||||
}
|
||||
});
|
||||
Thread freer = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
start.await();
|
||||
name.free();
|
||||
} catch (Throwable t) {
|
||||
failure.compareAndSet(null, t);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
setter.start();
|
||||
freer.start();
|
||||
start.countDown();
|
||||
setter.join();
|
||||
freer.join();
|
||||
|
||||
name.free();
|
||||
req.free();
|
||||
}
|
||||
|
||||
if (failure.get() != null) {
|
||||
throw new AssertionError(
|
||||
"unexpected error during setSubjectName/free race",
|
||||
failure.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue