(root)/
glib-2.79.0/
gio/
gsandbox.c
       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  }