Bug 513176 - KMountPoint API performs insecure operations in possibly attacker controlled locations
Summary: KMountPoint API performs insecure operations in possibly attacker controlled ...
Status: REPORTED
Alias: None
Product: frameworks-kio
Classification: Frameworks and Libraries
Component: general (other bugs)
Version First Reported In: unspecified
Platform: Other Linux
: NOR normal
Target Milestone: ---
Assignee: KIO Bugs
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2025-12-10 15:00 UTC by Matthias Gerstner
Modified: 2025-12-11 11:56 UTC (History)
3 users (show)

See Also:
Latest Commit:
Version Fixed/Implemented In:
Sentry Crash Report:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Matthias Gerstner 2025-12-10 15:00:05 UTC
This topic came up in the context of the smb4k security fixes for
CVE-2025-66002 and CVE-2025-66003. KDE security suggested we provide an MR#
fixing our concerns, but this is really beyond a simple contribution and
requires deeper thought. Therefore we are creating this bug, which was the
alternative that was suggested to us.

Here is the summary of our concerns:

The implementation of `KMountPoint::currentMountPoints()` relies on the libmount
library to retrieve a list of mount points [1]. The
libmount library provides a proven implementation for safely parsing
files like `/proc/self/mountinfo`, which we reviewed ourselves a few years
ago and deemed robust. After safely obtaining the information from
libmount, the KIO library performs some actions on top, however, which
can lead to security relevant issues.

One minor issue is found in kmountpoint.cpp line 365 [2] where
`stat()` is called on the target mount directory of each mount entry. This
potentially accesses untrusted paths, also from FUSE file systems, which could
in some cases cause a local Denial-of-Service if `stat()` blocks. Also, the
supposed mount point could be unmounted by the time the `stat()` call is
performed, allowing the path to point to an arbitrary file (also following
symbolic links), which would lead to incorrect information in the `m_deviceID`
field of the information returned by `currentMountPoints()`.

Later on the code tries to "resolve GVFS mount points" in line 382 [3]. The
`resolveGvfsMountPoints()` function [4] that implements this logic looks for
mount entries with "gvfsd-fuse" as source device name. For each of these mount
points the function will list the mount's directory contents and look for
directory entries of the form `<type>:<label>`, where `type` refers to the
file system type that is expected to be mounted there. The function then
synthesizes additional mount entries from this information which will be
returned to the caller, appearing as fully-fledged regular mounts.

There are two problems with this. For one, these operations are all subject to
race conditions; the mount table entries can change at any time. Secondly,
there exists a common way for unprivileged users in Linux systems to create
mount points with arbitrary source device names. This is the `fusermount`
setuid-root utility, which is used for mounting FUSE file systems. Local users
can create a fake `gvfsd-fuse` mount point like this:

    $ export _FUSE_COMMFD=0
    $ mkdir $HOME/mnt
    $ fusermount $HOME/mnt -ononempty,fsname=gvfsd-fuse
    $ mount | tail -n1
    gvfsd-fuse on /home/$USER/mnt type fuse (rw,nosuid,nodev,relatime,user_id=1000,group_id=100)

The default FUSE configuration prevents the `root` user from accessing
non-root controlled FUSE file systems. To overcome this limitation, a local
user can perform the following steps:

- create a fake `gvfsd-fuse` mount like shown above.
- trigger the `unmount()` logic in smb4k's mount helper.
- attempt to unmount `$HOME/mnt` after `currentMountPoints()` obtained the
  mount information from libmount, but before it calls
  `resolveGvfsMountPoints()`.
- place directories in this location that match the expected format e.g.
  something like `cifs:mymount`. These directories can already be placed
  there in advance, of course.
- on success, the `currentMountPoints()` function will return a
  synthesized entry to the mount helper which lists a CIFS mount in the
  unprivileged user's `$HOME/mnt/cifs:mymount`.

Using this approach, the verification step in the smb4k's mount helper's
`unmount()` function can be bypassed even if other issues would not have been
present.

There are further potential issues in the `KMountPoint` logic, e.g. in
`finalizeCurrentMountPoint()` the source device name is resolved if the
`KMountPoint::NeedRealDeviceName` flag is passed by the caller. This provides
another opportunity for unprivileged FUSE mounts with fake source device names
to influence the outcome, e.g. to perform file existence tests or otherwise
trick the caller of the KIO library.

Due to these problems, the information obtained from `currentMountPoints()`
currently cannot be used to base security related decisions on. Generally
`root` should not perform these additional queries at all. The library could
check for `geteuid() == 0` to prevent the execution of this dangerous logic in
privileged contexts.

For unprivileged applications we could imagine the addition of a flag like
`KMountPoint::AllowUnsafe`, which opts in to the problematic behaviour. Only
applications that are aware of the potential problems would then pass this
flag.

[1]: https://invent.kde.org/frameworks/kio/-/blob/v6.17.0/src/core/kmountpoint.cpp?ref_type=tags#L341
[2]: https://invent.kde.org/frameworks/kio/-/blob/v6.17.0/src/core/kmountpoint.cpp?ref_type=tags#L365
[3]: https://invent.kde.org/frameworks/kio/-/blob/v6.17.0/src/core/kmountpoint.cpp?ref_type=tags#L382
[4]: https://invent.kde.org/frameworks/kio/-/blob/v6.17.0/src/core/kmountpoint.cpp?ref_type=tags#L267
Comment 1 Nicolas Fella 2025-12-10 15:58:29 UTC
Thanks for the report!

Have you checked if https://doc.qt.io/qt-6/qstorageinfo.html has a similar problem?
Comment 2 Matthias Gerstner 2025-12-11 11:56:37 UTC
(In reply to Nicolas Fella from comment #1)
> Have you checked if https://doc.qt.io/qt-6/qstorageinfo.html has a similar
> problem?

The larger problem, i.e. the "resolving of GVFS mount points" is specific to the KMountPoint API.

The minor problem of of possible local Denial-of-Service or violated data integrity also seem to affect QStorageInfo, since it performs at least some naive `stat()` and `open()` operations on the source devices and mount directories, for example here:

https://github.com/qt/qtbase/blob/5394adcd61eb488d2ddea8cdef839802937353d0/src/corelib/io/qstorageinfo_linux.cpp#L538

So it might be necessary to approach Qt devs as well about this.