diff --git a/modules/comment/comment.test b/modules/comment/comment.test
index 9e69ba6..a63b453 100644
--- a/modules/comment/comment.test
+++ b/modules/comment/comment.test
@@ -13,7 +13,7 @@ class CommentHelperCase extends DrupalWebTestCase {
   function setUp() {
     parent::setUp('comment', 'search');
     // Create users and test node.
-    $this->admin_user = $this->drupalCreateUser(array('administer content types', 'administer comments', 'administer blocks'));
+    $this->admin_user = $this->drupalCreateUser(array('administer content types', 'administer comments', 'administer blocks', 'administer fields'));
     $this->web_user = $this->drupalCreateUser(array('access comments', 'post comments', 'create article content', 'edit own comments'));
     $this->node = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1, 'uid' => $this->web_user->uid));
   }
diff --git a/modules/field/modules/list/tests/list.test b/modules/field/modules/list/tests/list.test
index 84de7e8..b476b5a 100644
--- a/modules/field/modules/list/tests/list.test
+++ b/modules/field/modules/list/tests/list.test
@@ -212,7 +212,7 @@ class ListFieldUITestCase extends FieldTestCase {
     parent::setUp('field_test', 'field_ui');
 
     // Create test user.
-    $admin_user = $this->drupalCreateUser(array('access content', 'administer content types', 'administer taxonomy'));
+    $admin_user = $this->drupalCreateUser(array('access content', 'administer content types', 'administer taxonomy', 'administer fields'));
     $this->drupalLogin($admin_user);
 
     // Create content type, with underscores.
diff --git a/modules/field/modules/number/number.test b/modules/field/modules/number/number.test
index 88029cd..c88b4c1 100644
--- a/modules/field/modules/number/number.test
+++ b/modules/field/modules/number/number.test
@@ -23,7 +23,7 @@ class NumberFieldTestCase extends DrupalWebTestCase {
 
   function setUp() {
     parent::setUp('field_test');
-    $this->web_user = $this->drupalCreateUser(array('access field_test content', 'administer field_test content', 'administer content types'));
+    $this->web_user = $this->drupalCreateUser(array('access field_test content', 'administer field_test content', 'administer content types', 'administer fields'));
     $this->drupalLogin($this->web_user);
   }
 
diff --git a/modules/field/modules/options/options.test b/modules/field/modules/options/options.test
index 7183311..270fcad 100644
--- a/modules/field/modules/options/options.test
+++ b/modules/field/modules/options/options.test
@@ -54,7 +54,7 @@ class OptionsWidgetsTestCase extends FieldTestCase {
     $this->bool = field_create_field($this->bool);
 
     // Create a web user.
-    $this->web_user = $this->drupalCreateUser(array('access field_test content', 'administer field_test content'));
+    $this->web_user = $this->drupalCreateUser(array('access field_test content', 'administer field_test content', 'administer fields'));
     $this->drupalLogin($this->web_user);
   }
 
@@ -459,7 +459,7 @@ class OptionsWidgetsTestCase extends FieldTestCase {
     $this->assertNoFieldChecked("edit-bool-$langcode");
 
     // Create admin user.
-    $admin_user = $this->drupalCreateUser(array('access content', 'administer content types', 'administer taxonomy'));
+    $admin_user = $this->drupalCreateUser(array('access content', 'administer content types', 'administer taxonomy', 'administer fields'));
     $this->drupalLogin($admin_user);
 
     // Create a test field instance.
diff --git a/modules/field/modules/text/text.test b/modules/field/modules/text/text.test
index 2f14738..ad803cf 100644
--- a/modules/field/modules/text/text.test
+++ b/modules/field/modules/text/text.test
@@ -424,6 +424,7 @@ class TextTranslationTestCase extends DrupalWebTestCase {
       'administer content types',
       'access administration pages',
       'bypass node access',
+      'administer fields',
       filter_permission_name($full_html_format),
     ));
     $this->translator = $this->drupalCreateUser(array('create article content', 'edit own article content', 'translate content'));
diff --git a/modules/field_ui/field_ui.install b/modules/field_ui/field_ui.install
new file mode 100644
index 0000000..7390d6e
--- /dev/null
+++ b/modules/field_ui/field_ui.install
@@ -0,0 +1,19 @@
+<?php
+
+/**
+ * @file
+ * Install, update, and uninstall functions for the Field UI module.
+ */
+
+/**
+ * Grant the new "administer fields" permission to trusted users.
+ */
+function field_ui_update_7000() {
+  // Assign the permission to anyone that already has the "administer site
+  // configuration" permission.
+  $roles = user_roles(FALSE, 'administer site configuration');
+
+  foreach ($roles as $rid => $role_name) {
+    user_role_grant_permissions($rid, array('administer fields'));
+  }
+}
diff --git a/modules/field_ui/field_ui.module b/modules/field_ui/field_ui.module
index ed833fe..262ba6a 100644
--- a/modules/field_ui/field_ui.module
+++ b/modules/field_ui/field_ui.module
@@ -104,10 +104,26 @@ function field_ui_menu() {
 
           // Extract access information, providing defaults.
           $access = array_intersect_key($bundle_info['admin'], drupal_map_assoc(array('access callback', 'access arguments')));
-          $access += array(
-            'access callback' => 'user_access',
-            'access arguments' => array('administer site configuration'),
-          );
+
+          // Add the "administer fields" permission on top of the access
+          // restriction because the field UI should only be accessible to
+          // trusted users.
+          if (empty($access)) {
+            $field_ui_access = array(
+              'access callback' => 'user_access',
+              'access arguments' => array('administer fields'),
+            );
+          }
+          else {
+            $access += array(
+              'access callback' => 'user_access',
+              'access arguments' => array('administer fields'),
+            );
+            $field_ui_access = array(
+              'access callback' => 'field_ui_admin_access',
+              'access arguments' => array($access['access callback'], $access['access arguments']),
+            );
+          }
 
           $items["$path/fields"] = array(
             'title' => 'Manage fields',
@@ -116,7 +132,7 @@ function field_ui_menu() {
             'type' => MENU_LOCAL_TASK,
             'weight' => 1,
             'file' => 'field_ui.admin.inc',
-          ) + $access;
+          ) + $field_ui_access;
           $items["$path/fields/%field_ui_menu"] = array(
             'load arguments' => array($entity_type, $bundle_arg, $bundle_pos, '%map'),
             'title callback' => 'field_ui_menu_title',
@@ -124,7 +140,7 @@ function field_ui_menu() {
             'page callback' => 'drupal_get_form',
             'page arguments' => array('field_ui_field_edit_form', $field_position),
             'file' => 'field_ui.admin.inc',
-          ) + $access;
+          ) + $field_ui_access;
           $items["$path/fields/%field_ui_menu/edit"] = array(
             'load arguments' => array($entity_type, $bundle_arg, $bundle_pos, '%map'),
             'title' => 'Edit',
@@ -132,7 +148,7 @@ function field_ui_menu() {
             'page arguments' => array('field_ui_field_edit_form', $field_position),
             'type' => MENU_DEFAULT_LOCAL_TASK,
             'file' => 'field_ui.admin.inc',
-          ) + $access;
+          ) + $field_ui_access;
           $items["$path/fields/%field_ui_menu/field-settings"] = array(
             'load arguments' => array($entity_type, $bundle_arg, $bundle_pos, '%map'),
             'title' => 'Field settings',
@@ -140,7 +156,7 @@ function field_ui_menu() {
             'page arguments' => array('field_ui_field_settings_form', $field_position),
             'type' => MENU_LOCAL_TASK,
             'file' => 'field_ui.admin.inc',
-          ) + $access;
+          ) + $field_ui_access;
           $items["$path/fields/%field_ui_menu/widget-type"] = array(
             'load arguments' => array($entity_type, $bundle_arg, $bundle_pos, '%map'),
             'title' => 'Widget type',
@@ -148,7 +164,7 @@ function field_ui_menu() {
             'page arguments' => array('field_ui_widget_type_form', $field_position),
             'type' => MENU_LOCAL_TASK,
             'file' => 'field_ui.admin.inc',
-          ) + $access;
+          ) + $field_ui_access;
           $items["$path/fields/%field_ui_menu/delete"] = array(
             'load arguments' => array($entity_type, $bundle_arg, $bundle_pos, '%map'),
             'title' => 'Delete',
@@ -157,7 +173,7 @@ function field_ui_menu() {
             'type' => MENU_LOCAL_TASK,
             'weight' => 10,
             'file' => 'field_ui.admin.inc',
-          ) + $access;
+          ) + $field_ui_access;
 
           // 'Manage display' tab.
           $items["$path/display"] = array(
@@ -167,7 +183,7 @@ function field_ui_menu() {
             'type' => MENU_LOCAL_TASK,
             'weight' => 2,
             'file' => 'field_ui.admin.inc',
-          ) + $access;
+          ) + $field_ui_access;
 
           // View modes secondary tabs.
           // The same base $path for the menu item (with a placeholder) can be
@@ -186,7 +202,7 @@ function field_ui_menu() {
               // display' setting for the view mode, and the overall access
               // rules for the bundle admin pages.
               'access callback' => '_field_ui_view_mode_menu_access',
-              'access arguments' => array_merge(array($entity_type, $bundle_arg, $view_mode, $access['access callback']), $access['access arguments']),
+              'access arguments' => array_merge(array($entity_type, $bundle_arg, $view_mode, $field_ui_access['access callback']), $field_ui_access['access arguments']),
               'type' => ($view_mode == 'default' ? MENU_DEFAULT_LOCAL_TASK : MENU_LOCAL_TASK),
               'weight' => ($view_mode == 'default' ? -10 : $weight++),
               'file' => 'field_ui.admin.inc',
@@ -392,3 +408,26 @@ function field_ui_form_node_type_form_submit($form, &$form_state) {
     $form_state['redirect'] = _field_ui_bundle_admin_path('node', $form_state['values']['type']) .'/fields';
   }
 }
+
+/**
+ * Implements hook_permission().
+ */
+function field_ui_permission() {
+  return array(
+    'administer fields' => array(
+      'title' => t('Administer fields'),
+      'description' => t('Create, change and delete fields on entities.'),
+      'restrict access' => TRUE,
+    ),
+  );
+}
+
+/**
+ * Access callback to determine if a user is allowed to use the field UI.
+ *
+ * Only grant access if the user has both the "administer fields" permission and
+ * is granted access by the entity specific restrictions.
+ */
+function field_ui_admin_access($access_callback, $access_arguments) {
+  return user_access('administer fields') && call_user_func_array($access_callback, $access_arguments);
+}
diff --git a/modules/field_ui/field_ui.test b/modules/field_ui/field_ui.test
index 21767d6..73697c6 100644
--- a/modules/field_ui/field_ui.test
+++ b/modules/field_ui/field_ui.test
@@ -22,7 +22,7 @@ class FieldUITestCase extends DrupalWebTestCase {
     parent::setUp($modules);
 
     // Create test user.
-    $admin_user = $this->drupalCreateUser(array('access content', 'administer content types', 'administer taxonomy'));
+    $admin_user = $this->drupalCreateUser(array('access content', 'administer content types', 'administer taxonomy', 'administer fields'));
     $this->drupalLogin($admin_user);
 
     // Create content type, with underscores.
@@ -682,7 +682,7 @@ class FieldUIAlterTestCase extends DrupalWebTestCase {
     parent::setUp(array('field_test'));
 
     // Create test user.
-    $admin_user = $this->drupalCreateUser(array('access content', 'administer content types', 'administer users'));
+    $admin_user = $this->drupalCreateUser(array('access content', 'administer content types', 'administer users', 'administer fields'));
     $this->drupalLogin($admin_user);
   }
 
diff --git a/modules/file/tests/file.test b/modules/file/tests/file.test
index 0f6a578..53d9a03 100644
--- a/modules/file/tests/file.test
+++ b/modules/file/tests/file.test
@@ -22,7 +22,7 @@ class FileFieldTestCase extends DrupalWebTestCase {
     $modules[] = 'file';
     $modules[] = 'file_module_test';
     parent::setUp($modules);
-    $this->admin_user = $this->drupalCreateUser(array('access content', 'access administration pages', 'administer site configuration', 'administer users', 'administer permissions', 'administer content types', 'administer nodes', 'bypass node access'));
+    $this->admin_user = $this->drupalCreateUser(array('access content', 'access administration pages', 'administer site configuration', 'administer users', 'administer permissions', 'administer content types', 'administer nodes', 'bypass node access', 'administer fields'));
     $this->drupalLogin($this->admin_user);
   }
 
diff --git a/modules/image/image.test b/modules/image/image.test
index 2387314..2fe07c2 100644
--- a/modules/image/image.test
+++ b/modules/image/image.test
@@ -32,7 +32,7 @@ class ImageFieldTestCase extends DrupalWebTestCase {
 
   function setUp() {
     parent::setUp('image');
-    $this->admin_user = $this->drupalCreateUser(array('access content', 'access administration pages', 'administer site configuration', 'administer content types', 'administer nodes', 'create article content', 'edit any article content', 'delete any article content', 'administer image styles'));
+    $this->admin_user = $this->drupalCreateUser(array('access content', 'access administration pages', 'administer site configuration', 'administer content types', 'administer nodes', 'create article content', 'edit any article content', 'delete any article content', 'administer image styles', 'administer fields'));
     $this->drupalLogin($this->admin_user);
   }
 
diff --git a/modules/node/content_types.inc b/modules/node/content_types.inc
index 55af667..c451dc7 100644
--- a/modules/node/content_types.inc
+++ b/modules/node/content_types.inc
@@ -11,7 +11,7 @@
 function node_overview_types() {
   $types = node_type_get_types();
   $names = node_type_get_names();
-  $field_ui = module_exists('field_ui');
+  $field_ui = module_exists('field_ui') && user_access('administer fields');
   $header = array(t('Name'), array('data' => t('Operations'), 'colspan' => $field_ui ? '4' : '2'));
   $rows = array();
 
diff --git a/modules/node/node.test b/modules/node/node.test
index 5c9118e..496f7a8 100644
--- a/modules/node/node.test
+++ b/modules/node/node.test
@@ -1448,7 +1448,7 @@ class NodeTypeTestCase extends DrupalWebTestCase {
    * Tests editing a node type using the UI.
    */
   function testNodeTypeEditing() {
-    $web_user = $this->drupalCreateUser(array('bypass node access', 'administer content types'));
+    $web_user = $this->drupalCreateUser(array('bypass node access', 'administer content types', 'administer fields'));
     $this->drupalLogin($web_user);
 
     $instance = field_info_instance('node', 'body', 'page');
@@ -2698,8 +2698,8 @@ class NodeAccessFieldTestCase extends NodeWebTestCase {
     node_access_rebuild();
 
     // Create some users.
-    $this->admin_user = $this->drupalCreateUser(array('access content', 'bypass node access'));
-    $this->content_admin_user = $this->drupalCreateUser(array('access content', 'administer content types'));
+    $this->admin_user = $this->drupalCreateUser(array('access content', 'bypass node access', 'administer fields'));
+    $this->content_admin_user = $this->drupalCreateUser(array('access content', 'administer content types', 'administer fields'));
 
     // Add a custom field to the page content type.
     $this->field_name = drupal_strtolower($this->randomName() . '_field_name');
diff --git a/modules/taxonomy/taxonomy.test b/modules/taxonomy/taxonomy.test
index fdf354b..e9dac1e 100644
--- a/modules/taxonomy/taxonomy.test
+++ b/modules/taxonomy/taxonomy.test
@@ -1025,7 +1025,7 @@ class TaxonomyRSSTestCase extends TaxonomyWebTestCase {
 
   function setUp() {
     parent::setUp('taxonomy');
-    $this->admin_user = $this->drupalCreateUser(array('administer taxonomy', 'bypass node access', 'administer content types'));
+    $this->admin_user = $this->drupalCreateUser(array('administer taxonomy', 'bypass node access', 'administer content types', 'administer fields'));
     $this->drupalLogin($this->admin_user);
     $this->vocabulary = $this->createVocabulary();
 
