Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-134538

QRandomGenerator, QSimd: RDSEED should be checked for validity

    XMLWordPrintable

Details

    • Bug
    • Resolution: Fixed
    • P2: Important
    • 6.9.1, 6.10.0 FF
    • 6.8.2
    • Core: Other
    • None
    • Linux 6.14-rc5
      Qt 6.8.2

      AMD Cyan Skillfish APU (Zen2 based)
      AMD BC-250 board
    • Linux/Wayland, Linux/X11, Linux/Yocto, Linux/Other display system
    • 1b8d08532 (dev), 192178393 (6.9)

    Description

      UPDATE 

      the real issue in RDSEED instruction, read the comments for details{}

       


      For some reason, in some systems, such as based on the Zen2 core, the operation of the RDRAND instruction can be disrupted in various ways.

      For example, AMD's Cyan Skillfish (aka Sony's PlayStation 5 APU) has not received a microcode update to address the RDRAND issue that was discovered in 2019 ( https://arstechnica.com/gadgets/2019/10/how-a-months-old-amd-microcode-bug-destroyed-my-weekend/ ).

      This leads to QRandomGenerator::system()->generate() to return 0xFF

       

      std::array<uint, 4> arr;
      QRandomGenerator::system()->generate(&arr[0], &arr[4]);    
      for(uint val: arr){
          std::cout << std::hex << val;
      }
      ---
      ffffffffffffffffffffffffffffffff

       

      Qt tests are also broken

      ********* Start testing of tst_QRandomGenerator *********
      Config: Using QtTest library 6.8.2, Qt 6.8.2 (x86_64-little_endian-lp64 shared (dynamic) debug build; by GCC 14.2.1 20250220 [revision 9ffecde121af883b60bbe60d00425036bc873048]), opensuse-tumbleweed 20250307
      PASS   : tst_QRandomGenerator::initTestCase()
      PASS   : tst_QRandomGenerator::basics()
      PASS   : tst_QRandomGenerator::knownSequence()
      PASS   : tst_QRandomGenerator::discard()
      PASS   : tst_QRandomGenerator::copying()
      PASS   : tst_QRandomGenerator::copyingGlobal()
      FAIL!  : tst_QRandomGenerator::copyingSystem() 'sameCount < 20' returned FALSE. ()
         Loc: [/home/bc250/Experiments/qt-build/qtbase-everywhere-src-6.8.2/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp(258)]
      PASS   : tst_QRandomGenerator::systemRng()
      FAIL!  : tst_QRandomGenerator::securelySeeding() 'sameCount < 20' returned FALSE. ()
         Loc: [/home/bc250/Experiments/qt-build/qtbase-everywhere-src-6.8.2/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp(298)]
      PASS   : tst_QRandomGenerator::generate32(fixed)
      FAIL!  : tst_QRandomGenerator::generate32(global) 'rng.generate() != rng.generate()' returned FALSE. (3rd try)
         Loc: [/home/bc250/Experiments/qt-build/qtbase-everywhere-src-6.8.2/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp(330)]
      FAIL!  : tst_QRandomGenerator::generate32(hwrng) 'rng.generate() != rng.generate()' returned FALSE. (3rd try)
         Loc: [/home/bc250/Experiments/qt-build/qtbase-everywhere-src-6.8.2/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp(330)]
      PASS   : tst_QRandomGenerator::generate32(system)
      PASS   : tst_QRandomGenerator::generate64(fixed)
      FAIL!  : tst_QRandomGenerator::generate64(global) 'rng.generate64() != rng.generate64()' returned FALSE. (3rd try)
         Loc: [/home/bc250/Experiments/qt-build/qtbase-everywhere-src-6.8.2/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp(348)]
      FAIL!  : tst_QRandomGenerator::generate64(hwrng) 'rng.generate64() != rng.generate64()' returned FALSE. (3rd try)
         Loc: [/home/bc250/Experiments/qt-build/qtbase-everywhere-src-6.8.2/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp(348)]
      PASS   : tst_QRandomGenerator::generate64(system)
      PASS   : tst_QRandomGenerator::quality(fixed)
      QDEBUG : tst_QRandomGenerator::quality(global) 27 above threshold: 227
      FAIL!  : tst_QRandomGenerator::quality(global) 'v < FailureThreshold' returned FALSE. (27)
         Loc: [/home/bc250/Experiments/qt-build/qtbase-everywhere-src-6.8.2/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp(404)]
      QDEBUG : tst_QRandomGenerator::quality(hwrng) 255 above threshold: 2048
      FAIL!  : tst_QRandomGenerator::quality(hwrng) 'v < FailureThreshold' returned FALSE. (255)
         Loc: [/home/bc250/Experiments/qt-build/qtbase-everywhere-src-6.8.2/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp(404)]
      QDEBUG : tst_QRandomGenerator::quality(system) Average: 8 (expected 8 ideally) Max: 19 at 65 Min: 2 at 136
      PASS   : tst_QRandomGenerator::quality(system)
      PASS   : tst_QRandomGenerator::fillRangeUInt(fixed)
      FAIL!  : tst_QRandomGenerator::fillRangeUInt(global) '[&] { T array[2] = {}; rng.fillRange(array); return array[0] != array[1]; }()' returned FALSE. (3rd try)
         Loc: [/home/bc250/Experiments/qt-build/qtbase-everywhere-src-6.8.2/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp(428)]
      FAIL!  : tst_QRandomGenerator::fillRangeUInt(hwrng) '[&] { T array[2] = {}; rng.fillRange(array); return array[0] != array[1]; }()' returned FALSE. (3rd try)
         Loc: [/home/bc250/Experiments/qt-build/qtbase-everywhere-src-6.8.2/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp(428)]
      PASS   : tst_QRandomGenerator::fillRangeUInt(system)
      PASS   : tst_QRandomGenerator::fillRangeULong(fixed)
      FAIL!  : tst_QRandomGenerator::fillRangeULong(global) '[&] { T array[2] = {}; rng.fillRange(array); return array[0] != array[1]; }()' returned FALSE. (3rd try)
         Loc: [/home/bc250/Experiments/qt-build/qtbase-everywhere-src-6.8.2/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp(428)]
      FAIL!  : tst_QRandomGenerator::fillRangeULong(hwrng) '[&] { T array[2] = {}; rng.fillRange(array); return array[0] != array[1]; }()' returned FALSE. (3rd try)
         Loc: [/home/bc250/Experiments/qt-build/qtbase-everywhere-src-6.8.2/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp(428)]
      PASS   : tst_QRandomGenerator::fillRangeULong(system)
      PASS   : tst_QRandomGenerator::fillRangeULLong(fixed)
      FAIL!  : tst_QRandomGenerator::fillRangeULLong(global) '[&] { T array[2] = {}; rng.fillRange(array); return array[0] != array[1]; }()' returned FALSE. (3rd try)
         Loc: [/home/bc250/Experiments/qt-build/qtbase-everywhere-src-6.8.2/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp(428)]
      FAIL!  : tst_QRandomGenerator::fillRangeULLong(hwrng) '[&] { T array[2] = {}; rng.fillRange(array); return array[0] != array[1]; }()' returned FALSE. (3rd try)
         Loc: [/home/bc250/Experiments/qt-build/qtbase-everywhere-src-6.8.2/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp(428)]
      PASS   : tst_QRandomGenerator::fillRangeULLong(system)
      PASS   : tst_QRandomGenerator::generateUInt(fixed)
      PASS   : tst_QRandomGenerator::generateUInt(global)
      PASS   : tst_QRandomGenerator::generateUInt(hwrng)
      PASS   : tst_QRandomGenerator::generateUInt(system)
      PASS   : tst_QRandomGenerator::generateULLong(fixed)
      PASS   : tst_QRandomGenerator::generateULLong(global)
      PASS   : tst_QRandomGenerator::generateULLong(hwrng)
      PASS   : tst_QRandomGenerator::generateULLong(system)
      PASS   : tst_QRandomGenerator::generateNonContiguous(fixed)
      PASS   : tst_QRandomGenerator::generateNonContiguous(global)
      PASS   : tst_QRandomGenerator::generateNonContiguous(hwrng)
      PASS   : tst_QRandomGenerator::generateNonContiguous(system)
      PASS   : tst_QRandomGenerator::bounded(0,1)
      PASS   : tst_QRandomGenerator::bounded(25,200)
      PASS   : tst_QRandomGenerator::bounded(50,200)
      PASS   : tst_QRandomGenerator::bounded(75,200)
      PASS   : tst_QRandomGenerator::boundedQuality(fixed)
      QDEBUG : tst_QRandomGenerator::boundedQuality(global) 12 above threshold: 289
      QDEBUG : tst_QRandomGenerator::boundedQuality(global) 20 above threshold: 230
      QDEBUG : tst_QRandomGenerator::boundedQuality(global) 47 above threshold: 207
      QDEBUG : tst_QRandomGenerator::boundedQuality(global) 79 above threshold: 278
      QDEBUG : tst_QRandomGenerator::boundedQuality(global) 81 above threshold: 516
      FAIL!  : tst_QRandomGenerator::boundedQuality(global) 'v < FailureThreshold' returned FALSE. (81)
         Loc: [/home/bc250/Experiments/qt-build/qtbase-everywhere-src-6.8.2/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp(626)]
      QDEBUG : tst_QRandomGenerator::boundedQuality(hwrng) 282 above threshold: 9056
      FAIL!  : tst_QRandomGenerator::boundedQuality(hwrng) 'v < FailureThreshold' returned FALSE. (282)
         Loc: [/home/bc250/Experiments/qt-build/qtbase-everywhere-src-6.8.2/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp(626)]
      QDEBUG : tst_QRandomGenerator::boundedQuality(system) Average: 32 (expected 32 ideally) Max: 46 at 78 Min: 13 at 56
      PASS   : tst_QRandomGenerator::boundedQuality(system)
      PASS   : tst_QRandomGenerator::bounded64(0,1)
      PASS   : tst_QRandomGenerator::bounded64(16,200)
      PASS   : tst_QRandomGenerator::bounded64(32,200)
      PASS   : tst_QRandomGenerator::bounded64(128,200)
      PASS   : tst_QRandomGenerator::bounded64Quality(fixed)
      QDEBUG : tst_QRandomGenerator::bounded64Quality(global) 115 above threshold: 147
      QDEBUG : tst_QRandomGenerator::bounded64Quality(global) 137 above threshold: 136
      QDEBUG : tst_QRandomGenerator::bounded64Quality(global) 152 above threshold: 284
      QDEBUG : tst_QRandomGenerator::bounded64Quality(global) 201 above threshold: 134
      QDEBUG : tst_QRandomGenerator::bounded64Quality(global) 231 above threshold: 202
      QDEBUG : tst_QRandomGenerator::bounded64Quality(global) 232 above threshold: 436
      QDEBUG : tst_QRandomGenerator::bounded64Quality(global) Average: 32 (expected 32 ideally) Max: 436 at 232 Min: 0 at 29
      PASS   : tst_QRandomGenerator::bounded64Quality(global) 
      --- HANGS HERE ---

       

      However manual invocation of RDRAND does not reproduce the issue

       unsigned long long result = 0ULL;
       _rdrand64_step(&result);
       std::cout << std::hex << result;
      
      ---
      
      37d82748c155d5c9
      

       

      Disabling RDRAND in qsimd_p.h file fixes all the qt tests:

      static inline bool qHasHwrng()
       {
      -    return qCpuHasFeature(RDRND);
      +    return false;
       } 

       

      ********* Start testing of tst_QRandomGenerator *********
      Config: Using QtTest library 6.8.2, Qt 6.8.2 (x86_64-little_endian-lp64 shared (dynamic) debug build; by GCC 14.2.1 20250220 [revision 9ffecde121af883b60bbe60d00425036bc873048]), opensuse-tumbleweed 20250307
      PASS   : tst_QRandomGenerator::initTestCase()
      PASS   : tst_QRandomGenerator::basics()
      PASS   : tst_QRandomGenerator::knownSequence()
      PASS   : tst_QRandomGenerator::discard()
      PASS   : tst_QRandomGenerator::copying()
      PASS   : tst_QRandomGenerator::copyingGlobal()
      PASS   : tst_QRandomGenerator::copyingSystem()
      PASS   : tst_QRandomGenerator::systemRng()
      PASS   : tst_QRandomGenerator::securelySeeding()
      PASS   : tst_QRandomGenerator::generate32(fixed)
      PASS   : tst_QRandomGenerator::generate32(global)
      PASS   : tst_QRandomGenerator::generate32(system)
      PASS   : tst_QRandomGenerator::generate64(fixed)
      PASS   : tst_QRandomGenerator::generate64(global)
      PASS   : tst_QRandomGenerator::generate64(system)
      PASS   : tst_QRandomGenerator::quality(fixed)
      QDEBUG : tst_QRandomGenerator::quality(global) Average: 8 (expected 8 ideally) Max: 18 at 151 Min: 2 at 56
      PASS   : tst_QRandomGenerator::quality(global)
      QDEBUG : tst_QRandomGenerator::quality(system) Average: 8 (expected 8 ideally) Max: 18 at 211 Min: 1 at 219
      PASS   : tst_QRandomGenerator::quality(system)
      PASS   : tst_QRandomGenerator::fillRangeUInt(fixed)
      PASS   : tst_QRandomGenerator::fillRangeUInt(global)
      PASS   : tst_QRandomGenerator::fillRangeUInt(system)
      PASS   : tst_QRandomGenerator::fillRangeULong(fixed)
      PASS   : tst_QRandomGenerator::fillRangeULong(global)
      PASS   : tst_QRandomGenerator::fillRangeULong(system)
      PASS   : tst_QRandomGenerator::fillRangeULLong(fixed)
      PASS   : tst_QRandomGenerator::fillRangeULLong(global)
      PASS   : tst_QRandomGenerator::fillRangeULLong(system)
      PASS   : tst_QRandomGenerator::generateUInt(fixed)
      PASS   : tst_QRandomGenerator::generateUInt(global)
      PASS   : tst_QRandomGenerator::generateUInt(system)
      PASS   : tst_QRandomGenerator::generateULLong(fixed)
      PASS   : tst_QRandomGenerator::generateULLong(global)
      PASS   : tst_QRandomGenerator::generateULLong(system)
      PASS   : tst_QRandomGenerator::generateNonContiguous(fixed)
      PASS   : tst_QRandomGenerator::generateNonContiguous(global)
      PASS   : tst_QRandomGenerator::generateNonContiguous(system)
      PASS   : tst_QRandomGenerator::bounded(0,1)
      PASS   : tst_QRandomGenerator::bounded(25,200)
      PASS   : tst_QRandomGenerator::bounded(50,200)
      PASS   : tst_QRandomGenerator::bounded(75,200)
      PASS   : tst_QRandomGenerator::boundedQuality(fixed)
      QDEBUG : tst_QRandomGenerator::boundedQuality(global) Average: 32 (expected 32 ideally) Max: 51 at 23 Min: 17 at 62
      PASS   : tst_QRandomGenerator::boundedQuality(global)
      QDEBUG : tst_QRandomGenerator::boundedQuality(system) Average: 32 (expected 32 ideally) Max: 50 at 29 Min: 18 at 112
      PASS   : tst_QRandomGenerator::boundedQuality(system)
      PASS   : tst_QRandomGenerator::bounded64(0,1)
      PASS   : tst_QRandomGenerator::bounded64(16,200)
      PASS   : tst_QRandomGenerator::bounded64(32,200)
      PASS   : tst_QRandomGenerator::bounded64(128,200)
      PASS   : tst_QRandomGenerator::bounded64Quality(fixed)
      QDEBUG : tst_QRandomGenerator::bounded64Quality(global) Average: 32 (expected 32 ideally) Max: 55 at 54 Min: 16 at 177
      PASS   : tst_QRandomGenerator::bounded64Quality(global)
      QDEBUG : tst_QRandomGenerator::bounded64Quality(system) Average: 32 (expected 32 ideally) Max: 56 at 13 Min: 17 at 134
      PASS   : tst_QRandomGenerator::bounded64Quality(system)
      PASS   : tst_QRandomGenerator::generateReal(fixed)
      PASS   : tst_QRandomGenerator::generateReal(global)
      PASS   : tst_QRandomGenerator::generateReal(system)
      PASS   : tst_QRandomGenerator::qualityReal(fixed)
      QINFO  : tst_QRandomGenerator::qualityReal(global) Halfway distribution: 49.8 - 50.2
      QINFO  : tst_QRandomGenerator::qualityReal(global) 12.7 below 1/8 (expected 12.5% ideally)
      QINFO  : tst_QRandomGenerator::qualityReal(global) 12.7 above 7/8 (expected 12.5% ideally)
      PASS   : tst_QRandomGenerator::qualityReal(global)
      QINFO  : tst_QRandomGenerator::qualityReal(system) Halfway distribution: 50.0 - 50.0
      QINFO  : tst_QRandomGenerator::qualityReal(system) 12.5 below 1/8 (expected 12.5% ideally)
      QINFO  : tst_QRandomGenerator::qualityReal(system) 12.5 above 7/8 (expected 12.5% ideally)
      PASS   : tst_QRandomGenerator::qualityReal(system)
      PASS   : tst_QRandomGenerator::seedStdRandomEngines()
      PASS   : tst_QRandomGenerator::stdUniformIntDistribution(system:0)
      PASS   : tst_QRandomGenerator::stdUniformIntDistribution(global:0)
      PASS   : tst_QRandomGenerator::stdUniformIntDistribution(system:1)
      PASS   : tst_QRandomGenerator::stdUniformIntDistribution(global:1)
      PASS   : tst_QRandomGenerator::stdUniformIntDistribution(system:199)
      PASS   : tst_QRandomGenerator::stdUniformIntDistribution(global:199)
      PASS   : tst_QRandomGenerator::stdUniformIntDistribution(system:4294967295)
      PASS   : tst_QRandomGenerator::stdUniformIntDistribution(global:4294967295)
      PASS   : tst_QRandomGenerator::stdGenerateCanonical(fixed)
      PASS   : tst_QRandomGenerator::stdGenerateCanonical(global)
      PASS   : tst_QRandomGenerator::stdGenerateCanonical(system)
      PASS   : tst_QRandomGenerator::stdUniformRealDistribution(system:0-0)
      PASS   : tst_QRandomGenerator::stdUniformRealDistribution(global:0-0)
      PASS   : tst_QRandomGenerator::stdUniformRealDistribution(system:0-1)
      PASS   : tst_QRandomGenerator::stdUniformRealDistribution(global:0-1)
      PASS   : tst_QRandomGenerator::stdUniformRealDistribution(system:0-200)
      PASS   : tst_QRandomGenerator::stdUniformRealDistribution(global:0-200)
      PASS   : tst_QRandomGenerator::stdUniformRealDistribution(system:0-4.29497e+09)
      PASS   : tst_QRandomGenerator::stdUniformRealDistribution(global:0-4.29497e+09)
      PASS   : tst_QRandomGenerator::stdUniformRealDistribution(system:0-1.84467e+19)
      PASS   : tst_QRandomGenerator::stdUniformRealDistribution(global:0-1.84467e+19)
      PASS   : tst_QRandomGenerator::stdUniformRealDistribution(system:-1-1.6)
      PASS   : tst_QRandomGenerator::stdUniformRealDistribution(global:-1-1.6)
      PASS   : tst_QRandomGenerator::stdRandomDistributions()
      PASS   : tst_QRandomGenerator::cleanupTestCase()
      Totals: 82 passed, 0 failed, 0 skipped, 0 blacklisted, 35ms
      ********* Finished testing of tst_QRandomGenerator ********* 

       

      Probably on Linux systems, Qt should not use RDRAND and rely on /dev/urandom, which should produce the best possible hardware random on the system

      Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            mixaill Mikhail
            mixaill Mikhail
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes