mirror of
https://github.com/ostreedev/ostree.git
synced 2025-03-19 22:50:35 +03:00
core: Validate structure of objects in fsck
This commit is contained in:
parent
10b2f30165
commit
8792007bc1
@ -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,
|
||||
@ -1498,6 +1505,156 @@ validate_variant (GVariant *variant,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
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)
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user