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

Stack overflow in nativeSelect()

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Closed
    • Priority: P1: Critical
    • Resolution: Done
    • Affects Version/s: 4.8.7, 5.6.0 Beta
    • Fix Version/s: 5.7.0 RC
    • Component/s: Network: Sockets
    • Labels:
      None
    • Environment:
      OpenBSD/amd64 5.9-BETA
    • Commits:
      105fc117b70635dbeb921a5a74be75e44ac98fe2,f0a6d45cc8ca0b17838046c1c17efbc64773f2b5,1bf1d0f493a4561239961dbe582bdc798b69a946,3fc1002489d5861d4f7cc2e1e8800881d6593c9d,acbd79996d7dedd65cda98bd1b0f15690f0271e4,e65ffae850a7265c1d477957a5b24865b91ec3ad,d28bb50b

      Description

      QNativeSocketEnginePrivate code is vulnerable to fd_set overflow. As a result, an attacker could set at least one arbitrary bit on program's stack. Due to the nature of attack, stack smashing protection doesn't help much.

      Details: the QNativeSocketEnginePrivate::nativeSelect() calls do use select() system call. The latter relies upon setting desired file descriptor being waited on in fd_set (semi-opaque) structure. "Semi-opaque" means that while its actual implementation is system-dependent, maximum number of file descriptors it could address is hardcoded at the compile time. On systems like *BSD and GNU/Linux fd_set structures contain 1024 bits by default. The FD_SET() routine (usually implemented as macro), which is used for setting exact bits, doesn't check actual boundaries, allowing to access bits outside default fd_set size.

      Let's see what will happen if some malicious application opens >1021 files and then exec()'s the Qt-based binary. If such binary will call anything in Qt that results in QNativeSocketEnginePrivate::nativeSelect() being run, then out-of-bounds access will happen. In the worst case, this will case application to misbehave, for example, due to some flag variable like "allow current user to do something" being set instead of being zero.

      The problematic code existed since Qt 4.x at least.

      The supposed solution is to change select() to poll(), which is as well standardized as select(), but doesn't suffer from the same diseases.

      Attached are:
      1. Proposed patch (tested in the environment below);
      2. PoC code.

      Sample PoC output:

      $ ./qtsmashtest
      qtsmashtest: trying socket descriptor 1029
      qtsmashtest: trying socket descriptor 1037
      qtsmashtest: trying socket descriptor 1045
      qtsmashtest: trying socket descriptor 1053
      qtsmashtest: trying socket descriptor 1061
      qtsmashtest: trying socket descriptor 1069
      qtsmashtest: trying socket descriptor 1077
      qtsmashtest: trying socket descriptor 1085
      qtsmashtest: trying socket descriptor 1093
      Abort trap (core dumped)

        Attachments

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

          Activity

            People

            Assignee:
            louai Louai Al-Khanji
            Reporter:
            pers Vadim Zhukov
            Votes:
            0 Vote for this issue
            Watchers:
            6 Start watching this issue

              Dates

              Created:
              Updated:
              Resolved:

                Gerrit Reviews

                There are no open Gerrit changes