Bug#901062: qtbase5-dev: qtbase5-dev: QFile::exists() returns false for existing files?!

2018-06-08 Thread Wearenotalone
Found the bug.

Docker uses seccomp security profiles to restrict e.g. system calls [1].
In docker 17.05 system call "statx" is blocked [2][3], in trunk and in
18.04 which is not released yet that system call will be allowed [4][5].
By running the docker container with "--security-opt seccomp=unconfined"
or "--privileged" the system call "statx" not blocked [5] and everything
works as excepted: QFile::exists() returns true for existing files.

Older revisions of QFile (e.g. qt 5.7 from debian stretch) do work as
excepted even when statx is blocked, because they do not use system call
"statx".

That system call is not necessary to find out if a file exists. Qt is
able to detect whether "statx" is supported. But it fails to detect that
its call is not permitted. The reason for that is in
src/corelib/io/qfilesystemengine_unix.cpp which is still present in
latest upstream revision [6]. But lets start from the beginning:

QFile::exists() returns true if ExistsFlag is set [7]. Attributes are
set in "QFSFileEnginePrivate::doStat" [10]. This function first reads
attributes with 2-args-function-overload
"QFileSystemEngine::fillMetaData" [11] and then loads the missing
attributes with 3-args-function-overload
"QFileSystemEngine::fillMetaData" [12]. Boths overloads suffer from the
same bug.

The 2-args-overload "bool QFileSystemEngine::fillMetaData(int fd,
QFileSystemMetaData )" [11] calls "qt_fstatx". QtCore in debian sid
was build with a kernel that supports the statx system call and thus
function "qt_fstatx" does indeed call "syscall(SYS_statx, ...)". If this
syscall is blocked, then "syscall(...)" returns -1 and errno is set to 1
(EPERM == "Operation not permitted") [13]. Back in
"QFileSystemEngine::fillMetaData" [11] look at this code snippet:

  int ret = qt_fstatx(fd, );
  if (ret != -ENOSYS) {
  if (ret == 0) {
  data.fillFromStatxBuf(statxBuffer);
  return true;
  }
  return false;
  }

If statx is blocked, then ret==-EPERM (negated in [14]), which means
"return false" is executed, thus no attributes are read.

"QFSFileEnginePrivate::doStat" now executes the 3-args-overload "bool
QFileSystemEngine::fillMetaData(const QFileSystemEntry ,
QFileSystemMetaData , QFileSystemMetaData::MetaDataFlags what)"
[12]. It contains this snippet:

  statResult = qt_lstatx(nativeFilePath, );
  if (statResult == -ENOSYS) {
  //...
  } else if (statResult == 0) {
  //...
  }
 
  if (statResult >= 0) {
  //...
  } else {
  // it doesn't exist
  entryErrno = errno;
  data.knownFlagsMask |= QFileSystemMetaData::ExistsAttribute;
  }

When statx is blocked then statResult is -1 (-EPERM) and thus last
branch is executed. Thus 3-args-overload of fillMetaData says "i know
that file does not exist" (knownFlagsMask has ExistsAttribute but
entryFlags has not). The code "data.entryFlags |= flag |
QFileSystemMetaData::ExistsAttribute;" later in that function [16] is
never executed because entryErrno equals -1 (-EPERM).

Thus QFile always returns false, for all files, even existing once, as
long as statx is supported but blocked via e.g. seccomp.

Cheers,
Jakob


[1] https://github.com/Microsoft/docker/blob/master/docs/security/seccomp.md
[2] debian package "docker-engine" currently available for stretch is
17.05.0~ce-0~debian-stretch
[3] https://github.com/moby/moby/blob/17.05.x/profiles/seccomp/default.json
[4] https://github.com/moby/moby/blob/master/profiles/seccomp/default.json
[5] https://github.com/docker/for-linux/issues/208
[6]
https://code.qt.io/cgit/qt/qtbase.git/tree/src/corelib/io/qfilesystemengine_unix.cpp
[7] https://code.qt.io/cgit/qt/qtbase.git/tree/src/corelib/io/qfile.cpp#n425
[8] -DELETED-
[9] -DELETED-
[10]
https://code.qt.io/cgit/qt/qtbase.git/tree/src/corelib/io/qfsfileengine_unix.cpp#n419
[11]
https://code.qt.io/cgit/qt/qtbase.git/tree/src/corelib/io/qfilesystemengine_unix.cpp#n439
[12]
https://code.qt.io/cgit/qt/qtbase.git/tree/src/corelib/io/qfilesystemengine_unix.cpp#n931
[13] /usr/include/asm-generic/errno-base.h
[14]
https://code.qt.io/cgit/qt/qtbase.git/tree/src/corelib/io/qfilesystemengine_unix.cpp#n350
[15]
https://code.qt.io/cgit/qt/qtbase.git/tree/src/corelib/io/qfilesystemengine_unix.cpp#n979
[16]
https://code.qt.io/cgit/qt/qtbase.git/tree/src/corelib/io/qfilesystemengine_unix.cpp#n1053

Am 08.06.2018 um 20:54 schrieb Dmitry Shachnev:
> Hi Jakob!
>
> On Fri, Jun 08, 2018 at 04:01:54PM +0200, Wearenotalone wrote:
>> did a fresh install of debian sid within docker and stumbled upon this
>> bug in QFile:
>> QFile's method exists() returns false even if that file exists.
> Thanks for your bug report and the test case.
>
> Can you please obtain strace of your example and attach it?
> I am not able to reproduce this issue, but I would like to compare yours
> and mine strace outputs.
>
> --
> Dmitry Shachnev



Bug#901062: qtbase5-dev: qtbase5-dev: QFile::exists() returns false for existing files?!

2018-06-08 Thread Lisandro Damián Nicanor Pérez Meyer
[big snip]


>>
>> > in 4.13. A fallback mechanism might be codable, but someone needs to do
>> the
>> > job.
>>
>> I think you are mistaken here. Qt depends on getrandom(2) syscall that was
>> added in kernel 3.17 (see #895718), but that is not related to
>> QFile::exists()
>> in any way.
>>
>> Regarding this issue, I cannot reproduce it yet.
>
>
> I was told it produces another "interesting" side effects which do not
> appear to be related.
>
> But testing with a newer kernel should be enough.
>

Sorry, I clearly mixed kernel versions. Please forget what I've said.

>


Bug#901062: qtbase5-dev: qtbase5-dev: QFile::exists() returns false for existing files?!

2018-06-08 Thread Dmitry Shachnev
Hi Jakob!

On Fri, Jun 08, 2018 at 04:01:54PM +0200, Wearenotalone wrote:
> did a fresh install of debian sid within docker and stumbled upon this
> bug in QFile:
> QFile's method exists() returns false even if that file exists.

Thanks for your bug report and the test case.

Can you please obtain strace of your example and attach it?
I am not able to reproduce this issue, but I would like to compare yours
and mine strace outputs.

--
Dmitry Shachnev


signature.asc
Description: PGP signature


Bug#901062: qtbase5-dev: qtbase5-dev: QFile::exists() returns false for existing files?!

2018-06-08 Thread Lisandro Damián Nicanor Pérez Meyer
El vie., 8 de jun. de 2018 15:44, Dmitry Shachnev 
escribió:

> Hi Lisandro!
>
> On Fri, Jun 08, 2018 at 01:34:12PM -0300, Lisandro Damián Nicanor Pérez
> Meyer wrote:
> > -- System Information:
> > > Debian Release: buster/sid
> > >   APT prefers unstable
> > >   APT policy: (500, 'unstable')
> > > Architecture: amd64 (x86_64)
> > >
> > > Kernel: Linux 4.9.0-6-amd64 (SMP w/4 CPU cores)
> >
> > Old kernel. Qt requests an interface that, if I'm not mistaken, was added
> > in 4.13. A fallback mechanism might be codable, but someone needs to do
> the
> > job.
>
> I think you are mistaken here. Qt depends on getrandom(2) syscall that was
> added in kernel 3.17 (see #895718), but that is not related to
> QFile::exists()
> in any way.
>
> Regarding this issue, I cannot reproduce it yet.


I was told it produces another "interesting" side effects which do not
appear to be related.

But testing with a newer kernel should be enough.


Bug#901062: qtbase5-dev: qtbase5-dev: QFile::exists() returns false for existing files?!

2018-06-08 Thread Dmitry Shachnev
Hi Lisandro!

On Fri, Jun 08, 2018 at 01:34:12PM -0300, Lisandro Damián Nicanor Pérez Meyer 
wrote:
> -- System Information:
> > Debian Release: buster/sid
> >   APT prefers unstable
> >   APT policy: (500, 'unstable')
> > Architecture: amd64 (x86_64)
> >
> > Kernel: Linux 4.9.0-6-amd64 (SMP w/4 CPU cores)
>
> Old kernel. Qt requests an interface that, if I'm not mistaken, was added
> in 4.13. A fallback mechanism might be codable, but someone needs to do the
> job.

I think you are mistaken here. Qt depends on getrandom(2) syscall that was
added in kernel 3.17 (see #895718), but that is not related to QFile::exists()
in any way.

Regarding this issue, I cannot reproduce it yet.

--
Dmitry Shachnev


signature.asc
Description: PGP signature


Bug#901062: qtbase5-dev: qtbase5-dev: QFile::exists() returns false for existing files?!

2018-06-08 Thread Lisandro Damián Nicanor Pérez Meyer
Hi!

El vie., 8 de jun. de 2018 11:12, Wearenotalone 
escribió:

> Package: qtbase5-dev
> Version: 5.10.1+dfsg-7
> Severity: normal
>
>
> Dear Maintainer,
>
> did a fresh install of debian sid within docker and stumbled upon this
> bug in QFile:
> QFile's method exists() returns false even if that file exists.
>

[snip]


BUT surprisingly KDE apps like akregator have successfully been build
> for debian sid but fail for me/my sid install. They should have suffered
> the same problems during build because they also use desktoptojson
> during build.
>
> Any ideas?
>


Yes


-- System Information:
> Debian Release: buster/sid
>   APT prefers unstable
>   APT policy: (500, 'unstable')
> Architecture: amd64 (x86_64)
>
> Kernel: Linux 4.9.0-6-amd64 (SMP w/4 CPU cores)
>


Old kernel. Qt requests an interface that, if I'm not mistaken, was added
in 4.13. A fallback mechanism might be codable, but someone needs to do the
job.


Bug#901062: qtbase5-dev: qtbase5-dev: QFile::exists() returns false for existing files?!

2018-06-08 Thread Wearenotalone
Package: qtbase5-dev
Version: 5.10.1+dfsg-7
Severity: normal


Dear Maintainer,
 
did a fresh install of debian sid within docker and stumbled upon this
bug in QFile:
QFile's method exists() returns false even if that file exists.



STEPS TO REPRODUCE:

$ cat << 'EOF' >> /tmp/CMakeLists.txt
cmake_minimum_required(VERSION 3.0)

project(test)

find_package(Qt5Core REQUIRED)

add_executable(tgt main.cpp)

target_link_libraries(tgt Qt5::Core)
EOF

$ cat << 'EOF' >> /tmp/main.cpp
#include 
#include 
#include 
#include 

int main() {
    QString path{"/bin/sh"};
    QFile qf{path};
    QFileInfo qfi{path};
    std::cout << "TRUE:=" << true << std::endl;
    std::cout << "QFile::exists() == " << qf.exists() << std::endl;
    std::cout << "QFileInfo::exists() == " << qfi.exists() << std::endl;
    return 0;
}
EOF

$ cmake .
-- The C compiler identification is GNU 7.3.0
-- The CXX compiler identification is GNU 7.3.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /tmp/

$ make
Scanning dependencies of target tgt
[ 50%] Building CXX object CMakeFiles/tgt.dir/main.cpp.o
[100%] Linking CXX executable tgt
[100%] Built target tgt

$ ./tgt
TRUE:=1
QFile::exists() == 0
QFileInfo::exists() == 1



EXPECTED RESULT (same as in debian stretch):

$ ./tgt
TRUE:=1
QFile::exists() == 1
QFileInfo::exists() == 1



QFile is quite fundamental to Qt and KDE. For me it prevented
compilation of kdevelop from git because kdevelop uses desktoptojson
(from libkf5coreaddons-dev-bin) during build which fails due to this bug
(QFile is used in line 312 in file
kcoreaddons-5.46.0/src/lib/plugin/desktopfileparser.cpp)..

So far I was unable to locate the bug. QFile's code
(src/corelib/io/qfile.cpp) didn't change much from
qtbase-opensource-src-5.7.1 (stretch) to qtbase-opensource-src-5.10.1
(sid), so my guess is its somewhere in
/src/corelib/io/qabstractfileengine.cpp or even lower.

BUT surprisingly KDE apps like akregator have successfully been build
for debian sid but fail for me/my sid install. They should have suffered
the same problems during build because they also use desktoptojson
during build.

Any ideas?

Cheers
Jakob



-- System Information:
Debian Release: buster/sid
  APT prefers unstable
  APT policy: (500, 'unstable')
Architecture: amd64 (x86_64)

Kernel: Linux 4.9.0-6-amd64 (SMP w/4 CPU cores)
Locale: LANG=C, LC_CTYPE=C (charmap=ANSI_X3.4-1968), LANGUAGE=C
(charmap=ANSI_X3.4-1968)
Shell: /bin/sh linked to /bin/dash
Init: unable to detect

Versions of packages qtbase5-dev depends on:
ii  libgl1-mesa-dev [libgl-dev]    18.0.5-1
ii  libglu1-mesa-dev [libglu-dev]  9.0.0-2.1
ii  libqt5concurrent5  5.10.1+dfsg-7
ii  libqt5core5a   5.10.1+dfsg-7
ii  libqt5dbus5    5.10.1+dfsg-7
ii  libqt5gui5 5.10.1+dfsg-7
ii  libqt5network5 5.10.1+dfsg-7
ii  libqt5printsupport5    5.10.1+dfsg-7
ii  libqt5sql5 5.10.1+dfsg-7
ii  libqt5test5    5.10.1+dfsg-7
ii  libqt5widgets5 5.10.1+dfsg-7
ii  libqt5xml5 5.10.1+dfsg-7
ii  libxext-dev    2:1.3.3-1+b2
ii  qt5-qmake  5.10.1+dfsg-7
ii  qtbase5-dev-tools  5.10.1+dfsg-7
ii  qtchooser  64-ga1b6736-5

Versions of packages qtbase5-dev recommends:
ii  libqt5opengl5-dev  5.10.1+dfsg-7

Versions of packages qtbase5-dev suggests:
ii  default-libmysqlclient-dev  1.0.4
pn  firebird-dev    
ii  libegl1-mesa-dev    18.0.5-1
ii  libgl1-mesa-dev 18.0.5-1
ii  libpq-dev   10.4-2
ii  libsqlite3-dev  3.23.1-1
ii  unixodbc-dev    2.3.6-0.1

-- no debconf information