[ostree] core: Validate structure of objects in fsck



commit 8792007bc10ebb74ab009059e2edc69a1f9cdd61
Author: Colin Walters <walters verbum org>
Date:   Tue Apr 3 08:52:58 2012 -0400

    core: Validate structure of objects in fsck

 src/libostree/ostree-core.c  |  205 +++++++++++++++++++++++++++++++++++++-----
 src/libostree/ostree-core.h  |   21 ++++-
 src/ostree/ot-builtin-fsck.c |   23 +++++
 3 files changed, 222 insertions(+), 27 deletions(-)
---
diff --git a/src/libostree/ostree-core.c b/src/libostree/ostree-core.c
index 06897a2..947bc6d 100644
--- a/src/libostree/ostree-core.c
+++ b/src/libostree/ostree-core.c
@@ -35,30 +35,7 @@ gboolean
 ostree_validate_checksum_string (const char *sha256,
                                  GError    **error)
 {
-  int i = 0;
-  size_t len = strlen (sha256);
-
-  if (len != 64)
-    {
-      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
-                   "Invalid rev '%s'", sha256);
-      return FALSE;
-    }
-
-  for (i = 0; i < len; i++)
-    {
-      guint8 c = ((guint8*) sha256)[i];
-
-      if (!((c >= 48 && c <= 57)
-            || (c >= 97 && c <= 102)))
-        {
-          g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
-                       "Invalid character '%d' in rev '%s'",
-                       c, sha256);
-          return FALSE;
-        }
-    }
-  return TRUE;
+  return ostree_validate_structureof_checksum_string (sha256, error);
 }
 
 gboolean
@@ -1477,6 +1454,36 @@ ostree_validate_structureof_checksum (GVariant  *checksum,
   return TRUE;
 }
 
+gboolean
+ostree_validate_structureof_checksum_string (const char *checksum,
+                                             GError   **error)
+{
+  int i = 0;
+  size_t len = strlen (checksum);
+
+  if (len != 64)
+    {
+      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                   "Invalid rev '%s'", checksum);
+      return FALSE;
+    }
+
+  for (i = 0; i < len; i++)
+    {
+      guint8 c = ((guint8*) checksum)[i];
+
+      if (!((c >= 48 && c <= 57)
+            || (c >= 97 && c <= 102)))
+        {
+          g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                       "Invalid character '%d' in rev '%s'",
+                       c, checksum);
+          return FALSE;
+        }
+    }
+  return TRUE;
+}
+
 static gboolean
 validate_variant (GVariant           *variant,
                   const GVariantType *variant_type,
@@ -1499,6 +1506,156 @@ validate_variant (GVariant           *variant,
 }
 
 gboolean
+ostree_validate_structureof_commit (GVariant      *commit,
+                                    GError       **error)
+{
+  gboolean ret = FALSE;
+  const char *parent;
+  const char *contents;
+  const char *metadata;
+
+  if (!validate_variant (commit, OSTREE_COMMIT_GVARIANT_FORMAT, error))
+    goto out;
+
+  g_variant_get_child (commit, 2, "&s", &parent);
+
+  if (*parent)
+    {
+      if (!ostree_validate_structureof_checksum_string (parent, error))
+        goto out;
+    }
+
+  g_variant_get_child (commit, 6, "&s", &contents);
+  if (!ostree_validate_structureof_checksum_string (contents, error))
+    goto out;
+
+  g_variant_get_child (commit, 7, "&s", &metadata);
+  if (!ostree_validate_structureof_checksum_string (metadata, error))
+    goto out;
+
+  ret = TRUE;
+ out:
+  return ret;
+}
+
+gboolean
+ostree_validate_structureof_dirtree (GVariant      *dirtree,
+                                     GError       **error)
+{
+  gboolean ret = FALSE;
+  GVariantIter *contents_iter = NULL;
+  const char *filename;
+  const char *meta_checksum;
+  const char *content_checksum;
+
+  if (!validate_variant (dirtree, OSTREE_TREE_GVARIANT_FORMAT, error))
+    goto out;
+
+  g_variant_get_child (dirtree, 2, "a(ss)", &contents_iter);
+
+  while (g_variant_iter_loop (contents_iter, "(&s&s)",
+                              &filename, &content_checksum))
+    {
+      if (!ot_util_filename_validate (filename, error))
+        goto out;
+      if (!ostree_validate_structureof_checksum_string (content_checksum, error))
+        goto out;
+    }
+
+  g_variant_iter_free (contents_iter);
+  g_variant_get_child (dirtree, 3, "a(sss)", &contents_iter);
+
+  while (g_variant_iter_loop (contents_iter, "(&s&s&s)",
+                              &filename, &content_checksum, &meta_checksum))
+    {
+      if (!ot_util_filename_validate (filename, error))
+        goto out;
+      if (!ostree_validate_structureof_checksum_string (content_checksum, error))
+        goto out;
+      if (!ostree_validate_structureof_checksum_string (meta_checksum, error))
+        goto out;
+    }
+
+  ret = TRUE;
+ out:
+  if (contents_iter)
+    g_variant_iter_free (contents_iter);
+  return ret;
+}
+
+static gboolean
+validate_stat_mode_perms (guint32        mode,
+                          GError       **error)
+{
+  gboolean ret = FALSE;
+  guint32 otherbits = (~S_IFMT & ~S_IRWXU & ~S_IRWXG & ~S_IRWXO);
+
+  if (mode & otherbits)
+    {
+      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                   "Invalid mode %u; invalid bits in mode", mode);
+      goto out;
+    }
+
+  ret = TRUE;
+ out:
+  return ret;
+}
+
+gboolean
+ostree_validate_structureof_file_mode (guint32            mode,
+                                       GError           **error)
+{
+  gboolean ret = FALSE;
+
+  if (!(S_ISREG (mode)
+        || S_ISLNK (mode)
+        || S_ISCHR (mode)
+        || S_ISBLK (mode)
+        || S_ISFIFO (mode)))
+    {
+      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                   "Invalid file metadata mode %u; not a valid file type", mode);
+      goto out;
+    }
+
+  if (!validate_stat_mode_perms (mode, error))
+    goto out;
+
+  ret = TRUE;
+ out:
+  return ret;
+}
+
+gboolean
+ostree_validate_structureof_dirmeta (GVariant      *dirmeta,
+                                     GError       **error)
+{
+  gboolean ret = FALSE;
+  guint32 mode;
+
+  if (!validate_variant (dirmeta, OSTREE_DIRMETA_GVARIANT_FORMAT, error))
+    goto out;
+
+  g_variant_get_child (dirmeta, 3, "u", &mode); 
+  mode = GUINT32_FROM_BE (mode);
+
+  if (!S_ISDIR (mode))
+    {
+      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                   "Invalid directory metadata mode %u; not a directory", mode);
+      goto out;
+    }
+
+  if (!validate_stat_mode_perms (mode, error))
+    goto out;
+
+  ret = TRUE;
+ out:
+  return ret;
+}
+
+gboolean
 ostree_validate_structureof_pack_index (GVariant      *index,
                                         GError       **error)
 {
diff --git a/src/libostree/ostree-core.h b/src/libostree/ostree-core.h
index e733f51..1df8a6a 100644
--- a/src/libostree/ostree-core.h
+++ b/src/libostree/ostree-core.h
@@ -60,7 +60,7 @@ typedef enum {
  * u - mode
  * a(ayay) - xattrs
  */
-#define OSTREE_DIRMETA_GVARIANT_FORMAT "(uuuua(ayay))"
+#define OSTREE_DIRMETA_GVARIANT_FORMAT G_VARIANT_TYPE ("(uuuua(ayay))")
 
 #define OSTREE_TREE_VERSION 0
 /*
@@ -70,7 +70,7 @@ typedef enum {
  * a(ss) - array of (filename, checksum) for files
  * a(sss) - array of (dirname, tree_checksum, meta_checksum) for directories
  */
-#define OSTREE_TREE_GVARIANT_FORMAT "(ua{sv}a(ss)a(sss)"
+#define OSTREE_TREE_GVARIANT_FORMAT G_VARIANT_TYPE ("(ua{sv}a(ss)a(sss))")
 
 #define OSTREE_COMMIT_VERSION 0
 /*
@@ -84,7 +84,7 @@ typedef enum {
  * s - Root tree contents
  * s - Root tree metadata
  */
-#define OSTREE_COMMIT_GVARIANT_FORMAT "(ua{sv}ssstss)"
+#define OSTREE_COMMIT_GVARIANT_FORMAT G_VARIANT_TYPE ("(ua{sv}ssstss)")
 
 /* Archive file objects:
  * u - Version
@@ -300,6 +300,21 @@ gboolean ostree_validate_structureof_objtype (guint32    objtype,
 gboolean ostree_validate_structureof_checksum (GVariant  *checksum,
                                                GError   **error);
 
+gboolean ostree_validate_structureof_checksum_string (const char *checksum,
+                                                      GError   **error);
+
+gboolean ostree_validate_structureof_file_mode (guint32            mode,
+                                                GError           **error);
+
+gboolean ostree_validate_structureof_commit (GVariant      *index,
+                                             GError       **error);
+
+gboolean ostree_validate_structureof_dirtree (GVariant      *index,
+                                              GError       **error);
+
+gboolean ostree_validate_structureof_dirmeta (GVariant      *index,
+                                              GError       **error);
+
 gboolean ostree_validate_structureof_pack_index (GVariant      *index,
                                                  GError       **error);
 
diff --git a/src/ostree/ot-builtin-fsck.c b/src/ostree/ot-builtin-fsck.c
index 5b9b964..ee45dc3 100644
--- a/src/ostree/ot-builtin-fsck.c
+++ b/src/ostree/ot-builtin-fsck.c
@@ -200,6 +200,24 @@ fsck_reachable_objects_from_commits (OtFsckData            *data,
           if (!ostree_repo_load_variant (data->repo, objtype,
                                          checksum, &metadata, error))
             goto out;
+
+          if (objtype == OSTREE_OBJECT_TYPE_COMMIT)
+            {
+              if (!ostree_validate_structureof_commit (metadata, error))
+                goto out;
+            }
+          else if (objtype == OSTREE_OBJECT_TYPE_DIR_TREE)
+            {
+              if (!ostree_validate_structureof_dirtree (metadata, error))
+                goto out;
+            }
+          else if (objtype == OSTREE_OBJECT_TYPE_DIR_META)
+            {
+              if (!ostree_validate_structureof_dirmeta (metadata, error))
+                goto out;
+            }
+          else
+            g_assert_not_reached ();
           
           ot_clear_gvariant (&metadata_wrapped);
           metadata_wrapped = ostree_wrap_metadata_variant (objtype, metadata);
@@ -216,10 +234,15 @@ fsck_reachable_objects_from_commits (OtFsckData            *data,
       else if (objtype == OSTREE_OBJECT_TYPE_RAW_FILE
                || objtype == OSTREE_OBJECT_TYPE_ARCHIVED_FILE_META)
         {
+          guint32 mode;
           if (!ostree_repo_load_file (data->repo, checksum, &input, &file_info,
                                       &xattrs, cancellable, error))
             goto out;
           checksum_objtype = OSTREE_OBJECT_TYPE_RAW_FILE; /* Override */ 
+
+          mode = g_file_info_get_attribute_uint32 (file_info, "unix::mode");
+          if (!ostree_validate_structureof_file_mode (mode, error))
+            goto out;
         }
       else
         {



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]