We want to use the keyfile backend in sandboxes,
but we want to avoid people losing their existing
settings that are stored in dconf. Flatpak does
a migration from dconf to keyfile, but only if
the app explictly requests it.
From an app perspective, there are two steps to
the dconf->keyfile migration:
1. Request that flatpak do the migration, by adding
the migrate-path key to the metadata
2. Stop adding the 'dconf hole' to the sandbox
To keep us from switching to the keyfile backend
prematurely, look at whether the app has stopped
requesting a 'dconf hole' in the sandbox.
When we are in a sandboxed situation, bump the priority
of the keyfile settings backend above the dconf one,
so we use a keyfile inside the sandbox instead of requiring
holes in the sandbox for dconf.
Stacked databases and locks are dconf features that allow
management software like Fleet Commander to set system-wide
defaults and overrides centrally for applications.
This patch adds minimal support for the same to the keyfile
backend. We look for a keyfile named 'defaults' and a
lock-list named 'locks'.
Suitable files can be produced from a dconf database with
dconf dump and dconf list-locks, respectively.
The default location for these files is /etc/glib-2.0/settings/.
For test purposes, this can be overwritten with the
GSETTINGS_DEFAULTS_DIR environment variable.
Writes always go to the per-user keyfile.
Make it possible to instantiate a keyfile settings backend
without specifying parameters, by turning the arguments to
the new() function into construct-only properties. If no
filename is specified, default to
$XDG_CONFIG_HOME/glib-2.0/settings/keyfile
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.
Signed-off-by: Simon McVittie <smcv@collabora.com>
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
Add a new syntax to override files: if the group name has a ':' in it,
it indicates that we want to override the default values of keys for
only one desktop. For example:
[org.gnome.desktop.interface:Unity]
font-name='Ubuntu 12'
Will override the settings, only if "Unity" is found in
XDG_CURRENT_DESKTOP. Multiple per-desktop overrides can be specified
for a given key: the one which comes first in XDG_CURRENT_DESKTOP will
be used.
https://bugzilla.gnome.org/show_bug.cgi?id=746592
Recognise a new 'd' option in schema keys which gives a dictionary of
per-desktop default values. This dictionary is searched for the items
found in XDG_CURRENT_DESKTOP, in the order. If nothing matches (or if
the option is missing) then the default value is used as before.
This feature was requested by Alberts Muktupāvels and this patch is
based on an approach devised by them.
https://bugzilla.gnome.org/show_bug.cgi?id=746592
There are a couple of different ways (and soon one more) to access the
default value of a key. Clean up the various places that access this to
avoid duplication.
https://bugzilla.gnome.org/show_bug.cgi?id=746592
file_copy_fallback creates new files with default permissions and
set the correct permissions after the operation is finished. This
might cause that the files can be accessible by more users during
the operation than expected. Use G_FILE_CREATE_PRIVATE for the new
files to limit access to those files.
Fedora is using https://fedoraproject.org/wiki/Changes/Annobin
to try to ensure that all objects are built with hardening flags.
Pass down `CFLAGS` to ensure the SystemTap objects use them.
The existing code was generating code with undefined results that modern compilers warn about:
accounts-generated.c:204:23: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
(GDBusArgInfo **) &_accounts_accounts_method_info_list_cached_users_OUT_ARG_pointers,
At the moment the gdbus-unix-addresses test will fail if
G_MESSAGES_DEBUG is set, since the test checks stdout, and the
test has a g_debug call.
This commit drops the g_debug call, which isn't that useful anyway.
These were callers which explicitly specified the string length to
g_utf8_validate(), when it couldn’t be negative, and hence should be
able to unconditionally benefit from the increased string handling
length.
At least one call site would have previously silently changed behaviour
if called with strings longer than G_MAXSSIZE in length.
Another call site was passing strlen(string) to g_utf8_validate(), which
seems pointless: just pass -1 instead, and let g_utf8_validate()
calculate the string length. Its behaviour on embedded nul bytes
wouldn’t change, as strlen() stops at the first one.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
This introduces no real functional changes (except when compiling with
G_DISABLE_ASSERT, in which case it fixes the test). Mostly just a code
cleanup.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
The code was checking whether the signature provided by the blob was a
valid D-Bus signature — but that’s a superset of a valid GVariant type
string, since a D-Bus signature is zero or more complete types. A
GVariant type string is exactly one complete type.
This meant that a D-Bus message with a header field containing a variant
with an empty type signature (for example) could cause a critical
warning in the code parsing it.
Fix that by checking whether the string is a valid type string too.
Unit test included.
oss-fuzz#9810
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Parsing a D-Bus message with the signature field in the message header
of type other than ‘g’ (GVariant type signature) would cause a critical
warning. Instead, we should return a runtime error.
Includes a test.
oss-fuzz#9825
Signed-off-by: Philip Withnall <withnall@endlessm.com>
`read_netlink_messages()` is the callback attached to the netlink socket
(G_IO_IN). It calls `g_socket_receive_message()`. There is a race
condition that if the socket is closed while there is a pending call, we
will try to receive on a closed socket, which fails.
To avoid this, we switch the order of the operations around: first
destroy the source and then close the socket.
This is not a correct way to check if `g_socket_new_from_fd()` failed.
Instead just see if it returned `NULL` itself.
This was preventing the netlink monitor from being initialised.
Closes#1518
The source callback for a GCancellable should have the cancellable itself
as first argument.
This was not the case, and when this code was hit, we were instead trying
to treat the pointer as a CommunicateState reference and thus wrongly
deferencing it, causing a memory error and a crash.
7efd76dd6796f8 added these configure time tests to work around a bug
with older Android. Since the test didn't take Windows into account it
wrongfully applied the workaround on Windows too, breaking the build.
With meson this wasn't an issue since the check is skipped on Windows there
and our CI didn't catch this issue.
Change the test to run on Android only for meson and autotools.
This also makes it clear that the test+code can be dropped again if we stop
supporting older Android versions at some point.
It’s consistently timing out on the CI, which makes sense since it does
333 iterations of spawning a subprocess. Give it a bit more breathing
room.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
The network monitor portal interface is changing.
Version 2 is no longer using properties, but getters
instead (this lets the portal apply access control
and avoid sending information to non-networked
sandboxes).
To support both version 1 and 2 of the interface,
we stop using generated code and instead deal with
the api differences in our own code, which is not
too difficult.
Support version 1 as well
When using g_network_monitor_get_default() from another thread, it’s
possible for network-changed events to be processed after an instance of
GNetworkMonitor has been disposed, causing use-after-free problems.
Fix that by moving some of the initialisation into the GInitable.init()
chain, rather than in a main context idle callback.
This includes a unit test which probabilistically reproduces the bug
(but can’t do so deterministically due to it being a race condition).
Commit amended by Philip Withnall <withnall@endlessm.com> before
pushing.
https://bugzilla.gnome.org/show_bug.cgi?id=793727
While mountpoints are *not* symlinks, strictly speaking,
they works in a similar enough way, so consider them to be
symlinks for the purpose of querying local file info.
On Windows st_ctime field is the file creation time.
POSIX mandates that field to be the file state change time.
Naturally, glib code interpreted st_ctime as POSIX suggested,
and the result was bad.
Fix this by introducing special W32-only logic for setting
attributes from st_ctime field.
Fixes issue #1452.
Releasing GVolumeMonitor before g_volume_mount finish cause that
g_volume_get_mount returns NULL, because the mount is not correctly
propagated to the volume.
(Backported from commit 88b8ebb5dde0512fd1e098efe4c217111876d252 with
minor merge conflicts.)
https://gitlab.gnome.org/GNOME/glib/issues/1458
The documentation claims that g_volume_get_mount should succeed after
g_volume_mount. Let's update mounts before releasing g_volume_mount to
be sure that the mount is added to the corresponding volume. The same
is done in GVfsUDisks2VolumeMonitor.
(Backported from commit 9b6b282e0a9d3f37865aa36e21ea57bd2a326e20 with no
merge conflicts.)
https://gitlab.gnome.org/GNOME/glib/issues/1458
gunixmounts: Stop considering cifs/nfs as system file systems
See merge request GNOME/glib!125
(cherry picked from commit 51132b1d49c184f49baafa81ce7fac02b1458643)
a3a6c516 gunixmounts: Stop considering cifs/nfs as system file systems
The way things were before: a FreedesktopNotification struct is
allocated before the dbus call, and this same struct is possibly re-used
for other dbus calls. If the server becomes unavailable, the callback
will be invoked after the call times out, which leaves a long time where
other dbus calls can happen, re-using the same FreedesktopNotification
as user data. When the first call times out, the callback is invoked,
and the user data is freed. Subsequent calls that used the same user
data will time out later on, and try to free a pointer that was already
freed, hence segfaults.
This bug can be reproduced in Cinnamon 3.6.7, as mentioned in:
<https://github.com/linuxmint/Cinnamon/issues/7491>
This commit fixes that by always allocating a new
FreedesktopNotification before invoking dbus_call(), ensuring that the
callback always have a valid user data.
Signed-off-by: Arnaud Rebillout <elboulangero@gmail.com>
Previously, calling:
g_dbus_is_supported_address ("some-imaginary-transport:", NULL)
correctly returned FALSE; but calling:
g_dbus_is_supported_address ("some-imaginary-transport:", &error)
crashed with:
GLib-GIO:ERROR:../gio/gdbusaddress.c:434:g_dbus_is_supported_address:
assertion failed: (ret || (!ret && (error == NULL || *error != NULL)))
This was because, if the address component did not start with a known
transport, no error was set. Fix this, reusing an error string used by
the corresponding else branch in g_dbus_address_connect(), and adjust
the test to pass both NULL and non-NULL GError **s to this function in
every test case. This case:
g_assert (!g_dbus_is_supported_address ("some-imaginary-transport:foo=bar;unix:path=/this/is/valid", NULL));
would have caught this bug with a non-NULL GError **.