diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module
index 1a3580f..2b7fdae 100644
--- a/core/modules/comment/comment.module
+++ b/core/modules/comment/comment.module
@@ -1685,6 +1685,7 @@ function comment_form($form, &$form_state, $comment) {
   else {
     $comment = $form_state['comment'];
   }
+  $form_state['entity_original'] = $comment;
 
   $node = node_load($comment->nid);
   $form['#node'] = $node;
diff --git a/core/modules/entity/entity.module b/core/modules/entity/entity.module
index 9b2b6f2..0282a63 100644
--- a/core/modules/entity/entity.module
+++ b/core/modules/entity/entity.module
@@ -424,6 +424,9 @@ function entity_form_field_validate($entity_type, $form, &$form_state) {
   // until we have fully validated the submitted input. Therefore, for
   // validation, act on a pseudo entity created out of the form values.
   $pseudo_entity = (object) $form_state['values'];
+  if (!empty($form_state['entity_original'])) {
+    $pseudo_entity->original = $form_state['entity_original'];
+  }
   field_attach_form_validate($entity_type, $pseudo_entity, $form, $form_state);
 }
 
diff --git a/core/modules/field/tests/field.test b/core/modules/field/tests/field.test
index 3566484..3a03de6 100644
--- a/core/modules/field/tests/field.test
+++ b/core/modules/field/tests/field.test
@@ -637,6 +637,11 @@ class FieldAttachOtherTestCase extends FieldAttachTestCase {
     );
   }
 
+  function setUp() {
+    // Comment and taxonomy are required to test hook_field_attach_validate.
+    parent::setup('comment', 'taxonomy');
+  }
+
   /**
    * Test field_attach_view() and field_attach_prepare_view().
    */
@@ -948,7 +953,58 @@ class FieldAttachOtherTestCase extends FieldAttachTestCase {
       $errors = $e->errors;
     }
     $this->assertEqual($errors[$this->field_name][$langcode][0][0]['error'], 'field_cardinality', t('Cardinality validation failed.'));
+  }
+
+  /**
+   * Test hook_field_attach_validate()
+   */
+  function testHookFieldAttachValidate() {
+
+    // A node type must be created to test the hook on node entities.
+    $this->drupalCreateContentType(array('type' => 'page', 'name' => 'Basic page'));
+    // A node must be created to test the hook on comment entities.
+    $node = $this->drupalCreateNode(array('type' => 'page'));
+
+    // A vocabulary must be created to test the hook on taxonomy terms.
+    $vocabulary = entity_create('taxonomy_vocabulary', array(
+      'name' => $this->randomName(),
+      'machine_name' => drupal_strtolower($this->randomName()),
+      'langcode' => LANGUAGE_NOT_SPECIFIED,
+      'nodes' => array('page' => 'Basic page'),
+    ));
+    taxonomy_vocabulary_save($vocabulary);
 
+    // Create an array of entity types to test the hook on. The keys are the
+    // names of the entities and values are an array containing the page where
+    // an entity of this type can be created and the name of the submit button.
+    $entity_types = array(
+      'test_entity' => array('test-entity/add/test-bundle', t('Save')),
+      'node' => array('node/add/page', t('Save')),
+      'comment' => array('comment/reply/' . $node->nid, t('Save')),
+      'taxonomy_term' => array('admin/structure/taxonomy/' . $vocabulary->machine_name . '/add', t('Save')),
+      'user' => array('admin/people/create', t('Create new account')),
+    );
+
+    $web_user = $this->drupalCreateUser(array(
+      'access field_test content',
+      'administer field_test content',
+      'create page content',
+      'post comments',
+      'administer taxonomy',
+      'administer users',
+    ));
+    $this->drupalLogin($web_user);
+
+    foreach($entity_types as $entity_type => $entity_create_page) {
+      list($entity_add_path, $button) = $entity_create_page;
+      // Since the hook being tested runs on validation, the form can be left
+      // blank and the hook will still run.
+      $this->drupalPost($entity_add_path, array(), $button);
+      // The field_test module uses drupal_set_message to indicate that the
+      // hook has run and to indicate that the $entity->orginial value is set.
+      $this->assertText('hook_field_attach_validate runs for ' . $entity_type, 'hook_field_attach_validate runs for ' . $entity_type);
+      $this->assertNoText('Orginial entity missing in hook_field_attach_validate for ' . $entity_type, 'Original entity missing for ' . $entity_type);
+    }
   }
 
   /**
diff --git a/core/modules/field/tests/field_test.entity.inc b/core/modules/field/tests/field_test.entity.inc
index 52ed3fc..cf7c6ed 100644
--- a/core/modules/field/tests/field_test.entity.inc
+++ b/core/modules/field/tests/field_test.entity.inc
@@ -345,6 +345,7 @@ function field_test_entity_form($form, &$form_state, $entity, $add = FALSE) {
   else {
     $entity = $form_state['test_entity'];
   }
+  $form_state['entity_original'] = $entity;
 
   foreach (array('ftid', 'ftvid', 'fttype') as $key) {
     $form[$key] = array(
diff --git a/core/modules/field/tests/field_test.module b/core/modules/field/tests/field_test.module
index 75823c6..af48071 100644
--- a/core/modules/field/tests/field_test.module
+++ b/core/modules/field/tests/field_test.module
@@ -261,3 +261,14 @@ function field_test_field_widget_form_alter(&$element, &$form_state, $context) {
       break;
   }
 }
+
+/**
+ * Implements hook_field_attach_validate().
+ */
+function field_test_field_attach_validate($entity_type, $entity, &$errors) {
+
+  drupal_set_message('hook_field_attach_validate runs for ' . $entity_type);
+  if(!isset($entity->original)) {
+    drupal_set_message('Orginial entity missing in hook_field_attach_validate for ' . $entity_type);
+  }
+}
diff --git a/core/modules/node/node.pages.inc b/core/modules/node/node.pages.inc
index 4e94b26..36d7ae8 100644
--- a/core/modules/node/node.pages.inc
+++ b/core/modules/node/node.pages.inc
@@ -131,6 +131,7 @@ function node_form($form, &$form_state, $node) {
   else {
     $node = $form_state['node'];
   }
+  $form_state['entity_original'] = $node;
 
   // Some special stuff when previewing a node.
   if (isset($form_state['node_preview'])) {
diff --git a/core/modules/taxonomy/taxonomy.admin.inc b/core/modules/taxonomy/taxonomy.admin.inc
index a95b856..be88af4 100644
--- a/core/modules/taxonomy/taxonomy.admin.inc
+++ b/core/modules/taxonomy/taxonomy.admin.inc
@@ -680,6 +680,7 @@ function taxonomy_form_term($form, &$form_state, TaxonomyTerm $term = NULL, Taxo
       $vocabulary = taxonomy_vocabulary_load($term->vid);
     }
   }
+  $form_state['entity_original'] = $term;
 
   $parent = array_keys(taxonomy_term_load_parents($term->tid));
   $form['#term'] = (array) $term;
diff --git a/core/modules/user/user.module b/core/modules/user/user.module
index 865f17b..8973a32 100644
--- a/core/modules/user/user.module
+++ b/core/modules/user/user.module
@@ -3688,7 +3688,7 @@ function user_register_form($form, &$form_state) {
     drupal_goto('user/' . $user->uid);
   }
 
-  $form['#user'] = drupal_anonymous_user();
+  $form['#user'] = $form_state['entity_original'] = drupal_anonymous_user();
 
   $form['#attached']['library'][] = array('system', 'jquery.cookie');
   $form['#attributes']['class'][] = 'user-info-from-cookie';
diff --git a/core/modules/user/user.pages.inc b/core/modules/user/user.pages.inc
index c54bd4c..d9ab607 100644
--- a/core/modules/user/user.pages.inc
+++ b/core/modules/user/user.pages.inc
@@ -219,6 +219,7 @@ function user_profile_form($form, &$form_state, $account) {
   else {
     $account = $form_state['user'];
   }
+  $form_state['entity_original'] = $account;
 
   // @todo Legacy support. Modules are encouraged to access the entity using
   //   $form_state. Remove in Drupal 8.
