diff --git a/CHANGELOG.txt b/CHANGELOG.txt
index a048654..e2f4d35 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -1,6 +1,7 @@
 
 Drupal 8.0, xxxx-xx-xx (development version)
 ----------------------
+- Role is a fieldable entity.
 - Removed modules from core
     * The following modules have been removed from core, because contributed
       modules with similar functionality are available:
diff --git a/modules/user/user.admin.inc b/modules/user/user.admin.inc
index 4789e7e..881550d 100644
--- a/modules/user/user.admin.inc
+++ b/modules/user/user.admin.inc
@@ -937,6 +937,9 @@ function user_admin_role($form, $form_state, $role) {
     drupal_goto('admin/people/permissions/roles');
   }
 
+  // Save the role for later use.
+  $form_state['role'] = $role;
+
   // Display the edit role form.
   $form['name'] = array(
     '#type' => 'textfield',
@@ -966,6 +969,9 @@ function user_admin_role($form, $form_state, $role) {
     '#submit' => array('user_admin_role_delete_submit'),
   );
 
+  // Attach field widgets.
+  field_attach_form('user_role', $role, $form, $form_state);
+
   return $form;
 }
 
@@ -989,19 +995,34 @@ function user_admin_role_validate($form, &$form_state) {
   else {
     form_set_error('name', t('You must specify a valid role name.'));
   }
+
+  // Field validation.
+  if (isset($form_state['role'])) {
+    field_attach_form_validate('user_role', $form_state['role'], $form, $form_state);
+  }
 }
 
 /**
  * Form submit handler for the user_admin_role() form.
  */
 function user_admin_role_submit($form, &$form_state) {
-  $role = (object) $form_state['values'];
+  $role = isset($form_state['role']) ? $form_state['role'] : new stdClass;
+
+  if (isset($form_state['values']['rid'])) {
+    $role->rid = $form_state['values']['rid'];
+  }
+  $role->name = $form_state['values']['name'];
+
+  // Notify field widgets.
+  field_attach_submit('user_role', $role, $form, $form_state);
+
+  // Save the role.
+  user_role_save($role);
+
   if ($form_state['values']['op'] == t('Save role')) {
-    user_role_save($role);
     drupal_set_message(t('The role has been renamed.'));
   }
   elseif ($form_state['values']['op'] == t('Add role')) {
-    user_role_save($role);
     drupal_set_message(t('The role has been added.'));
   }
   $form_state['redirect'] = 'admin/people/permissions/roles';
@@ -1034,4 +1055,3 @@ function user_admin_role_delete_confirm_submit($form, &$form_state) {
   drupal_set_message(t('The role has been deleted.'));
   $form_state['redirect'] = 'admin/people/permissions/roles';
 }
-
diff --git a/modules/user/user.info b/modules/user/user.info
index d887352..9d04bd2 100644
--- a/modules/user/user.info
+++ b/modules/user/user.info
@@ -4,6 +4,7 @@ package = Core
 version = VERSION
 core = 8.x
 files[] = user.entity.inc
+files[] = user_role.entity.inc
 files[] = user.test
 required = TRUE
 configure = admin/config/people
diff --git a/modules/user/user.module b/modules/user/user.module
index 14e1459..827da3d 100644
--- a/modules/user/user.module
+++ b/modules/user/user.module
@@ -178,6 +178,31 @@ function user_entity_info() {
         ),
       ),
     ),
+    'user_role' => array(
+      'label' => t('Role'),
+      'controller class' => 'UserRoleController',
+      'base table' => 'role',
+      'fieldable' => TRUE,
+      'entity keys' => array(
+        'id' => 'rid',
+        'label' => 'name',
+      ),
+      'bundles' => array(
+        'user_role' => array(
+          'label' => t('Role'),
+          'admin' => array(
+            'path' => 'admin/config/people/accounts/role',
+            'access arguments' => array('administer users'),
+          ),
+        ),
+      ),
+      'view modes' => array(
+        'full' => array(
+          'label' => t('Role'),
+          'custom settings' => FALSE,
+        ),
+      ),
+    ),
   );
   return $return;
 }
@@ -229,6 +254,22 @@ function user_field_extra_fields() {
       ),
     ),
   );
+  $return['user_role']['user_role'] = array(
+    'form' => array(
+      'name' => array(
+        'label' => t('Role name'),
+        'description' => t('Role name.'),
+        'weight' => -10,
+      ),
+    ),
+    'display' => array(
+      'name' => array(
+        'label' => t('Role name'),
+        'description' => t('Role name.'),
+        'weight' => -10,
+      ),
+    ),
+  );
 
   return $return;
 }
@@ -1747,6 +1788,18 @@ function user_menu() {
 }
 
 /**
+ * Implements hook_menu_alter().
+ */
+function user_menu_alter(&$items) {
+
+  // Rename and re-arrange role tabs.
+  $items['admin/config/people/accounts/role/fields']['weight'] = 3;
+  $items['admin/config/people/accounts/role/fields']['title'] = 'Role fields';
+  $items['admin/config/people/accounts/role/display']['weight'] = 4;
+  $items['admin/config/people/accounts/role/display']['title'] = 'Role display';
+}
+
+/**
  * Implements hook_menu_site_status_alter().
  */
 function user_menu_site_status_alter(&$menu_site_status, $path) {
@@ -2787,23 +2840,47 @@ function user_roles($membersonly = FALSE, $permission = NULL) {
 }
 
 /**
- * Fetches a user role by role ID.
+ * Load multiple user roles.
+ *
+ * This function should be used whenever you need to load more than one user
+ * role from the database. User roles are loaded into memory and will not
+ * require database access if loaded again during the same page request.
+ *
+ * @param $rids
+ *   An array of role IDs.
+ * @param $reset
+ *   A boolean indicating that the internal cache should be reset. Use this if
+ *   loading a user object which has been altered during the page request.
+ *
+ * @return
+ *   An array of user role objects, indexed by uid.
+ *
+ * @see entity_load()
+ * @see user_role_load()
+ * @see EntityFieldQuery
+ */
+function user_role_load_multiple($rids = array(), $reset = FALSE) {
+  return entity_load('user_role', $rids, array(), $reset);
+}
+
+/**
+ * Loads a user role object.
  *
  * @param $rid
- *   An integer representing the role ID.
+ *   Integer specifying the user role ID to load.
+ * @param $reset
+ *   TRUE to reset the internal cache and load from the database; FALSE
+ *   (default) to load from the internal cache, if set.
  *
  * @return
- *   A fully-loaded role object if a role with the given ID exists, or FALSE
- *   otherwise.
+ *   A fully-loaded user role object upon successful user role load, or FALSE
+ *   if the user role cannot be loaded.
  *
- * @see user_role_load_by_name()
+ * @see user_role_load_multiple()
  */
-function user_role_load($rid) {
-  return db_select('role', 'r')
-    ->fields('r')
-    ->condition('rid', $rid)
-    ->execute()
-    ->fetchObject();
+function user_role_load($rid, $reset = FALSE) {
+  $roles = user_role_load_multiple(array($rid), $reset);
+  return reset($roles);
 }
 
 /**
@@ -2819,11 +2896,16 @@ function user_role_load($rid) {
  * @see user_role_load()
  */
 function user_role_load_by_name($role_name) {
-  return db_select('role', 'r')
-    ->fields('r')
-    ->condition('name', $role_name)
+  $rid = db_select('role', 'r')
+    ->fields('r', array('rid'))
+    ->condition('r.name', $role_name)
     ->execute()
-    ->fetchObject();
+    ->fetchField();
+
+  if ($rid) {
+    return user_role_load($rid);
+  }
+  return FALSE;
 }
 
 /**
@@ -2839,69 +2921,43 @@ function user_role_load_by_name($role_name) {
  *   performed.
  */
 function user_role_save($role) {
-  if ($role->name) {
-    // Prevent leading and trailing spaces in role names.
-    $role->name = trim($role->name);
-  }
-  if (!isset($role->weight)) {
-    // Set a role weight to make this new role last.
-    $query = db_select('role');
-    $query->addExpression('MAX(weight)');
-    $role->weight = $query->execute()->fetchField() + 1;
-  }
-
-  // Let modules modify the user role before it is saved to the database.
-  module_invoke_all('user_role_presave', $role);
-
-  if (!empty($role->rid) && $role->name) {
-    $status = drupal_write_record('role', $role, 'rid');
-    module_invoke_all('user_role_update', $role);
-  }
-  else {
-    $status = drupal_write_record('role', $role);
-    module_invoke_all('user_role_insert', $role);
-  }
-
-  // Clear the user access cache.
-  drupal_static_reset('user_access');
-  drupal_static_reset('user_role_permissions');
+  return entity_get_controller('user_role')->save($role);
+}
 
-  return $status;
+/**
+ * Delete multiple user roles.
+ *
+ * @param $rids
+ *   An array of role IDs.
+ *
+ * @return
+ *   Boolean indicating the delete was successfull.
+ */
+function user_role_delete_multiple($rids = array()) {
+  return entity_get_controller('user_role')->delete($rids);
 }
 
 /**
- * Delete a user role from database.
+ * Delete a user role.
  *
  * @param $role
  *   A string with the role name, or an integer with the role ID.
  */
 function user_role_delete($role) {
   if (is_int($role)) {
-    $role = user_role_load($role);
+    $rid = $role;
   }
   else {
     $role = user_role_load_by_name($role);
+    $rid = $role->rid;
   }
 
-  db_delete('role')
-    ->condition('rid', $role->rid)
-    ->execute();
-  db_delete('role_permission')
-    ->condition('rid', $role->rid)
-    ->execute();
-  // Update the users who have this role set:
-  db_delete('users_roles')
-    ->condition('rid', $role->rid)
-    ->execute();
-
-  module_invoke_all('user_role_delete', $role);
-
-  // Clear the user access cache.
-  drupal_static_reset('user_access');
-  drupal_static_reset('user_role_permissions');
+  return user_role_delete_multiple(array($rid));
 }
 
 /**
+ *
+/**
  * Menu access callback for user role editing.
  */
 function user_role_edit_access($role) {
diff --git a/modules/user/user_role.entity.inc b/modules/user/user_role.entity.inc
new file mode 100644
index 0000000..870e0e3
--- /dev/null
+++ b/modules/user/user_role.entity.inc
@@ -0,0 +1,105 @@
+<?php
+
+/**
+ * @file Controller class for user roles.
+ */
+
+/**
+ * Controller class for user roles.
+ *
+ * This extends the DrupalDefaultEntityController class, adding required
+ * special handling for user role objects.
+ */
+class UserRoleController extends DrupalDefaultEntityController {
+
+  function save($role) {
+    $transaction = db_transaction();
+
+    try {
+      if ($role->name) {
+        // Prevent leading and trailing spaces in role names.
+        $role->name = trim($role->name);
+      }
+      if (!isset($role->weight)) {
+        // Set a role weight to make this new role last.
+        $query = db_select('role');
+        $query->addExpression('MAX(weight)');
+        $role->weight = $query->execute()->fetchField() + 1;
+      }
+
+      // Let modules modify the user role before it is saved to the database.
+      module_invoke_all('user_role_presave', $role);
+
+      // Invoke presave operations of Field Attach API and Entity API.
+      field_attach_presave('user_role', $role);
+      module_invoke_all('entity_presave', $role, 'user_role');
+
+      if (!empty($role->rid) && $role->name) {
+        $status = drupal_write_record('role', $role, 'rid');
+        field_attach_update('user_role', $role);
+        module_invoke_all('user_role_update', $role);
+        module_invoke_all('entity_update', $role, 'user_role');
+        $this->resetCache(array($role->rid));
+      }
+      else {
+        $status = drupal_write_record('role', $role);
+        field_attach_insert('user_role', $role);
+        module_invoke_all('user_role_insert', $role);
+        module_invoke_all('entity_insert', $role, 'user_role');
+      }
+
+      // Clear the user access cache.
+      drupal_static_reset('user_access');
+      drupal_static_reset('user_role_permissions');
+
+      // Ignore slave server temporarily to give time for the saved
+      // order to be propagated to the slave.
+      db_ignore_slave();
+
+      return $status;
+    }
+    catch (Exception $e) {
+      $transaction->rollback();
+      watchdog_exception('user', $e, NULL, WATCHDOG_ERROR);
+      return FALSE;
+    }
+  }
+
+  function delete($rids) {
+    if (!empty($rids)) {
+      $roles = $this->load($rids, array());
+      $transaction = db_transaction();
+
+      try {
+        db_delete('role')
+          ->condition('rid', $rids, 'IN')
+          ->execute();
+        db_delete('role_permission')
+          ->condition('rid', $rids, 'IN')
+          ->execute();
+        db_delete('users_roles')
+          ->condition('rid', $rids)
+          ->execute();
+
+        foreach ($roles as $role_id => $role) {
+          module_invoke_all('user_role_delete', $role);
+          module_invoke_all('entity_delete', $role, 'user_role');
+          field_attach_delete('user_role', $role);
+        }
+        $this->resetCache();
+
+        // Clear the user access cache.
+        drupal_static_reset('user_access');
+        drupal_static_reset('user_role_permissions');
+
+        db_ignore_slave();
+        return TRUE;
+      }
+      catch (Exception $e) {
+        $transaction->rollback();
+        watchdog_exception('user', $e, NULL, WATCHDOG_ERROR);
+        return FALSE;
+      }
+    }
+  }
+}
