diff --git includes/common.inc includes/common.inc
index 382d047..ea2b8d5 100644
--- includes/common.inc
+++ includes/common.inc
@@ -2448,8 +2448,9 @@ function drupal_deliver_html_page($page_callback_result) {
 
         if (empty($return) || $return == MENU_NOT_FOUND || $return == MENU_ACCESS_DENIED) {
           // Standard 404 handler.
-          drupal_set_title(t('Page not found'));
-          $return = t('The requested page could not be found.');
+          $path = 'system/404';
+          menu_set_active_item($path);
+          $return = menu_execute_active_handler($path, FALSE);
         }
 
         drupal_set_page_content($return);
@@ -2477,8 +2478,9 @@ function drupal_deliver_html_page($page_callback_result) {
 
         if (empty($return) || $return == MENU_NOT_FOUND || $return == MENU_ACCESS_DENIED) {
           // Standard 403 handler.
-          drupal_set_title(t('Access denied'));
-          $return = t('You are not authorized to access this page.');
+          $path = 'system/403';
+          menu_set_active_item($path);
+          $return = menu_execute_active_handler($path, FALSE);
         }
 
         print drupal_render_page($return);
diff --git modules/system/system.module modules/system/system.module
index 6390ebc..80202bb 100644
--- modules/system/system.module
+++ modules/system/system.module
@@ -491,6 +491,18 @@ function system_element_info() {
  * Implements hook_menu().
  */
 function system_menu() {
+  $items['system/403'] = array(
+    'title' => 'Access denied',
+    'page callback' => 'system_access_denied',
+    'access callback' => TRUE,
+    'type' => MENU_CALLBACK,
+  );
+  $items['system/404'] = array(
+    'title' => 'Page not found',
+    'page callback' => 'system_not_found',
+    'access callback' => TRUE,
+    'type' => MENU_CALLBACK,
+  );
   $items['system/files'] = array(
     'title' => 'File download',
     'page callback' => 'file_download',
@@ -2093,6 +2105,26 @@ function system_admin_menu_block($item) {
 }
 
 /**
+ * Menu callback; returns a 403 error message.
+ *
+ * Page callback functions wanting to report an "access denied" message should
+ * not use this function. Instead see drupal_access_denied().
+ */
+function system_access_denied() {
+  return array('#markup' => t('You are not authorized to access this page.'));
+}
+
+/**
+ * Menu callback; returns a 404 error message.
+ *
+ * Page callback functions wanting to report a "not found" message should not
+ * use this function. Instead see drupal_not_found().
+ */
+function system_not_found() {
+  return array('#markup' => t('The requested page could not be found.'));
+}
+
+/**
  * Checks the existence of the directory specified in $form_element. This
  * function is called from the system_settings form to check both core file
  * directories (file_public_path, file_private_path, file_temporary_path).
diff --git modules/system/system.test modules/system/system.test
index 3cc68d6..3c460b6 100644
--- modules/system/system.test
+++ modules/system/system.test
@@ -674,24 +674,26 @@ class AccessDeniedTestCase extends DrupalWebTestCase {
     $this->drupalGet('admin');
     $this->assertText($node->title, t('Found the custom 403 page'));
 
-    // Logout and check that the user login block is shown on custom 403 pages.
+    // Logout and check that blocks and menu items are shown on custom 403 pages.
     $this->drupalLogout();
 
     $this->drupalGet('admin');
     $this->assertText($node->title, t('Found the custom 403 page'));
     $this->assertText(t('User login'), t('Blocks are shown on the custom 403 page'));
+    $this->assertText(t('Main menu'), t('Menu items are shown on the custom 403 page'));
 
     // Log back in and remove the custom 403 page.
     $this->drupalLogin($this->admin_user);
     $this->drupalPost('admin/config/system/site-information', array('site_403' => ''), t('Save configuration'));
 
-    // Logout and check that the user login block is shown on default 403 pages.
+    // Logout and check that blocks and menu items are shown on default 403 pages.
     $this->drupalLogout();
 
     $this->drupalGet('admin');
     $this->assertText(t('Access denied'), t('Found the default 403 page'));
     $this->assertResponse(403);
     $this->assertText(t('User login'), t('Blocks are shown on the default 403 page'));
+    $this->assertText(t('Main menu'), t('Menu items are shown on the default 403 page'));
 
     // Log back in, set the custom 403 page to /user and remove the block
     $this->drupalLogin($this->admin_user);
@@ -737,20 +739,29 @@ class PageNotFoundTestCase extends DrupalWebTestCase {
   }
 
   function testPageNotFound() {
+    // Logout and check that blocks and menu items are shown on default 404 pages.
+    $this->drupalLogout();
     $this->drupalGet($this->randomName(10));
     $this->assertText(t('Page not found'), t('Found the default 404 page'));
+    $this->assertText(t('User login'), t('Blocks are shown on the default 404 page'));
+    $this->assertText(t('Main menu'), t('Menu items are shown on the default 404 page'));
 
+    // Log back in and add a custom 404 page.
+    $this->drupalLogin($this->admin_user);
     $edit = array(
       'title' => $this->randomName(10),
       'body' => array(LANGUAGE_NONE => array(array('value' => $this->randomName(100)))),
     );
     $node = $this->drupalCreateNode($edit);
-
-    // Use a custom 404 page.
     $this->drupalPost('admin/config/system/site-information', array('site_404' => 'node/' . $node->nid), t('Save configuration'));
 
+    // Logout and check that blocks and menu items are shown on custom 404 pages.
+    $this->drupalLogout();
+
     $this->drupalGet($this->randomName(10));
     $this->assertText($node->title, t('Found the custom 404 page'));
+    $this->assertText(t('User login'), t('Blocks are shown on the custom 404 page'));
+    $this->assertText(t('Main menu'), t('Menu items are shown on the custom 404 page'));
   }
 }
 
