1 /* GIO - GLib Input, Output and Streaming Library
2 *
3 * Copyright 2022 Canonical Ltd
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 "gsandbox.h"
24
25 #include <string.h>
26
27 #define SNAP_CONFINEMENT_PREFIX "confinement:"
28
29 static gboolean
30 is_flatpak (void)
31 {
32 const char *flatpak_info = "/.flatpak-info";
33 gboolean found;
34
35 #ifdef G_PORTAL_SUPPORT_TEST
36 char *test_key_file =
37 g_build_filename (g_get_user_runtime_dir (), flatpak_info, NULL);
38 flatpak_info = test_key_file;
39 #endif
40
41 found = g_file_test (flatpak_info, G_FILE_TEST_EXISTS);
42
43 #ifdef G_PORTAL_SUPPORT_TEST
44 g_clear_pointer (&test_key_file, g_free);
45 #endif
46
47 return found;
48 }
49
50 static gchar *
51 get_snap_confinement (const char *snap_yaml,
52 GError **error)
53 {
54 char *confinement = NULL;
55 char *yaml_contents;
56
57 if (g_file_get_contents (snap_yaml, &yaml_contents, NULL, error))
58 {
59 const char *line = yaml_contents;
60
61 do
62 {
63 if (g_str_has_prefix (line, SNAP_CONFINEMENT_PREFIX))
64 break;
65
66 line = strchr (line, '\n');
67 if (line)
68 line += 1;
69 }
70 while (line != NULL);
71
72 if (line)
73 {
74 const char *start = line + strlen (SNAP_CONFINEMENT_PREFIX);
75 const char *end = strchr (start, '\n');
76
77 confinement =
78 g_strstrip (end ? g_strndup (start, end-start) : g_strdup (start));
79 }
80
81 g_free (yaml_contents);
82 }
83
84 return g_steal_pointer (&confinement);
85 }
86
87 static gboolean
88 is_snap (void)
89 {
90 GError *error = NULL;
91 const gchar *snap_path;
92 gchar *yaml_path;
93 char *confinement;
94 gboolean result;
95
96 snap_path = g_getenv ("SNAP");
97 if (snap_path == NULL)
98 return FALSE;
99
100 result = FALSE;
101 yaml_path = g_build_filename (snap_path, "meta", "snap.yaml", NULL);
102 confinement = get_snap_confinement (yaml_path, &error);
103 g_free (yaml_path);
104
105 /* Classic snaps are de-facto no sandboxed apps, so we can ignore them */
106 if (!error && g_strcmp0 (confinement, "classic") != 0)
107 result = TRUE;
108
109 g_clear_error (&error);
110 g_free (confinement);
111
112 return result;
113 }
114
115 /*
116 * glib_get_sandbox_type:
117 *
118 * Gets the type of sandbox this process is running inside.
119 *
120 * Checking for sandboxes may involve doing blocking I/O calls, but should not take
121 * any significant time.
122 *
123 * The sandbox will not change over the lifetime of the process, so calling this
124 * function once and reusing the result is valid.
125 *
126 * If this process is not sandboxed then @G_SANDBOX_TYPE_UNKNOWN will be returned.
127 * This is because this function only detects known sandbox types in #GSandboxType.
128 * It may be updated in the future if new sandboxes come into use.
129 *
130 * Returns: a #GSandboxType.
131 */
132 GSandboxType
133 glib_get_sandbox_type (void)
134 {
135 if (is_flatpak ())
136 return G_SANDBOX_TYPE_FLATPAK;
137 else if (is_snap ())
138 return G_SANDBOX_TYPE_SNAP;
139 else
140 return G_SANDBOX_TYPE_UNKNOWN;
141 }