diff options
author | Mikkel Krautz <mikkel@krautz.dk> | 2017-07-16 11:48:49 +0300 |
---|---|---|
committer | Mikkel Krautz <mikkel@krautz.dk> | 2017-07-17 11:19:21 +0300 |
commit | f6fb4d8b7567f11e64856762bcc9b434d2926268 (patch) | |
tree | 2cd09018af30f1fa7d0b64b9b1e1c5383aea6d1f /src | |
parent | 6892c8b29abe5e36bcc7a96a34dbeb5bbde4da0e (diff) |
src/tests: add TestSSLLocks test for testing our OpenSSL locking implementation.
This test tests that our SSLLocks class works correctly.
Note: Since OpenSSL 1.1, OpenSSL provides their own locking for Windows
and POSIX systems. So if you're playing around with this test, you should
only be able to make it crash OpenSSL versions prior to 1.1.
Diffstat (limited to 'src')
-rw-r--r-- | src/tests/TestSSLLocks/TestSSLLocks.cpp | 106 | ||||
-rw-r--r-- | src/tests/TestSSLLocks/TestSSLLocks.pro | 12 | ||||
-rw-r--r-- | src/tests/tests.pro | 3 |
3 files changed, 120 insertions, 1 deletions
diff --git a/src/tests/TestSSLLocks/TestSSLLocks.cpp b/src/tests/TestSSLLocks/TestSSLLocks.cpp new file mode 100644 index 000000000..9963c4350 --- /dev/null +++ b/src/tests/TestSSLLocks/TestSSLLocks.cpp @@ -0,0 +1,106 @@ +// Copyright 2005-2017 The Mumble Developers. All rights reserved. +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file at the root of the +// Mumble source tree or at <https://www.mumble.info/LICENSE>. + +#include <QtCore> +#include <QtTest> + +#include "SSL.h" +#include "QAtomicIntCompat.h" + +#include <openssl/rand.h> + +/// SSLRacer is a thread that runs operations on OpenSSL's +/// RAND infrastructure, in an attempt to crash/segfault +/// the test process. +/// +/// The thread can either query OpenSSL for random bytes, or +/// seed the RAND system. This is controlled by the |seed| +/// parameter to the constructor. +class SSLRacer : public QThread { +public: + bool m_seed; + QAtomicInt *m_running; + + SSLRacer(QAtomicInt *running, bool seed) + : m_seed(seed) + , m_running(running) { + } + + void run() { + unsigned char buf[64]; + while (QAtomicIntLoad(*m_running) == 1) { + for (int i = 0; i < 1024; i++) { + if (m_seed) { + RAND_seed(buf, sizeof(buf)); + } else { + RAND_bytes(buf, sizeof(buf)); + } + } + } + } +}; + +class TestSSLLocks : public QObject { + Q_OBJECT + private slots: + void initTestCase(); + void cleanupTestCase(); + void stress(); +}; + +void TestSSLLocks::initTestCase() { + // For OpenSSL < 1.1, if you comment out this line, + // you'll be running OpenSSL without locking callbacks + // enabled. That'll make this test fail by crashing/segfaulting. + MumbleSSL::initialize(); +} + +void TestSSLLocks::cleanupTestCase() { + MumbleSSL::destroy(); +} + +/// Stress test that our locking callbacks for OpenSSL are set up and +/// working correctly. +/// +/// We do this by spawning a bunch of SSLStresser threads. Some of the +/// threads will try to read random bytes in a tight loop. Other threads +/// will, at the same time, try to add/seed random bytes to the OpenSSL +/// RAND system. +/// +/// The idea is that without proper locking, the data races we're causing +/// should quite quickly cause the process to crash. +void TestSSLLocks::stress() { + std::vector<SSLRacer *> racers; + QAtomicInt running(1); + + // Spawn 24 threads in total. 12 readers, and 12 writers. + // Don't be too careful about cleaning up the threads. We'll either + // pass or crash, so the threads will be cleaned up either way. + int nthreads = 24; + for (int i = 0; i < nthreads; i++) { + bool seeder = i % 2; + SSLRacer *racer = new SSLRacer(&running, seeder); + racers.push_back(racer); + racer->start(); + } + + // Wait 2 seconds for a crash/segfault. + // If we don't crash within 2 seconds, we expect + // that our locking implementation works. + QTest::qSleep(2000); + + // Signal to the racers that they should stop. + running.fetchAndStoreOrdered(0); + + // Wait for all racers to complete. + for (size_t i = 0; i < racers.size(); i++) { + SSLRacer *racer = racers.at(i); + racer->wait(); + delete racer; + } +} + +QTEST_MAIN(TestSSLLocks) +#include "TestSSLLocks.moc" diff --git a/src/tests/TestSSLLocks/TestSSLLocks.pro b/src/tests/TestSSLLocks/TestSSLLocks.pro new file mode 100644 index 000000000..443c1b257 --- /dev/null +++ b/src/tests/TestSSLLocks/TestSSLLocks.pro @@ -0,0 +1,12 @@ +# Copyright 2005-2017 The Mumble Developers. All rights reserved. +# Use of this source code is governed by a BSD-style license +# that can be found in the LICENSE file at the root of the +# Mumble source tree or at <https://www.mumble.info/LICENSE>. + +include(../test.pri) + +QT += network + +TARGET = TestSSLLocks +SOURCES = SSL.cpp SSLLocks.cpp TestSSLLocks.cpp +HEADERS = SSL.h SSLLocks.h diff --git a/src/tests/tests.pro b/src/tests/tests.pro index 2b608453b..5ba7cf603 100644 --- a/src/tests/tests.pro +++ b/src/tests/tests.pro @@ -16,4 +16,5 @@ SUBDIRS += \ TestUnresolvedServerAddress \ TestServerAddress \ TestServerResolver \ - TestSelfSignedCertificate + TestSelfSignedCertificate \ + TestSSLLocks |