mtab_file_changed_id might be set on thread default context, but it is
always cleared on the global context because of usage of g_idle_add. This
can cause the emission of redundant "mounts-change" signals. This should
not cause any issues to the client application, but let's attach the idle
source to the thread-default context instead to avoid those races for sure.
The `get_mounts_timestamp()` function uses `mount_poller_time` when
`proc_mounts_watch_source` is set, but the `mount_poller_time` is not
initialized in the same time as `proc_mounts_watch_source`. This may
cause that zero, or some outdated value is returned. Let's initialize
`mount_poller_time` to prevent invalid values to be returned.
The Nautilus test suite often crashes with "GLib-FATAL-CRITICAL:
g_source_is_destroyed: assertion 'g_atomic_int_get (&source->ref_count)
> 0' failed" if it is started with "GIO_USE_VOLUME_MONITOR=unix". This
is because GUnixMountMonitor is simultaneously used from multiple
threads over GLocalFile and GVolumeMonitor APIs. Let's add guards for
proc_mounts_watch_source and mount_poller_time variables to prevent
those crashes.
Fixes: https://gitlab.gnome.org/GNOME/glib/issues/2030
There were a couple of custom paths which could end up being relative,
rather than absolute, due to not properly prefixing them with
`get_option('prefix')`.
The use of `join_paths()` here correctly drops all path components
before the final absolute path in the list of arguments. So if someone
configures GLib with an absolute path for `gio_module_dir`, that will be
used unprefixed; but if someone configures with a relative path, it will
be prefixed by `get_option('prefix)`.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Fixes: #1919
This is a fairly large refactoring. The highlights are:
- Removing in-progress connections/addresses from GSocketClientAsyncConnectData:
This caused issues where multiple ConnectionAttempt's would step over eachother
and modify shared state causing bugs like accidentally bypassing a set proxy.
Fixes#1871Fixes#1989Fixes#1902
- Cancelling address enumeration on error/completion
- Queuing successful TCP connections and doing application layer work serially:
This is more in the spirit of Happy Eyeballs but it also greatly simplifies
the flow of connection handling so fewer tasks are happening in parallel
when they don't need to be.
The behavior also should more closely match that of g_socket_client_connect().
- Better track the state of address enumeration:
Previously we were over eager to treat enumeration finishing as an error.
Fixes#1872
See also #1982
- Add more detailed documentation and logging.
Closes#1995
(cherry picked from commit 2722620e32)
Some CI platforms invoke these tests with euid != 0 but with
capabilities. Detect whether we have Linux CAP_DAC_OVERRIDE or other
OSs' equivalents, and skip tests that rely on DAC permissions being
denied if we do have that privilege.
(Cherry pick to 2.62: Fix one minor cherry-pick conflict.)
Signed-off-by: Simon McVittie <smcv@collabora.com>
Fixes: https://gitlab.gnome.org/GNOME/glib/issues/2027
Fixes: https://gitlab.gnome.org/GNOME/glib/issues/2028
This is the analogue of commit 7c4e6e9fbe, but applied to the
`GDBusMessage` parser, which does its own top-level parsing of the
variant format in D-Bus messages.
Previously, this code allowed arbitrary recursion of variant containers,
which could lead to a stack overflow. Now, that recursion is limited to
64 levels, as per the D-Bus specification:
https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-marshaling-signature
This includes a new unit test.
oss-fuzz#14870
Signed-off-by: Philip Withnall <withnall@endlessm.com>
We got a complaint here that trashing via the
portal deletes the target of a symlink, not the
symlink itself. It turns out that following the
symlink already happens on the glib side.
https://github.com/flatpak/xdg-desktop-portal/issues/412
_kqsub_free assumes the caller has called _kqsub_cancel before calling
it. It checks if both 'deps' and 'fd' have been freed and aborts when
the condition is not met. Since the only caller of _kqsub_free is
g_kqueue_file_monitor_finalize, which does call _kqsub_cancel before
calling _kqsub_free, it seems to be correct for _kqsub_free to assert
values of these two members there.
However, it is possible for _kqsub_cancel to return early without
freeing any resource _kqsub_free expects to be freed. When the kevent
call fails, _kqsub_cancel does not free anything and _kqsub_free aborts
with assertion failure. This is an unexpected behavior, and it can be
fixed by always freeing resources in _kqsub_cancel.
Fixes: https://gitlab.gnome.org/GNOME/glib/issues/1935
This bypasses any issues we might have with containers where IPv6 is
returned by name resolution (particularly since GNOME/glib!616) but
doesn't necessarily actually work.
This comes at a minor test-coverage cost: we don't test GDBusServer's
default behaviour when told to listen on "tcp:" or "nonce-tcp:", and
on systems where IPv6 is available, we don't test it. If we want to
do those, we should perhaps do them in separate tests, and disable
those tests when binding to ::1 doesn't work.
Mitigates: GNOME/glib#1912
Signed-off-by: Simon McVittie <smcv@collabora.com>
(cherry picked from commit 7021b84f10)
Previously, we used unix:tmpdir, except in tests that verify that a
particular address type works (notably unix:dir). Now we use unix:dir
most of the time, and unix:tmpdir gets its own test instead.
This helps to ensure that the tests continue to work on non-Linux Unix
kernels, where abstract sockets do not exist and so unix:tmpdir is
equivalent to unix:dir, even in the common case where the developer has
only tried the test on Linux.
Signed-off-by: Simon McVittie <smcv@collabora.com>
Otherwise, since GNOME/glib!1193, the listening socket won't be deleted,
and if we are not using abstract sockets (for example on *BSD), g_rmdir
will fail with ENOTEMPTY.
Fixes: 8e32b8e8 "gdbusserver: Delete socket and nonce file when stopping server"
Resolves: GNOME/glib#1921
Signed-off-by: Simon McVittie <smcv@collabora.com>
The `on_run()` function could be executed in any worker thread from the
`GThreadedSocketListener`, but didn’t previously hold a strong reference
to the `GDBusServer`, which meant the server could be finalised in
another thread while `on_run()` was still running.
This was not ideal.
Hold a strong reference to the `GDBusServer` while the socket listener
is listening, i.e. between every paired call to `g_dbus_server_start()`
and `g_dbus_server_stop()`.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Fixes: #1318
Rather than when finalising it. They should be automatically recreated
if the server is re-started.
This is important for ensuring that all externally visible behaviour of
the `GDBusServer` is synchronised with calls to
g_dbus_server_{start,stop}(). Finalisation of the server object could
happen an arbitrarily long time after g_dbus_server_stop() is called.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Helps: #1318
So that the tests all end up using separate `.dbus-keyring` directories,
and hence not racing to create and acquire lock files, use
`G_TEST_OPTION_ISOLATE_DIRS` to ensure they all run in separate
disposable directories.
This has the added benefit of meaning they don’t touch the developer’s
actual `$HOME` directory.
This reduces the false-failure rate of `gdbus-peer` by a factor of 9 for
me on my local machine.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Fixes: #1912
There’s actually no need for them to be global or reused between unit
tests, so move them inside the test functions.
This is one step towards eliminating shared state between the unit
tests.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Helps: #1912
If the directory is overridden, for example when running tests, the
parent directory of `.dbus-keyrings` (i.e. the fake `$HOME` directory)
might not exist. Create it automatically.
This should realistically not have an effect on non-test code.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Helps: #1912
These can be hit in the tests (if multiple tests run in parallel are
racing for `~/.dbus-keyrings/org_gtk_gdbus_general.lock` for a prolonged
period) and will cause spurious test failures due to the use of
`G_DEBUG=fatal-warnings`.
Instead, allow the error messages to be inspected programmatically.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Helps: #1912
Conceptually, a D-Bus server is really trying to determine the credentials
of (the process that initiated) a connection, not the credentials that
the process had when it sent a particular message. Ideally, it does
this with a getsockopt()-style API that queries the credentials of the
connection's initiator without requiring any particular cooperation from
that process, avoiding a class of possible failures.
The leading '\0' in the D-Bus protocol is primarily a workaround
for platforms where the message-based credentials-passing API is
strictly better than the getsockopt()-style API (for example, on
FreeBSD, SCM_CREDS includes a process ID but getpeereid() does not),
or where the getsockopt()-style API does not exist at all. As a result
libdbus, the reference implementation of D-Bus, does not implement
Linux SCM_CREDENTIALS at all - it has no reason to do so, because the
SO_PEERCRED socket option is equally informative.
This change makes GDBusServer on Linux more closely match the behaviour
of libdbus.
In particular, GNOME/glib#1831 indicates that when a libdbus client
connects to a GDBus server, recvmsg() sometimes yields a SCM_CREDENTIALS
message with cmsg_data={pid=0, uid=65534, gid=65534}. I think this is
most likely a race condition in the early steps to connect:
client server
connect
accept
send '\0' <- race -> set SO_PASSCRED = 1
receive '\0'
If the server wins the race:
client server
connect
accept
set SO_PASSCRED = 1
send '\0'
receive '\0'
then everything is fine. However, if the client wins the race:
client server
connect
accept
send '\0'
set SO_PASSCRED = 1
receive '\0'
then the kernel does not record credentials for the message containing
'\0' (because SO_PASSCRED was 0 at the time). However, by the time the
server receives the message, the kernel knows that credentials are
desired. I would have expected the kernel to omit the credentials header
in this case, but it seems that instead, it synthesizes a credentials
structure with a dummy process ID 0, a dummy uid derived from
/proc/sys/kernel/overflowuid and a dummy gid derived from
/proc/sys/kernel/overflowgid.
In an unconfigured GDBusServer, hitting this race condition results in
falling back to DBUS_COOKIE_SHA1 authentication, which in practice usually
succeeds in authenticating the peer's uid. However, we encourage AF_UNIX
servers on Unix platforms to allow only EXTERNAL authentication as a
security-hardening measure, because DBUS_COOKIE_SHA1 relies on a series
of assumptions including a cryptographically strong PRNG and a shared
home directory with no write access by others, which are not necessarily
true for all operating systems and users. EXTERNAL authentication will
fail if the server cannot determine the client's credentials.
In particular, this caused a regression when CVE-2019-14822 was fixed
in ibus, which appears to be resolved by this commit. Qt clients
(which use libdbus) intermittently fail to connect to an ibus server
(which uses GDBusServer), because ibus no longer allows DBUS_COOKIE_SHA1
authentication or non-matching uids.
Signed-off-by: Simon McVittie <smcv@collabora.com>
Closes: https://gitlab.gnome.org/GNOME/glib/issues/1831
On Linux, if getsockopt SO_PEERCRED is used on a TCP socket, one
might expect it to fail with an appropriate error like ENOTSUP or
EPROTONOSUPPORT. However, it appears that in fact it succeeds, but
yields a credentials structure with pid 0, uid -1 and gid -1. These
are not real process, user and group IDs that can be allocated to a
real process (pid 0 needs to be reserved to give kill(0) its documented
special semantics, and similarly uid and gid -1 need to be reserved for
setresuid() and setresgid()) so it is not meaningful to signal them to
high-level API users.
An API user with Linux-specific knowledge can still inspect these fields
via g_credentials_get_native() if desired.
Similarly, if SO_PASSCRED is used to receive a SCM_CREDENTIALS message
on a receiving Unix socket, but the sending socket had not enabled
SO_PASSCRED at the time that the message was sent, it is possible
for it to succeed but yield a credentials structure with pid 0, uid
/proc/sys/kernel/overflowuid and gid /proc/sys/kernel/overflowgid. Even
if we were to read those pseudo-files, we cannot distinguish between
the overflow IDs and a real process that legitimately has the same IDs
(typically they are set to 'nobody' and 'nogroup', which can be used
by a real process), so we detect this situation by noticing that
pid == 0, and to save syscalls we do not read the overflow IDs from
/proc at all.
This results in a small API change: g_credentials_is_same_user() now
returns FALSE if we compare two credentials structures that are both
invalid. This seems like reasonable, conservative behaviour: if we cannot
prove that they are the same user, we should assume they are not.
(Dropped new translatable string when backporting to `glib-2-62`.)
Signed-off-by: Simon McVittie <smcv@collabora.com>
Otherwise we’ll end up using the host’s `objcopy`, which will output
object files in the wrong format.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Fixes: #1916
Previously we were keeping a pointer to the `GFileMonitor` in a
`GFileMonitorSource` instance, but since we weren’t keeping a strong
reference, that `GFileMonitor` instance could be finalised from another
thread at any point while the source was referring to it. Not good.
Use a weak reference, and upgrade it to a strong reference whenever the
`GFileMonitorSource` is referring to the file monitor.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Helps: #1903
It’s not enough to unref the monitor, since the GLib worker thread might
still hold a reference to it.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Helps: #1903
`DesktopFileDir` pointers are passed around between threads: they are
initially created on the main thread, but a pointer to them is passed to
the GLib worker thread in the file monitor callback
(`desktop_file_dir_changed()`).
Accordingly, the `DesktopFileDir` objects either have to be
(1) immutable;
(2) reference counted; or
(3) synchronised between the two threads
to avoid one of them being used by one thread after being freed on
another. Option (1) changed with commit 99bc33b6 and is no longer an
option. Option (3) would mean blocking the main thread on the worker
thread, which would be hard to achieve and is against the point of
having a worker thread. So that leaves option (2), which is implemented
here.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Fixes: #1903
When the _g_dbus_worker_flush_sync() schedules the 'data' and releases
the worker->write_lock, it is possible for the GDBus worker thread thread
to finish the D-Bus call and acquire the worker->write_lock before
the _g_dbus_worker_flush_sync() re-acquires it in the if (data != NULL) body.
When that happens, the ostream_flush_cb() increases the worker->write_num_messages_flushed
and then releases the worker->write_lock. The write lock is reacquired by
the _g_dbus_worker_flush_sync(), which sees that the while condition is satisfied,
thus it doesn't enter the loop body and immediately clears the data members and
frees the data structure itself. The ostream_flush_cb() is still ongoing, possibly
inside flush_data_list_complete(), where it accesses the FlushData, which can be
in any stage of being freed.
Instead, add an explicit boolean flag indicating when the flush is truly finished.
Closes#1896
Fixes build failure:
../gio/gunixmounts.c: In function ‘_g_get_unix_mounts’:
../gio/gunixmounts.c:742:53: error: ‘struct mnttab’ has no member named ‘mnt_opts’; did you mean ‘mnt_mntopts’?
742 | mntent.mnt_opts,
| ^~~~~~~~
| mnt_mntopts
Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
If a copy operation is started with `G_FILE_COPY_TARGET_DEFAULT_PERMS`,
don’t create the destination file as private. Instead, create it with
the process’ current umask (i.e. ‘default permissions’).
This is a partial re-work of commit d8f8f4d637, with
input from Ondrej Holy.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Fixes: #174
If we're cross-compiling, the installed-tests are useful even if we
can't run them on the build machine: we can copy them to the host
machine (possibly via a distro package like Debian's libglib2.0-tests)
and run them there.
While I'm changing the build-tests condition anyway, deduplicate it.
Based on a patch by Helmut Grohne.
Bug-Debian: https://bugs.debian.org/941509
Signed-off-by: Simon McVittie <smcv@collabora.com>
(cherry picked from commit 42d8e17795)
g_date_time_add_seconds() and g_date_time_add_full() use floating-point
seconds, which can result in the value varying slightly from what's
actually on disk. This causes intermittent test failures in
gio/tests/g-file-info.c on Debian i386, where we set a file's mtime
to be 50µs later, then read it back and sometimes find that it is only
49µs later than the previous value.
I've only seen this happen on i386, which means it might be to do with
different floating-point rounding when a value is stored in the 80-bit
legacy floating point registers rather than in double precision.
g_date_time_add() takes a GTimeSpan, which is in microseconds;
conveniently, that's exactly what we get from the GFileInfo.
Bug-Debian: https://bugs.debian.org/941547
Signed-off-by: Simon McVittie <smcv@collabora.com>
(cherry picked from commit 14609b0b25)
They provide more detailed failure messages, and aren’t compiled out
when building with `G_DISABLE_ASSERT`.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
When future porting deprecated code to use
g_file_info_get_modification_date_time() we risk a number of breakages
because the current implementation also requires the additional use of
G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC. This handles that situation gracefully
and returns a GDateTime with less precision.
Applications that want the additional precision, are already using the
additional attribute.
(Minor tweaks by Philip Withnall.)
Instead of letting each directory to find its way to link with libdl,
it is easier to put the check in the top level, so its result can be
used by all directories.
It is a follow-up of https://gitlab.gnome.org/GNOME/glib/merge_requests/810.
The header file was installed when building using autotools, but was
inadvertently omitted in the meson targets.
Luckily, ABI is not impacted, since gnativesocketaddress.c was always
compiled and linked into libgio.
Fixes: #1854