diff --git a/core/includes/update.inc b/core/includes/update.inc
index bf11562..c12268e 100644
--- a/core/includes/update.inc
+++ b/core/includes/update.inc
@@ -1533,3 +1533,30 @@ function update_add_cache_columns($table) {
     ));
   }
 }
+
+/**
+ * Rename permissions during update.
+ *
+ * This function can rename one permission to several or even delete an old
+ * one.
+ *
+ * @param $rename
+ *   An asssociative array. The keys are the old permissions the values are
+ *   a list of new permissions. If the list is an empty array, the old
+ *   permission is removed.
+ */
+function update_rename_permissions($rename) {
+  $config = config('user.permission');
+  $all_permissions = $config->get();
+  foreach ($all_permissions as $rid => $permissions) {
+    foreach ($rename as $old_permission => $new_permissions) {
+      $key = array_search($old_permission, $permissions);
+      if ($key !== FALSE) {
+        unset($permissions[$key]);
+        $permissions = array_merge($permissions, $new_permissions);
+      }
+    }
+    $config->set($rid, $permissions);
+  }
+  $config->save();
+}
diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module
index dd87b29..92898fd 100644
--- a/core/modules/comment/comment.module
+++ b/core/modules/comment/comment.module
@@ -1243,18 +1243,21 @@ function comment_node_update_index(EntityInterface $node, $langcode) {
   $index_comments = &drupal_static(__FUNCTION__);
 
   if ($index_comments === NULL) {
-    // Find and save roles that can 'access comments' or 'search content'.
-    $perms = array('access comments' => array(), 'search content' => array());
-    $result = db_query("SELECT rid, permission FROM {role_permission} WHERE permission IN ('access comments', 'search content')");
-    foreach ($result as $record) {
-      $perms[$record->permission][$record->rid] = $record->rid;
-    }
-
-    // Prevent indexing of comments if there are any roles that can search but
-    // not view comments.
+    // Do not index in the following three cases:
+    // 1. 'Authenticated user' can search content but can't access comments.
+    // 2. 'Anonymous user' can search content but can't access comments.
+    // 3. Any role can search content but can't access comments and access
+    // comments is not granted by the 'authenticated user' role. In this case
+    // all users might have both permissions from various roles but it is also
+    // possible to set up a user to have only search content and so a user
+    // edit could change the security situation so it is not safe to index the
+    // comments.
     $index_comments = TRUE;
-    foreach ($perms['search content'] as $rid) {
-      if (!isset($perms['access comments'][$rid]) && (($rid == DRUPAL_AUTHENTICATED_RID || $rid == DRUPAL_ANONYMOUS_RID) || !isset($perms['access comments'][DRUPAL_AUTHENTICATED_RID]))) {
+    $all_permissions = config('user.permission')->get();
+    $authenticated_can_access = in_array('access comments', $all_permissions[DRUPAL_AUTHENTICATED_RID]);
+    foreach ($all_permissions as $rid => $permissions) {
+      if (in_array('search content', $permissions) && !in_array('access comments', $permissions) &&
+         ($rid == DRUPAL_AUTHENTICATED_RID || $rid == DRUPAL_ANONYMOUS_RID || !$authenticated_can_access)) {
         $index_comments = FALSE;
         break;
       }
diff --git a/core/modules/field_ui/field_ui.install b/core/modules/field_ui/field_ui.install
index f0ad035..f486cc4 100644
--- a/core/modules/field_ui/field_ui.install
+++ b/core/modules/field_ui/field_ui.install
@@ -10,7 +10,7 @@
  */
 function field_ui_update_8001() {
 
-  $permissions = array(
+  $rename = array(
     'administer comments' => array(
       'administer comment fields',
       'administer comment display',
@@ -28,23 +28,5 @@ function field_ui_update_8001() {
       'administer taxonomy_term display',
     ),
   );
-
-  // We can not call user_permission_get_modules() as that will start
-  // invoking hooks which we can't during update hooks. Directly query
-  // for the permissions and insert them into the database.
-  foreach ($permissions as $old_permission => $new_permissions) {
-    $results = db_query("SELECT rid FROM {role_permission} WHERE permission = :permission", array(':permission' => $old_permission));
-    foreach ($results as $record) {
-      $query = db_insert('role_permission')->fields(array('rid', 'permission', 'module'));
-      foreach ($new_permissions as $new_permission) {
-        $query->values(array($record->rid, $new_permission, 'field_ui'));
-      }
-      $query->execute();
-    }
-
-    // Remove old permission.
-    db_delete('role_permission')
-      ->condition('permission', $old_permission)
-      ->execute();
-  }
+  update_rename_permissions($rename);
 }
diff --git a/core/modules/filter/lib/Drupal/filter/Tests/FilterDefaultConfigTest.php b/core/modules/filter/lib/Drupal/filter/Tests/FilterDefaultConfigTest.php
index 85b5fef..f7f91d1 100644
--- a/core/modules/filter/lib/Drupal/filter/Tests/FilterDefaultConfigTest.php
+++ b/core/modules/filter/lib/Drupal/filter/Tests/FilterDefaultConfigTest.php
@@ -30,7 +30,7 @@ function setUp() {
     // filter_permission() calls into url() to output a link in the description.
     $this->installSchema('system', 'url_alias');
 
-    $this->installSchema('user', array('users_roles', 'role_permission'));
+    $this->installSchema('user', array('users_roles'));
 
     // Install filter_test module, which ships with custom default format.
     $this->installConfig(array('user', 'filter_test'));
diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeAccessLanguageTest.php b/core/modules/node/lib/Drupal/node/Tests/NodeAccessLanguageTest.php
index ae2aee4..75b3c80 100644
--- a/core/modules/node/lib/Drupal/node/Tests/NodeAccessLanguageTest.php
+++ b/core/modules/node/lib/Drupal/node/Tests/NodeAccessLanguageTest.php
@@ -41,11 +41,10 @@ function assertNodeAccess($ops, $node, $account, $langcode = NULL) {
 
   function setUp() {
     parent::setUp();
-
     // Clear permissions for authenticated users.
-    db_delete('role_permission')
-      ->condition('rid', DRUPAL_AUTHENTICATED_RID)
-      ->execute();
+    config('user.permission')
+      ->clear(DRUPAL_AUTHENTICATED_RID)
+      ->save();
   }
 
   /**
diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeAccessTest.php b/core/modules/node/lib/Drupal/node/Tests/NodeAccessTest.php
index 4f87348..6fcd2bc 100644
--- a/core/modules/node/lib/Drupal/node/Tests/NodeAccessTest.php
+++ b/core/modules/node/lib/Drupal/node/Tests/NodeAccessTest.php
@@ -36,9 +36,9 @@ function assertNodeAccess($ops, $node, $account) {
   function setUp() {
     parent::setUp();
     // Clear permissions for authenticated users.
-    db_delete('role_permission')
-      ->condition('rid', DRUPAL_AUTHENTICATED_RID)
-      ->execute();
+    config('user.permission')
+      ->clear(DRUPAL_AUTHENTICATED_RID)
+      ->save();
   }
 
   /**
diff --git a/core/modules/node/node.install b/core/modules/node/node.install
index ebbce13..4bdc9c0 100644
--- a/core/modules/node/node.install
+++ b/core/modules/node/node.install
@@ -465,6 +465,15 @@ function _update_7000_node_get_types() {
  */
 
 /**
+ * Implements hook_update_dependency().
+ */
+function node_update_dependency() {
+  $dependencies['node'][8013] = array(
+    'user' => 8002,
+  );
+}
+
+/**
  * Rename node type language variable names.
  *
  * @see http://drupal.org/node/540294
@@ -690,15 +699,11 @@ function node_update_8012() {
  * Renames global revision permissions to use the word 'all'.
  */
 function node_update_8013() {
-  $actions = array('view', 'delete', 'revert');
-
-  foreach ($actions as $action) {
-    db_update('role_permission')
-      ->fields(array('permission' => $action . ' all revisions'))
-      ->condition('permission', $action . ' revisions')
-      ->condition('module', 'node')
-      ->execute();
-  }
+  update_rename_permissions(array(
+    'view revisions' => array('view all revisions'),
+    'revert revisions' => array('revert all revisions'),
+    'delete revisions' => array('delete all revisions'),
+  ));
 }
 
 /**
diff --git a/core/modules/node/node.views.inc b/core/modules/node/node.views.inc
index 5d14a38..74fb72d 100644
--- a/core/modules/node/node.views.inc
+++ b/core/modules/node/node.views.inc
@@ -655,17 +655,10 @@ function node_views_analyze(ViewExecutable $view) {
         // check for no access control
         $access = $display->getOption('access');
         if (empty($access['type']) || $access['type'] == 'none') {
-          $result = db_select('role_permission', 'p')
-            ->fields('p', array('rid', 'permission'))
-            ->condition('p.rid', array(DRUPAL_ANONYMOUS_RID, DRUPAL_AUTHENTICATED_RID), 'IN')
-            ->condition('p.permission', 'access content')
-            ->execute();
-
-          foreach ($result as $role) {
-            $role->safe = TRUE;
-            $roles[$role->rid] = $role;
-          }
-          if (!($roles[DRUPAL_ANONYMOUS_RID]->safe && $roles[DRUPAL_AUTHENTICATED_RID]->safe)) {
+          $config = config('user.permission');
+          $anonymous_has_access = in_array('access content', $config->get(DRUPAL_ANONYMOUS_RID));
+          $authenticated_has_access = in_array('access content', $config->get(DRUPAL_ANONYMOUS_RID));
+          if (!$anonymous_has_access || !$authenticated_has_access) {
             $ret[] = Analyzer::formatMessage(t('Some roles lack permission to access content, but display %display has no access control.', array('%display' => $display->display['display_title'])), 'warning');
           }
           $filters = $display->getOption('filters');
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
index 9e8b097..801db2a 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
@@ -546,8 +546,7 @@ protected function drupalCreateRole(array $permissions, $rid = NULL, $name = NUL
       // Grant the specified permissions to the role, if any.
       if (!empty($permissions)) {
         user_role_grant_permissions($role->id(), $permissions);
-
-        $assigned_permissions = db_query('SELECT permission FROM {role_permission} WHERE rid = :rid', array(':rid' => $role->id()))->fetchCol();
+        $assigned_permissions = config('user.permission')->get($role->id());
         $missing_permissions = array_diff($permissions, $assigned_permissions);
         if (!$missing_permissions) {
           $this->pass(t('Created permissions: @perms', array('@perms' => implode(', ', $permissions))), t('Role'));
diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityAccessTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityAccessTest.php
index 0642032..b3f2020 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityAccessTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityAccessTest.php
@@ -29,7 +29,7 @@ public static function getInfo() {
 
   function setUp() {
     parent::setUp();
-    $this->installSchema('user', array('role_permission', 'users_roles'));
+    $this->installSchema('user', array('users_roles'));
     $this->installSchema('system', array('variable', 'url_alias'));
     $this->installSchema('language', 'language');
 
diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityBCDecoratorTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityBCDecoratorTest.php
index 892fd18..27a45fb 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityBCDecoratorTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityBCDecoratorTest.php
@@ -31,7 +31,7 @@ public static function getInfo() {
 
   public function setUp() {
     parent::setUp();
-    $this->installSchema('user', array('users_roles', 'users_data', 'role_permission'));
+    $this->installSchema('user', array('users_data'));
     $this->installSchema('node', array('node', 'node_revision', 'node_type', 'node_access'));
     $this->installSchema('comment', array('comment', 'node_comment_statistics'));
   }
diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityUnitTestBase.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityUnitTestBase.php
index b747e79..f4d726c 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityUnitTestBase.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityUnitTestBase.php
@@ -36,8 +36,7 @@ public function setUp() {
    *   (optional) The values used to create the entity.
    * @param array $permissions
    *   (optional) Array of permission names to assign to user. The
-   *   role_permission and users_roles tables must be installed before this can
-   *   be used.
+   *   users_roles tables must be installed before this can be used.
    *
    * @return \Drupal\user\Plugin\Core\Entity\User
    *   The created user entity.
diff --git a/core/modules/system/lib/Drupal/system/Tests/Module/UninstallTest.php b/core/modules/system/lib/Drupal/system/Tests/Module/UninstallTest.php
index 3345d2f..78cecbf 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Module/UninstallTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Module/UninstallTest.php
@@ -38,8 +38,7 @@ function testUserPermsUninstalled() {
     module_disable(array('module_test'));
     module_uninstall(array('module_test'));
 
-    // Are the perms defined by module_test removed from {role_permission}.
-    $count = db_query("SELECT COUNT(rid) FROM {role_permission} WHERE permission = :perm", array(':perm' => 'module_test perm'))->fetchField();
-    $this->assertEqual(0, $count, 'Permissions were all removed.');
+    // Are the perms defined by module_test removed?
+    $this->assertFalse(user_roles(FALSE, 'module_test perm'), 'Permissions were all removed.');
   }
 }
diff --git a/core/modules/system/lib/Drupal/system/Tests/Upgrade/LanguageUpgradePathTest.php b/core/modules/system/lib/Drupal/system/Tests/Upgrade/LanguageUpgradePathTest.php
index 6b669a5..f0729f6 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Upgrade/LanguageUpgradePathTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Upgrade/LanguageUpgradePathTest.php
@@ -184,6 +184,8 @@ public function testLanguageNoPluralsUpgrade() {
    * Tests upgrading translations permissions.
    */
   public function testLanguagePermissionsUpgrade() {
+    // Insert a permission into the Drupal 7 database before running the
+    // upgrade.
     db_insert('role_permission')->fields(array(
       'rid' => 2,
       'permission' => 'translate content',
@@ -191,12 +193,8 @@ public function testLanguagePermissionsUpgrade() {
     ))->execute();
 
     $this->assertTrue($this->performUpgrade(), 'The upgrade was completed successfully.');
-
-    // Check that translate content role doesn't exist on database.
-    $old_permission_exists = db_query('SELECT * FROM {role_permission} WHERE permission LIKE ?', array('translate content'))->fetchObject();
-    $this->assertFalse($old_permission_exists, 'No translate content role left on database.');
+    $this->assertFalse(user_roles(FALSE, 'translate content'), 'No translate content role left on database.');
     // Check that translate content has been renamed to translate all content.
-    $new_permission_exists = db_query('SELECT * FROM {role_permission} WHERE permission LIKE ?', array('translate all content'))->fetchObject();
-    $this->assertTrue($new_permission_exists, 'Rename role translate content to translate all content was completed successfully.');
+    $this->assertTrue(user_roles(FALSE, 'translate all content'), 'Rename role translate content to translate all content was completed successfully.');
   }
 }
diff --git a/core/modules/system/system.install b/core/modules/system/system.install
index 08a9fd9..b1ee63a 100644
--- a/core/modules/system/system.install
+++ b/core/modules/system/system.install
@@ -1611,13 +1611,12 @@ function system_update_8020() {
   $blocked_ips_exists = db_query_range('SELECT 1 FROM {blocked_ips}', 0, 1)->fetchField();
   if ($blocked_ips_exists) {
     // Rename the permission name.
-    db_update('role_permission')
-      ->fields(array(
-        'permission' => 'ban IP addresses',
-        'module' => 'ban',
-      ))
-      ->condition('permission', 'block IP addresses')
-      ->execute();
+    update_rename_permissions(array(
+      'block IP addresses' => array('ban IP addresses'),
+    ));
+    config('user.permission.module')
+      ->set("ban.ban IP addresses", TRUE)
+      ->save();
     // Rename {blocked_ips} table into {ban_ip}.
     db_rename_table('blocked_ips', 'ban_ip');
     // Remove all references to the removed action callback.
diff --git a/core/modules/translation/translation.install b/core/modules/translation/translation.install
index 61d014d..f91b975 100644
--- a/core/modules/translation/translation.install
+++ b/core/modules/translation/translation.install
@@ -10,10 +10,9 @@
  * Rename the translate content permission.
  */
 function translation_update_8000() {
-  db_update('role_permission')
-    ->fields(array('permission' => 'translate all content'))
-    ->condition('permission', 'translate content')
-    ->execute();
+  update_rename_permissions(array(
+    'translate content' => array('translate all content'),
+  ));
 }
 
 /**
diff --git a/core/modules/user/lib/Drupal/user/Plugin/views/field/Permissions.php b/core/modules/user/lib/Drupal/user/Plugin/views/field/Permissions.php
index 7688c84..56c01ba 100644
--- a/core/modules/user/lib/Drupal/user/Plugin/views/field/Permissions.php
+++ b/core/modules/user/lib/Drupal/user/Plugin/views/field/Permissions.php
@@ -47,28 +47,21 @@ function pre_render(&$values) {
     }
 
     if ($uids) {
-      // Get a list of all the modules implementing a hook_permission() and sort by
-      // display name.
-      $module_info = system_get_info('module');
-      $modules = array();
-      foreach (module_implements('permission') as $module) {
-        $modules[$module] = $module_info[$module]['name'];
-      }
-      asort($modules);
-
-      $permissions = module_invoke_all('permission');
-
-      $query = db_select('role_permission', 'rp');
-      $query->join('users_roles', 'u', 'u.rid = rp.rid');
+      $permission_names = module_invoke_all('permission');
+      $query = db_select('users_roles', 'u');
       $query->fields('u', array('uid', 'rid'));
-      $query->addField('rp', 'permission');
       $query->condition('u.uid', $uids);
-      $query->condition('rp.module', array_keys($modules));
-      $query->orderBy('rp.permission');
       $result = $query->execute();
-
-      foreach ($result as $perm) {
-        $this->items[$perm->uid][$perm->permission]['permission'] = $permissions[$perm->permission]['title'];
+      $config = config('user.permission');
+      foreach ($result as $row) {
+        foreach ($config->get($row->rid) as $permission) {
+          $this->items[$row->uid][$permission]['permission'] = $permission_names[$permission]['title'];
+        }
+      }
+      foreach ($uids as $uid) {
+        if (isset($this->items[$uid])) {
+          ksort($this->items[$uid]);
+        }
       }
     }
   }
diff --git a/core/modules/user/lib/Drupal/user/RoleStorageController.php b/core/modules/user/lib/Drupal/user/RoleStorageController.php
index f5f6575..b05c779 100644
--- a/core/modules/user/lib/Drupal/user/RoleStorageController.php
+++ b/core/modules/user/lib/Drupal/user/RoleStorageController.php
@@ -26,6 +26,11 @@ public function preSave(EntityInterface $entity) {
       });
       $entity->weight = $max + 1;
     }
+    if ($entity->isNew()) {
+      config('user.permission')
+        ->set($entity->id(), array())
+        ->save();
+    }
     parent::preSave($entity);
   }
 
@@ -37,7 +42,7 @@ public function resetCache(array $ids = NULL) {
 
     // Clear the user access cache.
     drupal_static_reset('user_access');
-    drupal_static_reset('user_role_permissions');
+    config('user.permission')->init();
   }
 
   /**
@@ -47,9 +52,11 @@ protected function postDelete($entities) {
     $rids = array_keys($entities);
 
     // Delete permission assignments.
-    db_delete('role_permission')
-      ->condition('rid', $rids)
-      ->execute();
+    $config = config('user.permission');
+    foreach ($rids as $rid) {
+      $config->clear($rid);
+    }
+    $config->save();
     // Remove the role from all users.
     db_delete('users_roles')
       ->condition('rid', $rids)
diff --git a/core/modules/user/lib/Drupal/user/Tests/UserPermissionsTest.php b/core/modules/user/lib/Drupal/user/Tests/UserPermissionsTest.php
index 2455b10..3721e60 100644
--- a/core/modules/user/lib/Drupal/user/Tests/UserPermissionsTest.php
+++ b/core/modules/user/lib/Drupal/user/Tests/UserPermissionsTest.php
@@ -47,7 +47,7 @@ function testUserPermissionChanges() {
     $this->drupalPost('admin/people/permissions', $edit, t('Save permissions'));
     $this->assertText(t('The changes have been saved.'), 'Successful save message displayed.');
     drupal_static_reset('user_access');
-    drupal_static_reset('user_role_permissions');
+    config('user.permission')->init();
     $this->assertTrue(user_access('administer nodes', $account), 'User now has "administer nodes" permission.');
 
     // Remove a permission.
@@ -57,7 +57,7 @@ function testUserPermissionChanges() {
     $this->drupalPost('admin/people/permissions', $edit, t('Save permissions'));
     $this->assertText(t('The changes have been saved.'), 'Successful save message displayed.');
     drupal_static_reset('user_access');
-    drupal_static_reset('user_role_permissions');
+    config('user.permission')->init();
     $this->assertFalse(user_access('access user profiles', $account), 'User no longer has "access user profiles" permission.');
   }
 
diff --git a/core/modules/user/user.install b/core/modules/user/user.install
index c7fd16b..f87c35f 100644
--- a/core/modules/user/user.install
+++ b/core/modules/user/user.install
@@ -148,42 +148,6 @@ function user_schema() {
     ),
   );
 
-  $schema['role_permission'] = array(
-    'description' => 'Stores the permissions assigned to user roles.',
-    'fields' => array(
-      'rid' => array(
-        'type' => 'varchar',
-        'length' => 64,
-        'not null' => TRUE,
-        'description' => 'Foreign Key: {role}.rid.',
-      ),
-      'permission' => array(
-        'type' => 'varchar',
-        'length' => 128,
-        'not null' => TRUE,
-        'default' => '',
-        'description' => 'A single permission granted to the role identified by rid.',
-      ),
-      'module' => array(
-        'type' => 'varchar',
-        'length' => 255,
-        'not null' => TRUE,
-        'default' => '',
-        'description' => "The module declaring the permission.",
-      ),
-    ),
-    'primary key' => array('rid', 'permission'),
-    'indexes' => array(
-      'permission' => array('permission'),
-    ),
-    'foreign keys' => array(
-      'role' => array(
-        'table' => 'role',
-        'columns' => array('rid' => 'rid'),
-      ),
-    ),
-  );
-
   $schema['users_data'] = array(
     'description' => 'Stores module data as key/value pairs per user.',
     'fields' => array(
@@ -441,9 +405,6 @@ function user_update_8002() {
   );
   db_change_field('role', 'rid', 'rid', $column);
 
-  $column['description'] = 'Foreign Key: {role}.rid.';
-  db_change_field('role_permission', 'rid', 'rid', $column);
-
   $column['description'] = 'Primary Key: {role}.rid for role.';
   db_change_field('users_roles', 'rid', 'rid', $column);
 
@@ -460,32 +421,16 @@ function user_update_8002() {
   db_drop_unique_key('role', 'name');
 
   // Rename the built-in serial role IDs into the hardcoded machine names.
-  db_update('role')
-    ->fields(array('rid' => DRUPAL_ANONYMOUS_RID))
-    ->condition('rid', 1)
-    ->execute();
-  db_update('role')
-    ->fields(array('rid' => DRUPAL_AUTHENTICATED_RID))
-    ->condition('rid', 2)
-    ->execute();
-
-  db_update('role_permission')
-    ->fields(array('rid' => DRUPAL_ANONYMOUS_RID))
-    ->condition('rid', 1)
-    ->execute();
-  db_update('role_permission')
-    ->fields(array('rid' => DRUPAL_AUTHENTICATED_RID))
-    ->condition('rid', 2)
-    ->execute();
-
-  db_update('users_roles')
-    ->fields(array('rid' => DRUPAL_ANONYMOUS_RID))
-    ->condition('rid', 1)
-    ->execute();
-  db_update('users_roles')
-    ->fields(array('rid' => DRUPAL_AUTHENTICATED_RID))
-    ->condition('rid', 2)
-    ->execute();
+  foreach (array(1, 2) as $rid) {
+    db_update('role')
+      ->fields(array('rid' => _user_update_map_rid($rid)))
+      ->condition('rid', $rid)
+      ->execute();
+    db_update('users_roles')
+      ->fields(array('rid' => _user_update_map_rid($rid)))
+      ->condition('rid', $rid)
+      ->execute();
+  }
 }
 
 /**
@@ -1038,7 +983,7 @@ function user_update_8017() {
     ->fields('r')
     ->execute()
     ->fetchAll();
-
+  $config_permission = config('user.permission');
   foreach ($roles as $role) {
     config('user.role.' . $role->rid)
       ->set('id', $role->rid)
@@ -1047,7 +992,9 @@ function user_update_8017() {
       ->set('weight', $role->weight)
       ->set('langcode', LANGUAGE_NOT_SPECIFIED)
       ->save();
+    $config_permission->set(_user_update_map_rid($role->rid), array());
   }
+  $config_permission->save();
 
   update_config_manifest_add('user.role', array_map(function ($role) {
     return $role->rid;
@@ -1055,5 +1002,41 @@ function user_update_8017() {
 }
 
 /**
+ * Maps a role id to the new string.
+ *
+ * @param int $rid
+ *   A D7 numeric role ID.
+ * @return string
+ *   A D8 string role ID.
+ */
+function _user_update_map_rid($rid) {
+  $rid_map = array(
+    1 => DRUPAL_ANONYMOUS_RID,
+    2 => DRUPAL_AUTHENTICATED_RID,
+  );
+  return isset($rid_map[$rid]) ? $rid_map[$rid] : $rid;
+}
+/**
+ * Migrate roles permissions into configuration.
+ *
+ * @ingroup config_upgrade
+ */
+function user_update_8018() {
+  $db_permissions = db_select('role_permission', 'p')
+    ->fields('p')
+    ->execute()
+    ->fetchAll();
+  $new_permissions = array();
+  foreach ($db_permissions as $permission) {
+    $new_permissions[_user_update_map_rid($permission->rid)][] = $permission->permission;
+  }
+  $config = config('user.permission');
+  $empty_permissions = $config->get();
+  $config
+    ->setData($new_permissions + $empty_permissions)
+    ->save();
+}
+
+/**
  * @} End of "addtogroup updates-7.x-to-8.x".
  */
diff --git a/core/modules/user/user.module b/core/modules/user/user.module
index bdf5862..92422a0 100644
--- a/core/modules/user/user.module
+++ b/core/modules/user/user.module
@@ -429,34 +429,12 @@ function user_password($length = 10) {
  *   An array indexed by role ID. Each value is an array whose keys are the
  *   permission strings for the given role ID.
  */
-function user_role_permissions($roles) {
-  $cache = &drupal_static(__FUNCTION__, array());
-
-  $role_permissions = $fetch = array();
-
+function user_role_permissions(array $roles) {
+  $role_permissions = array();
   foreach ($roles as $rid => $name) {
-    if (isset($cache[$rid])) {
-      $role_permissions[$rid] = $cache[$rid];
-    }
-    else {
-      // Add this rid to the list of those needing to be fetched.
-      $fetch[] = $rid;
-      // Prepare in case no permissions are returned.
-      $cache[$rid] = array();
-    }
-  }
-
-  if ($fetch) {
-    // Get from the database permissions that were not in the static variable.
-    // Only role IDs with at least one permission assigned will return rows.
-    $result = db_query("SELECT rid, permission FROM {role_permission} WHERE rid IN (:fetch)", array(':fetch' => $fetch));
-
-    foreach ($result as $row) {
-      $cache[$row->rid][$row->permission] = TRUE;
-    }
-    foreach ($fetch as $rid) {
-      // For every rid, we know we at least assigned an empty array.
-      $role_permissions[$rid] = $cache[$rid];
+    $role_permissions[$rid] = array();
+    foreach (config('user.permission')->get($rid) as $permission) {
+      $role_permissions[$rid][$permission] = TRUE;
     }
   }
 
@@ -1826,12 +1804,11 @@ function user_roles($membersonly = FALSE, $permission = NULL) {
   }
 
   if (!empty($permission)) {
-    $result = db_select('role_permission', 'p')
-      ->fields('p', array('rid'))
-      ->condition('p.rid', array_keys($roles))
-      ->condition('p.permission', $permission)
-      ->execute()->fetchCol();
-    $roles = array_intersect_key($roles, array_flip($result));
+    foreach (config('user.permission')->get() as $rid => $permissions) {
+      if (!in_array($permission, $permissions)) {
+        unset($roles[$rid]);
+      }
+    }
   }
 
   if (empty($permission)) {
@@ -1938,23 +1915,22 @@ function user_role_change_permissions($rid, array $permissions = array()) {
  * @see user_role_revoke_permissions()
  */
 function user_role_grant_permissions($rid, array $permissions = array()) {
-  $modules = user_permission_get_modules();
   // Grant new permissions for the role.
-  foreach ($permissions as $name) {
-    db_merge('role_permission')
-      ->key(array(
-        'rid' => $rid,
-        'permission' => $name,
-      ))
-      ->fields(array(
-        'module' => $modules[$name],
-      ))
-      ->execute();
+  $config = config('user.permission');
+  $old_permissions = (array) $config->get($rid);
+  $new_permissions = array_unique(array_merge($old_permissions, $permissions));
+  $config
+    ->set($rid, $new_permissions)
+    ->save();
+  // @TODO: remove.
+  $modules = user_permission_get_modules();
+  $config = config('user.permission.module');
+  foreach ($modules as $permission => $module) {
+    $config->set("$module.$permission", TRUE);
   }
-
+  $config->save();
   // Clear the user access cache.
   drupal_static_reset('user_access');
-  drupal_static_reset('user_role_permissions');
 }
 
 /**
@@ -1970,14 +1946,14 @@ function user_role_grant_permissions($rid, array $permissions = array()) {
  */
 function user_role_revoke_permissions($rid, array $permissions = array()) {
   // Revoke permissions for the role.
-  db_delete('role_permission')
-    ->condition('rid', $rid)
-    ->condition('permission', $permissions, 'IN')
-    ->execute();
-
+  $config = config('user.permission');
+  $old_permissions = $config->get($rid);
+  $new_permissions = array_diff($old_permissions, $permissions);
+  $config
+    ->set($rid, $new_permissions)
+    ->save();
   // Clear the user access cache.
   drupal_static_reset('user_access');
-  drupal_static_reset('user_role_permissions');
 }
 
 /**
@@ -2273,17 +2249,13 @@ function user_build_filter_query(SelectInterface $query) {
     // the authenticated role. If so, then all users would be listed, and we can
     // skip adding it to the filter query.
     if ($key == 'permission') {
-      $account = entity_create('user', array());
-      $account->uid = 'user_filter';
-      $account->roles = array(DRUPAL_AUTHENTICATED_RID => 1);
-      if (user_access($value, $account)) {
+      $roles = user_roles(FALSE, $value);
+      if (isset($roles[DRUPAL_AUTHENTICATED_RID])) {
         continue;
       }
-      $users_roles_alias = $query->join('users_roles', 'ur', '%alias.uid = u.uid');
-      $permission_alias = $query->join('role_permission', 'p', $users_roles_alias . '.rid = %alias.rid');
-      $query->condition($permission_alias . '.permission', $value);
+      $value = array_keys($roles);
     }
-    elseif ($key == 'role') {
+    if ($key == 'permission' || $key == 'role') {
       $users_roles_alias = $query->join('users_roles', 'ur', '%alias.uid = u.uid');
       $query->condition($users_roles_alias . '.rid' , $value);
     }
@@ -2593,9 +2565,22 @@ function user_modules_installed($modules) {
  * Implements hook_modules_uninstalled().
  */
 function user_modules_uninstalled($modules) {
-   db_delete('role_permission')
-     ->condition('module', $modules, 'IN')
-     ->execute();
+  $config = config('user.permission.module');
+  $permissions_to_remove = array();
+  foreach ($modules as $module) {
+    $permissions_to_remove += $config->get($module);
+    $config->clear($module);
+  }
+  $config->save();
+  if ($permissions_to_remove) {
+    $config = config('user.permission');
+    $all_permissions = $config->get();
+    $permissions_to_remove = array_keys($permissions_to_remove);
+    foreach ($all_permissions as $rid => $permissions) {
+      $config->set($rid, array_diff($permissions, $permissions_to_remove));
+    }
+    $config->save();
+  }
   // Remove any potentially orphan module data stored for users.
   drupal_container()->get('user.data')->delete($modules);
 }
diff --git a/core/modules/user/user.views.inc b/core/modules/user/user.views.inc
index 13b1690..2b6a77e 100644
--- a/core/modules/user/user.views.inc
+++ b/core/modules/user/user.views.inc
@@ -349,30 +349,6 @@ function user_views_data() {
     ),
   );
 
-  // Define the base group of this table. Fields that don't have a group defined
-  // will go into this field by default.
-  $data['role_permission']['table']['group']  = t('User');
-  // Explain how this table joins to others.
-  $data['role_permission']['table']['join'] = array(
-    'users' => array(
-      'left_table' => 'users_roles',
-      'left_field' => 'rid',
-      'field' => 'rid',
-    ),
-  );
-
-  $data['role_permission']['permission'] = array(
-    'title' => t('Permission'),
-    'help' => t('The user permissions.'),
-    'field' => array(
-      'id' => 'user_permissions',
-      'no group by' => TRUE,
-    ),
-    'filter' => array(
-      'id' => 'user_permissions',
-    ),
-  );
-
   return $data;
 }
 
diff --git a/core/modules/views/lib/Drupal/views/Tests/Handler/FieldCounterTest.php b/core/modules/views/lib/Drupal/views/Tests/Handler/FieldCounterTest.php
index 721b3c5..72af9bd 100644
--- a/core/modules/views/lib/Drupal/views/Tests/Handler/FieldCounterTest.php
+++ b/core/modules/views/lib/Drupal/views/Tests/Handler/FieldCounterTest.php
@@ -36,11 +36,6 @@ public static function getInfo() {
     );
   }
 
-  protected function setUp() {
-    parent::setUp();
-    $this->installSchema('user', 'role_permission');
-  }
-
   function testSimple() {
     $view = views_get_view('test_view');
     $view->setDisplay();
diff --git a/core/modules/views/lib/Drupal/views/Tests/Handler/FieldUnitTest.php b/core/modules/views/lib/Drupal/views/Tests/Handler/FieldUnitTest.php
index afff1b3..944eb0e 100644
--- a/core/modules/views/lib/Drupal/views/Tests/Handler/FieldUnitTest.php
+++ b/core/modules/views/lib/Drupal/views/Tests/Handler/FieldUnitTest.php
@@ -38,11 +38,6 @@ public static function getInfo() {
     );
   }
 
-  public function setUp() {
-    parent::setUp();
-    $this->installSchema('user', 'role_permission');
-  }
-
   /**
    * Overrides Drupal\views\Tests\ViewTestBase::viewsData().
    */
diff --git a/core/modules/views/lib/Drupal/views/Tests/Plugin/RelationshipJoinTestBase.php b/core/modules/views/lib/Drupal/views/Tests/Plugin/RelationshipJoinTestBase.php
index 5d2b524..5550cec 100644
--- a/core/modules/views/lib/Drupal/views/Tests/Plugin/RelationshipJoinTestBase.php
+++ b/core/modules/views/lib/Drupal/views/Tests/Plugin/RelationshipJoinTestBase.php
@@ -26,7 +26,7 @@
    * Overrides \Drupal\views\Tests\ViewUnitTestBase::setUpFixtures().
    */
   protected function setUpFixtures() {
-    $this->installSchema('user', array('users', 'users_roles', 'role_permission'));
+    $this->installSchema('user', array('users', 'users_roles'));
     $this->installSchema('field', array('field_config', 'field_config_instance'));
     $this->installConfig(array('user'));
     parent::setUpFixtures();
diff --git a/core/modules/views/lib/Drupal/views/Tests/ViewExecutableTest.php b/core/modules/views/lib/Drupal/views/Tests/ViewExecutableTest.php
index c876972..82d7dcd 100644
--- a/core/modules/views/lib/Drupal/views/Tests/ViewExecutableTest.php
+++ b/core/modules/views/lib/Drupal/views/Tests/ViewExecutableTest.php
@@ -78,7 +78,7 @@ public static function getInfo() {
   }
 
   protected function setUpFixtures() {
-    $this->installSchema('user', array('users', 'role_permission'));
+    $this->installSchema('user', array('users'));
     $this->installSchema('node', array('node_type', 'node'));
     $this->installSchema('comment', array('comment', 'node_comment_statistics'));
     parent::setUpFixtures();
