Branch data Line data Source code
1 : : /* GIO - GLib Input, Output and Streaming Library
2 : : *
3 : : * Copyright 2016 Red Hat, Inc.
4 : : *
5 : : * SPDX-License-Identifier: LGPL-2.1-or-later
6 : : *
7 : : * This library is free software; you can redistribute it and/or
8 : : * modify it under the terms of the GNU Lesser General Public
9 : : * License as published by the Free Software Foundation; either
10 : : * version 2.1 of the License, or (at your option) any later version.
11 : : *
12 : : * This library is distributed in the hope that it will be useful,
13 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 : : * Lesser General Public License for more details.
16 : : *
17 : : * You should have received a copy of the GNU Lesser General
18 : : * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 : : */
20 : :
21 : : #include "config.h"
22 : :
23 : : #include "glib-private.h"
24 : : #include "gportalsupport.h"
25 : : #include "gsandbox.h"
26 : :
27 : : static GSandboxType sandbox_type = G_SANDBOX_TYPE_UNKNOWN;
28 : : static gboolean use_portal;
29 : : static gboolean network_available;
30 : : static gboolean dconf_access;
31 : :
32 : : #ifdef G_PORTAL_SUPPORT_TEST
33 : : static const char *snapctl = "snapctl";
34 : : #else
35 : : static const char *snapctl = "/usr/bin/snapctl";
36 : : #endif
37 : :
38 : : static gboolean
39 : 47 : snap_plug_is_connected (const gchar *plug_name)
40 : : {
41 : : gint wait_status;
42 : 47 : const gchar *argv[] = { snapctl, "is-connected", plug_name, NULL };
43 : :
44 : : /* Bail out if our process is privileged - we don't want to pass those
45 : : * privileges to snapctl. It could be overridden and this would
46 : : * allow arbitrary code execution.
47 : : */
48 : 47 : if (GLIB_PRIVATE_CALL (g_check_setuid) ())
49 : 0 : return FALSE;
50 : :
51 : 47 : if (!g_spawn_sync (NULL, (gchar **) argv, NULL,
52 : : #ifdef G_PORTAL_SUPPORT_TEST
53 : : G_SPAWN_SEARCH_PATH |
54 : : #endif
55 : : G_SPAWN_STDOUT_TO_DEV_NULL |
56 : : G_SPAWN_STDERR_TO_DEV_NULL,
57 : : NULL, NULL, NULL, NULL, &wait_status,
58 : : NULL))
59 : 4 : return FALSE;
60 : :
61 : 43 : return g_spawn_check_wait_status (wait_status, NULL);
62 : : }
63 : :
64 : : static void
65 : 225 : sandbox_info_read (void)
66 : : {
67 : : static gsize sandbox_info_is_read = 0;
68 : :
69 : : /* Sandbox type and Flatpak info is static, so only read once */
70 : 225 : if (!g_once_init_enter (&sandbox_info_is_read))
71 : 98 : return;
72 : :
73 : 127 : sandbox_type = glib_get_sandbox_type ();
74 : :
75 : 127 : switch (sandbox_type)
76 : : {
77 : 4 : case G_SANDBOX_TYPE_FLATPAK:
78 : : {
79 : : GKeyFile *keyfile;
80 : 4 : const char *keyfile_path = "/.flatpak-info";
81 : :
82 : 4 : use_portal = TRUE;
83 : 4 : network_available = FALSE;
84 : 4 : dconf_access = FALSE;
85 : :
86 : 4 : keyfile = g_key_file_new ();
87 : :
88 : : #ifdef G_PORTAL_SUPPORT_TEST
89 : 4 : char *test_key_file =
90 : 4 : g_build_filename (g_get_user_runtime_dir (), keyfile_path, NULL);
91 : 4 : keyfile_path = test_key_file;
92 : : #endif
93 : :
94 : 4 : if (g_key_file_load_from_file (keyfile, keyfile_path, G_KEY_FILE_NONE, NULL))
95 : : {
96 : 4 : char **shared = NULL;
97 : 4 : char *dconf_policy = NULL;
98 : :
99 : 4 : shared = g_key_file_get_string_list (keyfile, "Context", "shared", NULL, NULL);
100 : 4 : if (shared)
101 : : {
102 : 3 : network_available = g_strv_contains ((const char *const *) shared, "network");
103 : 3 : g_strfreev (shared);
104 : : }
105 : :
106 : 4 : dconf_policy = g_key_file_get_string (keyfile, "Session Bus Policy", "ca.desrt.dconf", NULL);
107 : 4 : if (dconf_policy)
108 : : {
109 : 3 : if (strcmp (dconf_policy, "talk") == 0)
110 : 2 : dconf_access = TRUE;
111 : 3 : g_free (dconf_policy);
112 : : }
113 : : }
114 : :
115 : : #ifdef G_PORTAL_SUPPORT_TEST
116 : 4 : g_clear_pointer (&test_key_file, g_free);
117 : : #endif
118 : :
119 : 4 : g_key_file_unref (keyfile);
120 : : }
121 : 4 : break;
122 : 1 : case G_SANDBOX_TYPE_SNAP:
123 : 1 : break;
124 : 122 : case G_SANDBOX_TYPE_UNKNOWN:
125 : : {
126 : : const char *var;
127 : :
128 : 122 : var = g_getenv ("GIO_USE_PORTALS");
129 : 122 : if (var && var[0] == '1')
130 : 2 : use_portal = TRUE;
131 : 122 : network_available = TRUE;
132 : 122 : dconf_access = TRUE;
133 : : }
134 : 122 : break;
135 : : }
136 : :
137 : 127 : g_once_init_leave (&sandbox_info_is_read, 1);
138 : : }
139 : :
140 : : gboolean
141 : 180 : glib_should_use_portal (void)
142 : : {
143 : 180 : sandbox_info_read ();
144 : :
145 : 180 : if (sandbox_type == G_SANDBOX_TYPE_SNAP)
146 : 13 : return snap_plug_is_connected ("desktop");
147 : :
148 : 167 : return use_portal;
149 : : }
150 : :
151 : : gboolean
152 : 22 : glib_network_available_in_sandbox (void)
153 : : {
154 : 22 : sandbox_info_read ();
155 : :
156 : 22 : if (sandbox_type == G_SANDBOX_TYPE_SNAP)
157 : : {
158 : : /* FIXME: This is inefficient doing multiple calls to check connections.
159 : : * See https://github.com/snapcore/snapd/pull/12301 for a proposed
160 : : * improvement to snapd for this.
161 : : */
162 : 21 : return snap_plug_is_connected ("desktop") ||
163 : 8 : snap_plug_is_connected ("network-status");
164 : : }
165 : :
166 : 9 : return network_available;
167 : : }
168 : :
169 : : gboolean
170 : 23 : glib_has_dconf_access_in_sandbox (void)
171 : : {
172 : 23 : sandbox_info_read ();
173 : :
174 : 23 : if (sandbox_type == G_SANDBOX_TYPE_SNAP)
175 : 13 : return snap_plug_is_connected ("gsettings");
176 : :
177 : 10 : return dconf_access;
178 : : }
|