diff --git a/include/config_file.h b/include/config_file.h index 01def6236..e8c2f32a0 100644 --- a/include/config_file.h +++ b/include/config_file.h @@ -88,6 +88,7 @@ typedef struct { GHashTable *slots; /* flag to ensure slot states were determined */ gboolean slot_states_determined; + gchar *file_checksum; } RaucConfig; typedef enum { @@ -164,3 +165,11 @@ G_GNUC_WARN_UNUSED_RESULT; void free_config(RaucConfig *config); G_DEFINE_AUTOPTR_CLEANUP_FUNC(RaucConfig, free_config); + +/** + * Checks if the current file checksum of the system config matches the one currently loaded. + * + * Prints a warning if the checksums of the config file does not match the one + * recorded during config parsing. + */ +void r_config_file_modified_check(void); diff --git a/src/config_file.c b/src/config_file.c index 65d4e81fc..069e7f23a 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -395,9 +395,34 @@ static GHashTable *parse_slots(const char *filename, const char *data_directory, return g_steal_pointer(&slots); } +void r_config_file_modified_check(void) { + g_autoptr(GError) ierror = NULL; + g_autofree gchar *data = NULL; + gsize length; + g_autofree gchar *new_checksum = NULL; + + if (!r_context()->config->file_checksum) + return; + + if (!g_file_get_contents(r_context()->configpath, &data, &length, &ierror)) { + g_warning("Failed to compare config: %s", ierror->message); + return; + } + + new_checksum = g_compute_checksum_for_data(G_CHECKSUM_SHA256, (guchar*) data, length); + + if (g_strcmp0(r_context()->config->file_checksum, new_checksum) != 0) { + g_warning("System configuration file changed on disk! " + "Still using old configuration! " + "Please restart the rauc service."); + } +} + gboolean load_config(const gchar *filename, RaucConfig **config, GError **error) { GError *ierror = NULL; + g_autofree gchar *data = NULL; + gsize length; g_autoptr(RaucConfig) c = g_new0(RaucConfig, 1); g_autoptr(GKeyFile) key_file = NULL; gboolean dtbvariant; @@ -409,9 +434,16 @@ gboolean load_config(const gchar *filename, RaucConfig **config, GError **error) g_return_val_if_fail(config && *config == NULL, FALSE); g_return_val_if_fail(error == NULL || *error == NULL, FALSE); + /* We store checksum for later comparison */ + if (!g_file_get_contents(filename, &data, &length, &ierror)) { + g_propagate_error(error, ierror); + return FALSE; + } + c->file_checksum = g_compute_checksum_for_data(G_CHECKSUM_SHA256, (guchar*) data, length); + key_file = g_key_file_new(); - if (!g_key_file_load_from_file(key_file, filename, G_KEY_FILE_NONE, &ierror)) { + if (!g_key_file_load_from_data(key_file, data, length, G_KEY_FILE_NONE, &ierror)) { g_propagate_error(error, ierror); return FALSE; } @@ -906,5 +938,6 @@ void free_config(RaucConfig *config) g_free(config->encryption_key); g_free(config->encryption_cert); g_clear_pointer(&config->slots, g_hash_table_destroy); + g_free(config->file_checksum); g_free(config); } diff --git a/src/service.c b/src/service.c index 92e1d11c2..3ad540960 100644 --- a/src/service.c +++ b/src/service.c @@ -120,6 +120,8 @@ static gboolean r_on_handle_install_bundle( goto out; } + r_config_file_modified_check(); + r_installer_set_operation(r_installer, "installing"); g_dbus_interface_skeleton_flush(G_DBUS_INTERFACE_SKELETON(r_installer)); res = install_run(args); @@ -417,6 +419,8 @@ static gboolean r_on_handle_get_slot_status(RInstaller *interface, return TRUE; } + r_config_file_modified_check(); + slotstatus = create_slotstatus_array(&ierror); if (!slotstatus) { g_dbus_method_invocation_return_gerror(invocation, ierror);