diff --git a/core/lib/Drupal/Core/Config/ConfigInstaller.php b/core/lib/Drupal/Core/Config/ConfigInstaller.php
index c8defe7..d9939cd 100644
--- a/core/lib/Drupal/Core/Config/ConfigInstaller.php
+++ b/core/lib/Drupal/Core/Config/ConfigInstaller.php
@@ -85,9 +85,17 @@ public function __construct(ConfigFactoryInterface $config_factory, StorageInter
   }
 
   /**
-   * {@inheritdoc}
+   * Gather default configuration to install.
+   *
+   * @param string $type
+   *   Type of extension to install.
+   * @param string $name
+   *   Name of extension to install.
+   *
+   * @return
+   *   Array with list of configuration keys to install.
    */
-  public function installDefaultConfig($type, $name) {
+  public function gatherDefaultConfig($type, $name) {
     $extension_path = drupal_get_path($type, $name);
     // If the extension provides configuration schema clear the definitions.
     if (is_dir($extension_path . '/' . InstallStorage::CONFIG_SCHEMA_DIRECTORY)) {
@@ -156,6 +164,23 @@ protected function listDefaultConfigCollection($collection, $type, $name, array
 
       $config_to_install = array_merge($config_to_install, $other_module_config);
     }
+    // Profiles can provide default configuration on behalf of other modules if
+    // the configuration already exists remove it as it was used when the
+    // extension that owns the configuration was installed.
+    if ($type == 'profile') {
+      $config_to_install = array_filter($config_to_install, function ($config_name) {
+        return !$this->activeStorage->exists($config_name);
+      });
+    }
+    return $config_to_install;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function installDefaultConfig($type, $name) {
+    $source_storage = new ExtensionInstallStorage($this->activeStorage);
+    $config_to_install = $this->gatherDefaultConfig($type, $name);
 
     return $config_to_install;
   }
@@ -322,4 +347,28 @@ public function setSyncing($status) {
   public function isSyncing() {
     return $this->isSyncing;
   }
+
+  /**
+   * Validate default configuration before installation.
+   *
+   * @param string $type
+   *   Type of extension to install.
+   * @param string $name
+   *   Name of extension to install.
+   *
+   * @return bool
+   *   Whether all the default configuration of this module can be installed.
+   *   If any of the default configuration already exists in the system, returns
+   *   FALSE.
+   */
+  public function validatePreInstall($type, $name) {
+    $config_to_install = $this->gatherDefaultConfig($type, $name);
+    foreach ($config_to_install as $config_name) {
+      if ($this->activeStorage->exists($config_name)) {
+        drupal_set_message(t('%extension cannot be installed because default configuration named %config_name already exists in active configuration.', array('%config_name' => $config_name, '%extension' => $name)), 'error');
+        return FALSE;
+      }
+    }
+    return TRUE;
+  }
 }
diff --git a/core/lib/Drupal/Core/Extension/ModuleHandler.php b/core/lib/Drupal/Core/Extension/ModuleHandler.php
index 62cdd06..8e321dc 100644
--- a/core/lib/Drupal/Core/Extension/ModuleHandler.php
+++ b/core/lib/Drupal/Core/Extension/ModuleHandler.php
@@ -636,8 +636,8 @@ public static function parseDependency($dependency) {
   public function install(array $module_list, $enable_dependencies = TRUE) {
     $extension_config = \Drupal::config('core.extension');
     if ($enable_dependencies) {
-      // Get all module data so we can find dependencies and sort.
       $module_data = system_rebuild_module_data();
+      // Get all module data so we can find dependencies and sort.
       $module_list = $module_list ? array_combine($module_list, $module_list) : array();
       if (array_diff_key($module_list, $module_data)) {
         // One or more of the given modules doesn't exist.
@@ -651,21 +651,18 @@ public function install(array $module_list, $enable_dependencies = TRUE) {
         return TRUE;
       }
 
-      // Conditionally add the dependencies to the list of modules.
-      if ($enable_dependencies) {
-        // Add dependencies to the list. The new modules will be processed as
-        // the while loop continues.
-        while (list($module) = each($module_list)) {
-          foreach (array_keys($module_data[$module]->requires) as $dependency) {
-            if (!isset($module_data[$dependency])) {
-              // The dependency does not exist.
-              return FALSE;
-            }
+      // Add dependencies to the list. The new modules will be processed as
+      // the while loop continues.
+      while (list($module) = each($module_list)) {
+        foreach (array_keys($module_data[$module]->requires) as $dependency) {
+          if (!isset($module_data[$dependency])) {
+            // The dependency does not exist.
+            return FALSE;
+          }
 
-            // Skip already installed modules.
-            if (!isset($module_list[$dependency]) && !isset($installed_modules[$dependency])) {
-              $module_list[$dependency] = $dependency;
-            }
+          // Skip already installed modules.
+          if (!isset($module_list[$dependency]) && !isset($installed_modules[$dependency])) {
+            $module_list[$dependency] = $dependency;
           }
         }
       }
@@ -678,6 +675,13 @@ public function install(array $module_list, $enable_dependencies = TRUE) {
       // Sort the module list by their weights (reverse).
       arsort($module_list);
       $module_list = array_keys($module_list);
+
+      // Validate default configuration of this module. Bail if unable to
+      // install. Should not continue installing more modules because those
+      // may depend on this one.
+      if (!\Drupal::service('config.installer')->validatePreInstall($module_data[$module]->getType(), $module)) {
+        break;
+      }
     }
 
     // Required for module installation checks.
diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigInstallWebTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigInstallWebTest.php
index 776daa4..39212a3 100644
--- a/core/modules/config/lib/Drupal/config/Tests/ConfigInstallWebTest.php
+++ b/core/modules/config/lib/Drupal/config/Tests/ConfigInstallWebTest.php
@@ -96,6 +96,13 @@ function testIntegrationModuleReinstallation() {
     $config_entity = \Drupal::config($default_configuration_entity);
     $this->assertIdentical($config_entity->isNew(), FALSE);
     $this->assertIdentical($config_entity->get('label'), 'Customized integration config label');
+
+    // Verify that installing a module with default configuration that already
+    // exists in active configuration produces a warning.
+    \Drupal::moduleHandler()->install(array('config_install_fail'));
+    $messages = drupal_get_messages('error');
+    $expected_message = t('%extension cannot be installed because default configuration named %config_name already exists in active configuration.', array('%config_name' => 'config_test.dynamic.dotted.default', '%extension_name' => 'config_install_fail'));
+    $this->assertTrue(in_array($expected_message, $messages['error']), 'Error message about existing configuration exists.');
   }
 
   /**
diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigInstallWebTest.php.orig b/core/modules/config/lib/Drupal/config/Tests/ConfigInstallWebTest.php.orig
new file mode 100644
index 0000000..7116bea
--- /dev/null
+++ b/core/modules/config/lib/Drupal/config/Tests/ConfigInstallWebTest.php.orig
@@ -0,0 +1,152 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\config\Tests\ConfigInstallTest.
+ */
+
+namespace Drupal\config\Tests;
+
+use Drupal\simpletest\WebTestBase;
+use Drupal\Core\Config\FileStorage;
+
+/**
+ * Tests installation of configuration objects in installation functionality.
+ */
+class ConfigInstallWebTest extends WebTestBase {
+  public static function getInfo() {
+    return array(
+      'name' => 'Install, disable and uninstall functionality',
+      'description' => 'Tests installation and removal of configuration objects in install, disable and uninstall functionality.',
+      'group' => 'Configuration',
+    );
+  }
+
+  function setUp() {
+    parent::setUp();
+
+    // Ensure the global variable being asserted by this test does not exist;
+    // a previous test executed in this request/process might have set it.
+    unset($GLOBALS['hook_config_test']);
+  }
+
+  /**
+   * Tests module re-installation.
+   */
+  function testIntegrationModuleReinstallation() {
+    $default_config = 'config_integration_test.settings';
+    $default_configuration_entity = 'config_test.dynamic.config_integration_test';
+
+    // Install the config_test module we're integrating with.
+    \Drupal::moduleHandler()->install(array('config_test'));
+
+    // Verify the configuration does not exist prior to installation.
+    $config_static = \Drupal::config($default_config);
+    $this->assertIdentical($config_static->isNew(), TRUE);
+    $config_entity = \Drupal::config($default_configuration_entity);
+    $this->assertIdentical($config_entity->isNew(), TRUE);
+
+    // Install the integration module.
+    \Drupal::moduleHandler()->install(array('config_integration_test'));
+
+    // Verify that default module config exists.
+    \Drupal::configFactory()->reset($default_config);
+    \Drupal::configFactory()->reset($default_configuration_entity);
+    $config_static = \Drupal::config($default_config);
+    $this->assertIdentical($config_static->isNew(), FALSE);
+    $this->assertIdentical($config_static->get('foo'), 'default setting');
+    $config_entity = \Drupal::config($default_configuration_entity);
+    $this->assertIdentical($config_entity->isNew(), FALSE);
+    $this->assertIdentical($config_entity->get('label'), 'Default integration config label');
+
+    // Customize both configuration objects.
+    $config_static->set('foo', 'customized setting')->save();
+    $config_entity->set('label', 'Customized integration config label')->save();
+
+    // @todo FIXME: Setting config keys WITHOUT SAVING retains the changed config
+    //   object in memory. Every new call to \Drupal::config() MUST revert in-memory changes
+    //   that haven't been saved!
+    //   In other words: This test passes even without this reset, but it shouldn't.
+    $this->container->get('config.factory')->reset();
+
+    // Disable and uninstall the integration module.
+    module_uninstall(array('config_integration_test'));
+
+    // Verify the integration module's config was uninstalled.
+    $config_static = \Drupal::config($default_config);
+    $this->assertIdentical($config_static->isNew(), TRUE);
+
+    // Verify the integration config still exists.
+    $config_entity = \Drupal::config($default_configuration_entity);
+    $this->assertIdentical($config_entity->isNew(), FALSE);
+    $this->assertIdentical($config_entity->get('label'), 'Customized integration config label');
+
+    // Reinstall the integration module.
+    \Drupal::moduleHandler()->install(array('config_integration_test'));
+
+    // Verify the integration module's config was re-installed.
+    \Drupal::configFactory()->reset($default_config);
+    \Drupal::configFactory()->reset($default_configuration_entity);
+    $config_static = \Drupal::config($default_config);
+    $this->assertIdentical($config_static->isNew(), FALSE);
+    $this->assertIdentical($config_static->get('foo'), 'default setting');
+
+    // Verify the customized integration config still exists.
+    $config_entity = \Drupal::config($default_configuration_entity);
+    $this->assertIdentical($config_entity->isNew(), FALSE);
+    $this->assertIdentical($config_entity->get('label'), 'Customized integration config label');
+  }
+
+  /**
+   * Tests install profile config changes.
+   */
+  function testInstallProfileConfigOverwrite() {
+    $config_name = 'system.cron';
+    // The expected configuration from the system module.
+    $expected_original_data = array(
+      'threshold' => array(
+        'autorun' => 0,
+        'requirements_warning' => 172800,
+        'requirements_error' => 1209600,
+      ),
+    );
+    // The expected active configuration altered by the install profile.
+    $expected_profile_data = array(
+      'threshold' => array(
+        'autorun' => 0,
+        'requirements_warning' => 259200,
+        'requirements_error' => 1209600,
+      ),
+    );
+
+    // Verify that the original data matches. We have to read the module config
+    // file directly, because the install profile default system.cron.yml
+    // configuration file was used to create the active configuration.
+    $config_dir = drupal_get_path('module', 'system') . '/config';
+    $this->assertTrue(is_dir($config_dir));
+    $source_storage = new FileStorage($config_dir);
+    $data = $source_storage->read($config_name);
+    $this->assertIdentical($data, $expected_original_data);
+
+    // Verify that active configuration matches the expected data, which was
+    // created from the testing install profile's system.cron.yml file.
+    $config = \Drupal::config($config_name);
+    $this->assertIdentical($config->get(), $expected_profile_data);
+
+    // Turn on the test module, which will attempt to replace the
+    // configuration data. This attempt to replace the active configuration
+    // should be ignored.
+    \Drupal::moduleHandler()->install(array('config_override_test'));
+
+    // Verify that the test module has not been able to change the data.
+    $config = \Drupal::config($config_name);
+    $this->assertIdentical($config->get(), $expected_profile_data);
+
+    // Disable and uninstall the test module.
+    \Drupal::moduleHandler()->uninstall(array('config_override_test'));
+
+    // Verify that the data hasn't been altered by removing the test module.
+    $config = \Drupal::config($config_name);
+    $this->assertIdentical($config->get(), $expected_profile_data);
+  }
+}
diff --git a/core/modules/config/tests/config_install_fail/config/config_test.dynamic.dotted.default.yml b/core/modules/config/tests/config_install_fail/config/config_test.dynamic.dotted.default.yml
new file mode 100644
index 0000000..6e2af21
--- /dev/null
+++ b/core/modules/config/tests/config_install_fail/config/config_test.dynamic.dotted.default.yml
@@ -0,0 +1,6 @@
+id: dotted.default
+label: 'Config install fail'
+weight: 0
+protected_property: Default
+# Intentionally commented out to verify default status behavior.
+# status: 1
diff --git a/core/modules/config/tests/config_install_fail/config_install_fail.info.yml b/core/modules/config/tests/config_install_fail/config_install_fail.info.yml
new file mode 100644
index 0000000..ebe72ad
--- /dev/null
+++ b/core/modules/config/tests/config_install_fail/config_install_fail.info.yml
@@ -0,0 +1,8 @@
+name: 'Configuration test install fial'
+type: module
+package: Testing
+version: VERSION
+core: 8.x
+hidden: true
+dependencies:
+  - config_test
diff --git a/core/modules/config/tests/config_install_fail/config_install_fail.module b/core/modules/config/tests/config_install_fail/config_install_fail.module
new file mode 100644
index 0000000..e77c7ce
--- /dev/null
+++ b/core/modules/config/tests/config_install_fail/config_install_fail.module
@@ -0,0 +1,6 @@
+<?php
+
+/**
+ * @file
+ * Empty module to test providing a default config entity with the same name.
+ */
diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldImportChangeTest.php b/core/modules/field/lib/Drupal/field/Tests/FieldImportChangeTest.php
index d5d6407..ac56a73 100644
--- a/core/modules/field/lib/Drupal/field/Tests/FieldImportChangeTest.php
+++ b/core/modules/field/lib/Drupal/field/Tests/FieldImportChangeTest.php
@@ -15,6 +15,10 @@ class FieldImportChangeTest extends FieldUnitTestBase {
   /**
    * Modules to enable.
    *
+   * The default configuration provided by field_test_config is imported by
+   * \Drupal\field\Tests\FieldUnitTestBase::setUp() when it installs field
+   * configuration.
+   *
    * @var array
    */
   public static $modules = array('field_test_config');
@@ -35,8 +39,6 @@ function testImportChange() {
     $instance_id = "entity_test.entity_test.$field_id";
     $instance_config_name = "field.instance.$instance_id";
 
-    // Import default config.
-    $this->installConfig(array('field_test_config'));
     $active = $this->container->get('config.storage');
     $staging = $this->container->get('config.storage.staging');
     $this->copyConfig($active, $staging);
diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldImportDeleteTest.php b/core/modules/field/lib/Drupal/field/Tests/FieldImportDeleteTest.php
index b0485c4..c3142a3 100644
--- a/core/modules/field/lib/Drupal/field/Tests/FieldImportDeleteTest.php
+++ b/core/modules/field/lib/Drupal/field/Tests/FieldImportDeleteTest.php
@@ -17,6 +17,10 @@ class FieldImportDeleteTest extends FieldUnitTestBase {
   /**
    * Modules to enable.
    *
+   * The default configuration provided by field_test_config is imported by
+   * \Drupal\field\Tests\FieldUnitTestBase::setUp() when it installs field
+   * configuration.
+   *
    * @var array
    */
   public static $modules = array('field_test_config');
@@ -57,9 +61,6 @@ public function testImportDelete() {
     // Create a second bundle for the 'Entity test' entity type.
     entity_test_create_bundle('test_bundle');
 
-    // Import default config.
-    $this->installConfig(array('field_test_config'));
-
     // Get the uuid's for the fields.
     $field_uuid = entity_load('field_config', $field_id)->uuid();
     $field_uuid_2 = entity_load('field_config', $field_id_2)->uuid();
