Exemplo n.º 1
0
/* SELinux uses PCRE pre-compiled regexps for binary caches, which can
 * fail if the version of PCRE on the host differs from the version
 * which generated the cache (in the target root).
 *
 * Note also this function is probably already broken in Fedora
 * 23+ from https://bugzilla.redhat.com/show_bug.cgi?id=1265406
 */
static gboolean
workaround_selinux_cross_labeling_recurse (int            dfd,
        const char    *path,
        GCancellable  *cancellable,
        GError       **error)
{
    gboolean ret = FALSE;
    g_auto(GLnxDirFdIterator) dfd_iter = { 0, };

    if (!glnx_dirfd_iterator_init_at (dfd, path, TRUE, &dfd_iter, error))
        goto out;

    while (TRUE)
    {
        struct dirent *dent = NULL;
        const char *name;

        if (!glnx_dirfd_iterator_next_dent_ensure_dtype (&dfd_iter, &dent, cancellable, error))
            goto out;

        if (!dent)
            break;

        name = dent->d_name;

        if (dent->d_type == DT_DIR)
        {
            if (!workaround_selinux_cross_labeling_recurse (dfd_iter.fd, name, cancellable, error))
                goto out;
        }
        else if (g_str_has_suffix (name, ".bin"))
        {
            struct stat stbuf;
            const char *lastdot;
            gs_free char *nonbin_name = NULL;

            if (TEMP_FAILURE_RETRY (fstatat (dfd_iter.fd, name, &stbuf, AT_SYMLINK_NOFOLLOW)) != 0)
            {
                glnx_set_error_from_errno (error);
                goto out;
            }

            lastdot = strrchr (name, '.');
            g_assert (lastdot);

            nonbin_name = g_strndup (name, lastdot - name);

            g_print ("Setting mtime of '%s' to newer than '%s'\n", nonbin_name, name);
            if (TEMP_FAILURE_RETRY (utimensat (dfd_iter.fd, nonbin_name, NULL, 0)) == -1)
            {
                glnx_set_error_from_errno (error);
                goto out;
            }
        }
    }

    ret = TRUE;
out:
    return ret;
}
Exemplo n.º 2
0
static gboolean
workaround_selinux_cross_labeling (GFile         *rootfs,
                                   GCancellable  *cancellable,
                                   GError       **error)
{
  gboolean ret = FALSE;
  gs_unref_object GFile *etc_selinux_dir = g_file_resolve_relative_path (rootfs, "usr/etc/selinux");

  if (g_file_query_exists (etc_selinux_dir, NULL))
    {
      if (!workaround_selinux_cross_labeling_recurse (etc_selinux_dir,
                                                      cancellable, error))
        goto out;
    }
    
  ret = TRUE;
 out:
  return ret;
}
Exemplo n.º 3
0
static gboolean
rpmostree_prepare_rootfs_get_sepolicy (int            dfd,
                                       const char    *path,
                                       OstreeSePolicy **out_sepolicy,
                                       GCancellable  *cancellable,
                                       GError       **error)
{
    gboolean ret = FALSE;
    glnx_unref_object OstreeSePolicy *ret_sepolicy = NULL;
    struct stat stbuf;

    if (TEMP_FAILURE_RETRY (fstatat (dfd, "usr/etc/selinux", &stbuf, AT_SYMLINK_NOFOLLOW)) != 0)
    {
        if (errno != ENOENT)
        {
            glnx_set_error_from_errno (error);
            goto out;
        }
    }
    else
    {
        if (!workaround_selinux_cross_labeling_recurse (dfd, "usr/etc/selinux",
                cancellable, error))
            goto out;
    }

    {
        g_autofree char *abspath = glnx_fdrel_abspath (dfd, path);
        glnx_unref_object GFile *rootfs = g_file_new_for_path (abspath);
        ret_sepolicy = ostree_sepolicy_new (rootfs, cancellable, error);
        if (!ret_sepolicy)
            goto out;
    }

    ret = TRUE;
    *out_sepolicy = g_steal_pointer (&ret_sepolicy);
out:
    return ret;
}
Exemplo n.º 4
0
static gboolean
workaround_selinux_cross_labeling_recurse (GFile         *dir,
                                           GCancellable  *cancellable,
                                           GError       **error)
{
  gboolean ret = FALSE;
  gs_unref_object GFileEnumerator *direnum = NULL;

  direnum = g_file_enumerate_children (dir, "standard::name,standard::type,time::modified,time::access",
                                       G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
                                       cancellable, error);
  if (!direnum)
    goto out;

  while (TRUE)
    {
      GFileInfo *file_info;
      GFile *child;
      const char *name;

      if (!gs_file_enumerator_iterate (direnum, &file_info, &child,
                                       cancellable, error))
        goto out;
      if (!file_info)
        break;

      name = g_file_info_get_name (file_info);

      if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_DIRECTORY)
        {
          if (!workaround_selinux_cross_labeling_recurse (child, cancellable, error))
            goto out;
        }
      else if (g_str_has_suffix (name, ".bin"))
        {
          const char *lastdot;
          gs_free char *nonbin_name = NULL;
          gs_unref_object GFile *nonbin_path = NULL;
          guint64 mtime = g_file_info_get_attribute_uint64 (file_info, "time::modified");
          guint64 atime = g_file_info_get_attribute_uint64 (file_info, "time::access");
          struct utimbuf times;

          lastdot = strrchr (name, '.');
          g_assert (lastdot);

          nonbin_name = g_strndup (name, lastdot - name);
          nonbin_path = g_file_get_child (dir, nonbin_name);

          times.actime = (time_t)atime;
          times.modtime = ((time_t)mtime) + 60;

          g_print ("Setting mtime of '%s' to newer than '%s'\n",
                   gs_file_get_path_cached (nonbin_path),
                   gs_file_get_path_cached (child));
          if (utime (gs_file_get_path_cached (nonbin_path), &times) == -1)
            {
              int errsv = errno;
              g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                           "utime(%s): %s", gs_file_get_path_cached (nonbin_path),
                           strerror (errsv));
              goto out;
            }
        }
    }

  ret = TRUE;
 out:
  return ret;
}