diff --git a/core/authorize.php b/core/authorize.php
index d033b7e..dbab02f 100644
--- a/core/authorize.php
+++ b/core/authorize.php
@@ -51,7 +51,6 @@
  *   TRUE if the current user can run authorize.php, and FALSE if not.
  */
 function authorize_access_allowed() {
-  \Drupal::service('session_manager')->start();
   return Settings::get('allow_authorize_operations', TRUE) && \Drupal::currentUser()->hasPermission('administer software updates');
 }
 
diff --git a/core/core.services.yml b/core/core.services.yml
index 9f5d6fc..9fe8324 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -475,6 +475,11 @@ services:
     arguments: ['@kernel']
     tags:
       - { name: http_middleware, priority: 100 }
+  http_middleware.session:
+    class: Drupal\Core\StackMiddleware\Session
+    arguments: ['@session']
+    tags:
+      - { name: http_middleware, priority: 50 }
   language_manager:
     class: Drupal\Core\Language\LanguageManager
     arguments: ['@language.default']
@@ -993,7 +998,7 @@ services:
     arguments: ['@module_handler', '@cache.discovery', '@language_manager', '@cache_tags.invalidator']
   batch.storage:
     class: Drupal\Core\Batch\BatchStorage
-    arguments: ['@database', '@session_manager', '@csrf_token']
+    arguments: ['@database', '@session', '@csrf_token']
     tags:
       - { name: backend_overridable }
   replica_database_ignore__subscriber:
@@ -1089,6 +1094,15 @@ services:
   session_configuration:
     class: Drupal\Core\Session\SessionConfiguration
     arguments: ['%session.storage.options%']
+  session:
+    class: Symfony\Component\HttpFoundation\Session\Session
+    arguments: ['@session_manager', '@session.attribute_bag', '@session.flash_bag']
+  session.flash_bag:
+    class: Symfony\Component\HttpFoundation\Session\Flash\FlashBag
+    public: false
+  session.attribute_bag:
+    class: Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag
+    public: false
   session_manager:
     class: Drupal\Core\Session\SessionManager
     arguments: ['@request_stack', '@database', '@session_manager.metadata_bag', '@session_configuration']
diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc
index f98c64d..34187f2 100644
--- a/core/includes/install.core.inc
+++ b/core/includes/install.core.inc
@@ -21,9 +21,11 @@
 use Drupal\Core\DependencyInjection\ContainerBuilder;
 use Drupal\Core\Url;
 use Drupal\language\Entity\ConfigurableLanguage;
+use Symfony\Cmf\Component\Routing\RouteObjectInterface;
 use Symfony\Component\DependencyInjection\Reference;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\Routing\Route;
 
 use GuzzleHttp\Exception\RequestException;
 
@@ -396,7 +398,6 @@ function install_begin_request($class_loader, &$install_state) {
   $kernel->setSitePath($site_path);
   $kernel->boot();
   $container = $kernel->getContainer();
-  $container->get('request_stack')->push($request);
 
   // Register the file translation service.
   if (isset($GLOBALS['config']['locale.settings']['translation']['path'])) {
@@ -442,13 +443,15 @@ function install_begin_request($class_loader, &$install_state) {
   if ($profile && !$module_handler->moduleExists($profile)) {
     $module_handler->addProfile($profile, $install_state['profiles'][$profile]->getPath());
   }
-  // After setting up a custom and finite module list in a custom low-level
-  // bootstrap like here, ensure to use ModuleHandler::loadAll() so that
-  // ModuleHandler::isLoaded() returns TRUE, since that is a condition being
-  // checked by other subsystems (e.g., the theme system).
-  $module_handler->loadAll();
 
-  $kernel->prepareLegacyRequest($request);
+  // Load all modules and perform request related initialization.
+  $kernel->preHandle($request);
+
+  // Initialize a route on this legacy request similar to
+  // \Drupal\Core\DrupalKernel::prepareLegacyRequest() since normal routing
+  // will not happen.
+  $request->attributes->set(RouteObjectInterface::ROUTE_OBJECT, new Route('<none>'));
+  $request->attributes->set(RouteObjectInterface::ROUTE_NAME, '<none>');
 
   // Prepare for themed output. We need to run this at the beginning of the
   // page request to avoid a different theme accidentally getting set. (We also
@@ -593,7 +596,7 @@ function install_run_task($task, &$install_state) {
       $response = batch_process($url, clone $url);
       if ($response instanceof Response) {
         // Save $_SESSION data from batch.
-        \Drupal::service('session_manager')->save();
+        \Drupal::service('session')->save();
         // Send the response.
         $response->send();
         exit;
@@ -1548,7 +1551,7 @@ function install_load_profile(&$install_state) {
  *   An array of information about the current installation state.
  */
 function install_bootstrap_full() {
-  \Drupal::service('session_manager')->start();
+  \Drupal::service('session')->start();
 }
 
 /**
diff --git a/core/lib/Drupal/Core/Authentication/Provider/Cookie.php b/core/lib/Drupal/Core/Authentication/Provider/Cookie.php
index 5f88c47..e36275f 100644
--- a/core/lib/Drupal/Core/Authentication/Provider/Cookie.php
+++ b/core/lib/Drupal/Core/Authentication/Provider/Cookie.php
@@ -18,27 +18,10 @@
 class Cookie implements AuthenticationProviderInterface {
 
   /**
-   * The session manager.
-   *
-   * @var \Drupal\Core\Session\SessionManagerInterface
-   */
-  protected $sessionManager;
-
-  /**
-   * Constructs a new Cookie authentication provider instance.
-   *
-   * @param \Drupal\Core\Session\SessionManagerInterface $session_manager
-   *   The session manager.
-   */
-  public function __construct(SessionManagerInterface $session_manager) {
-    $this->sessionManager = $session_manager;
-  }
-
-  /**
    * {@inheritdoc}
    */
   public function applies(Request $request) {
-    return TRUE;
+    return $request->hasSession();
   }
 
   /**
@@ -47,10 +30,11 @@ public function applies(Request $request) {
   public function authenticate(Request $request) {
     // Global $user is deprecated, but the session system is still based on it.
     global $user;
-    $this->sessionManager->start();
-    if ($this->sessionManager->isStarted()) {
+
+    if ($request->getSession()->start()) {
       return $user;
     }
+
     return NULL;
   }
 
@@ -58,7 +42,6 @@ public function authenticate(Request $request) {
    * {@inheritdoc}
    */
   public function cleanup(Request $request) {
-    $this->sessionManager->save();
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Batch/BatchStorage.php b/core/lib/Drupal/Core/Batch/BatchStorage.php
index da0fe94..5742fd2 100644
--- a/core/lib/Drupal/Core/Batch/BatchStorage.php
+++ b/core/lib/Drupal/Core/Batch/BatchStorage.php
@@ -8,7 +8,7 @@
 namespace Drupal\Core\Batch;
 
 use Drupal\Core\Database\Connection;
-use Drupal\Core\Session\SessionManager;
+use Symfony\Component\HttpFoundation\Session\SessionInterface;
 use Drupal\Core\Access\CsrfTokenGenerator;
 
 class BatchStorage implements BatchStorageInterface {
@@ -21,11 +21,11 @@ class BatchStorage implements BatchStorageInterface {
   protected $connection;
 
   /**
-   * The session manager.
+   * The session.
    *
-   * @var \Drupal\Core\Session\SessionManager
+   * @var \Symfony\Component\HttpFoundation\Session\SessionInterface
    */
-  protected $sessionManager;
+  protected $session;
 
   /**
    * The CSRF token generator.
@@ -39,14 +39,14 @@ class BatchStorage implements BatchStorageInterface {
    *
    * @param \Drupal\Core\Database\Connection $connection
    *   The database connection.
-   * @param \Drupal\Core\Session\SessionManager $session_manager
-   *   The session manager.
+   * @param \Symfony\Component\HttpFoundation\Session\SessionInterface $session
+   *   The session.
    * @param \Drupal\Core\Access\CsrfTokenGenerator $csrf_token
    *   The CSRF token generator.
    */
-  public function __construct(Connection $connection, SessionManager $session_manager, CsrfTokenGenerator $csrf_token) {
+  public function __construct(Connection $connection, SessionInterface $session, CsrfTokenGenerator $csrf_token) {
     $this->connection = $connection;
-    $this->sessionManager = $session_manager;
+    $this->session = $session;
     $this->csrfToken = $csrf_token;
   }
 
@@ -55,7 +55,7 @@ public function __construct(Connection $connection, SessionManager $session_mana
    */
   public function load($id) {
     // Ensure that a session is started before using the CSRF token generator.
-    $this->sessionManager->start();
+    $this->session->start();
     $batch = $this->connection->query("SELECT batch FROM {batch} WHERE bid = :bid AND token = :token", array(
       ':bid' => $id,
       ':token' => $this->csrfToken->get($id),
@@ -100,7 +100,7 @@ public function cleanup() {
    */
   public function create(array $batch) {
     // Ensure that a session is started before using the CSRF token generator.
-    $this->sessionManager->start();
+    $this->session->start();
     $this->connection->insert('batch')
       ->fields(array(
         'bid' => $batch['id'],
diff --git a/core/lib/Drupal/Core/DrupalKernel.php b/core/lib/Drupal/Core/DrupalKernel.php
index bc36c15..bfa2c98 100644
--- a/core/lib/Drupal/Core/DrupalKernel.php
+++ b/core/lib/Drupal/Core/DrupalKernel.php
@@ -571,8 +571,9 @@ public function handle(Request $request, $type = self::MASTER_REQUEST, $catch =
   public function prepareLegacyRequest(Request $request) {
     $this->boot();
     $this->preHandle($request);
-    // Enter the request scope so that current_user service is available for
-    // locale/translation sake.
+    // Setup services which are normally initialized from within stack
+    // middleware or during the request kernel event.
+    $request->setSession($this->container->get('session'));
     $request->attributes->set(RouteObjectInterface::ROUTE_OBJECT, new Route('<none>'));
     $request->attributes->set(RouteObjectInterface::ROUTE_NAME, '<none>');
     $this->container->get('request_stack')->push($request);
@@ -718,6 +719,16 @@ protected function initializeContainer($rebuild = FALSE) {
     if ($session_manager_started) {
       $this->container->get('session_manager')->start();
     }
+
+    // The request stack is preserved accross container rebuilds. Reinject the
+    // new session into the master request if one was present before.
+    if (($request_stack = $this->container->get('request_stack', ContainerInterface::NULL_ON_INVALID_REFERENCE))) {
+      if ($request = $request_stack->getMasterRequest()) {
+        if ($request->hasSession()) {
+          $request->setSession($this->container->get('session'));
+        }
+      }
+    }
     \Drupal::setContainer($this->container);
 
     // If needs dumping flag was set, dump the container.
diff --git a/core/lib/Drupal/Core/Entity/ContentEntityBase.php b/core/lib/Drupal/Core/Entity/ContentEntityBase.php
index 62c464d..a767326 100644
--- a/core/lib/Drupal/Core/Entity/ContentEntityBase.php
+++ b/core/lib/Drupal/Core/Entity/ContentEntityBase.php
@@ -650,9 +650,9 @@ protected function initializeTranslation($langcode) {
     $translation->translations = &$this->translations;
     $translation->enforceIsNew = &$this->enforceIsNew;
     $translation->translationInitialize = FALSE;
-    // Reset language-dependent properties.
+    // The label is the only entity key that can change based on the language,
+    // so unset that in case it is currently set.
     unset($translation->entityKeys['label']);
-    $translation->typedData = NULL;
 
     return $translation;
   }
diff --git a/core/lib/Drupal/Core/EventSubscriber/DefaultExceptionHtmlSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/DefaultExceptionHtmlSubscriber.php
index 9535abf..f757aa7 100644
--- a/core/lib/Drupal/Core/EventSubscriber/DefaultExceptionHtmlSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/DefaultExceptionHtmlSubscriber.php
@@ -111,6 +111,11 @@ protected function makeSubrequest(GetResponseForExceptionEvent $event, $path, $s
         // Persist the 'exception' attribute to the subrequest.
         $sub_request->attributes->set('exception', $request->attributes->get('exception'));
 
+        // Carry over the session to the subrequest.
+        if ($session = $request->getSession()) {
+          $sub_request->setSession($session);
+        }
+
         $response = $this->httpKernel->handle($sub_request, HttpKernelInterface::SUB_REQUEST);
         $response->setStatusCode($status_code);
         $event->setResponse($response);
diff --git a/core/lib/Drupal/Core/Installer/InstallerServiceProvider.php b/core/lib/Drupal/Core/Installer/InstallerServiceProvider.php
index 96b5e73..83a7845 100644
--- a/core/lib/Drupal/Core/Installer/InstallerServiceProvider.php
+++ b/core/lib/Drupal/Core/Installer/InstallerServiceProvider.php
@@ -59,9 +59,6 @@ public function register(ContainerBuilder $container) {
     // @todo Convert installer steps into routes; add an installer.routing.yml.
     $definition = $container->getDefinition('router.builder');
     $definition->setClass('Drupal\Core\Installer\InstallerRouteBuilder');
-
-    // Remove dependencies on Drupal's default session handling.
-    $container->removeDefinition('authentication.cookie');
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Session/SessionManager.php b/core/lib/Drupal/Core/Session/SessionManager.php
index c354cec..2a143b7 100644
--- a/core/lib/Drupal/Core/Session/SessionManager.php
+++ b/core/lib/Drupal/Core/Session/SessionManager.php
@@ -338,7 +338,7 @@ protected function getSessionDataMask() {
     // Ignore attribute bags when they do not contain any data.
     foreach ($this->bags as $bag) {
       $key = $bag->getStorageKey();
-      $mask[$key] = empty($_SESSION[$key]);
+      $mask[$key] = !empty($_SESSION[$key]);
     }
 
     return array_intersect_key($mask, $_SESSION);
diff --git a/core/lib/Drupal/Core/StackMiddleware/Session.php b/core/lib/Drupal/Core/StackMiddleware/Session.php
new file mode 100644
index 0000000..b45a16e
--- /dev/null
+++ b/core/lib/Drupal/Core/StackMiddleware/Session.php
@@ -0,0 +1,63 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\StackMiddleware\Session.
+ */
+
+namespace Drupal\Core\StackMiddleware;
+
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Session\SessionInterface;
+use Symfony\Component\HttpKernel\HttpKernelInterface;
+
+/**
+ * Wrap session logic around a HTTP request.
+ */
+class Session implements HttpKernelInterface {
+
+  /**
+   * The wrapped HTTP kernel.
+   *
+   * @var \Symfony\Component\HttpKernel\HttpKernelInterface
+   */
+  protected $httpKernel;
+
+  /**
+   * The session.
+   *
+   * @var \Symfony\Component\HttpFoundation\Session\SessionInterface
+   */
+  protected $session;
+
+  /**
+   * Constructs a Session stack middleware object.
+   *
+   * @param \Symfony\Component\HttpKernel\HttpKernelInterface $http_kernel
+   *   The decorated kernel.
+   * @param \Symfony\Component\HttpFoundation\Session\SessionInterface $session
+   *   The session.
+   */
+  public function __construct(HttpKernelInterface $http_kernel, SessionInterface $session) {
+    $this->httpKernel = $http_kernel;
+    $this->session = $session;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = TRUE) {
+    if ($type === self::MASTER_REQUEST) {
+      $request->setSession($this->session);
+    }
+
+    $result = $this->httpKernel->handle($request, $type, $catch);
+
+    if ($type === self::MASTER_REQUEST && $request->hasSession()) {
+      $request->getSession()->save();
+    }
+
+    return $result;
+  }
+
+}
diff --git a/core/modules/comment/src/Controller/CommentController.php b/core/modules/comment/src/Controller/CommentController.php
index 84fbf72..69be36a 100644
--- a/core/modules/comment/src/Controller/CommentController.php
+++ b/core/modules/comment/src/Controller/CommentController.php
@@ -130,6 +130,10 @@ public function commentPermalink(Request $request, CommentInterface $comment) {
       // @todo: Cleaner sub request handling.
       $redirect_request = Request::create($entity->url(), 'GET', $request->query->all(), $request->cookies->all(), array(), $request->server->all());
       $redirect_request->query->set('page', $page);
+      // Carry over the session to the subrequest.
+      if ($session = $request->getSession()) {
+        $redirect_request->setSession($session);
+      }
       // @todo: Convert the pager to use the request object.
       $request->query->set('page', $page);
       return $this->httpKernel->handle($redirect_request, HttpKernelInterface::SUB_REQUEST);
diff --git a/core/modules/migrate/src/Entity/Migration.php b/core/modules/migrate/src/Entity/Migration.php
index ba563f1..f07ba40 100644
--- a/core/modules/migrate/src/Entity/Migration.php
+++ b/core/modules/migrate/src/Entity/Migration.php
@@ -14,6 +14,7 @@
 use Drupal\migrate\MigrateSkipRowException;
 use Drupal\migrate\Plugin\MigrateIdMapInterface;
 use Drupal\migrate\Plugin\RequirementsInterface;
+use Drupal\Component\Utility\NestedArray;
 
 /**
  * Defines the Migration entity.
@@ -406,6 +407,19 @@ public function setProcess(array $process) {
   /**
    * {@inheritdoc}
    */
+  public function setProcessOfProperty($field_name, $process, $merge = TRUE) {
+    if (isset($this->process[$field_name]) && is_array($process) && $merge) {
+      $this->process = NestedArray::mergeDeepArray([$this->process, [$field_name => $process]], TRUE);
+    }
+    else {
+      $this->process[$field_name] = $process;
+    }
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
   public function getSystemOfRecord() {
     return $this->systemOfRecord;
   }
diff --git a/core/modules/migrate/src/Entity/MigrationInterface.php b/core/modules/migrate/src/Entity/MigrationInterface.php
index 09cc770..ca9ac03 100644
--- a/core/modules/migrate/src/Entity/MigrationInterface.php
+++ b/core/modules/migrate/src/Entity/MigrationInterface.php
@@ -198,6 +198,23 @@ public function getProcess();
   public function setProcess(array $process);
 
   /**
+   * Set the process for an individual destination field.
+   *
+   * @param string $field_name
+   *   The field name of which to set the process.
+   * @param array $process
+   *   An array of process data.
+   * @param boolean $merge
+   *   (optional) TRUE if we should merge the process arrays otherwise FALSE.
+   *
+   * @return $this
+   *   The migration entity.
+   *
+   * @see Drupal\migrate_drupal\Plugin\migrate\load\LoadEntity::processLinkField().
+   */
+  public function setProcessOfProperty($field_name, $process, $merge = TRUE);
+
+  /**
    * Get the current system of record of the migration.
    *
    * @return string
diff --git a/core/modules/migrate_drupal/src/Plugin/migrate/load/LoadEntity.php b/core/modules/migrate_drupal/src/Plugin/migrate/load/LoadEntity.php
index c9db0e7..7de8883 100644
--- a/core/modules/migrate_drupal/src/Plugin/migrate/load/LoadEntity.php
+++ b/core/modules/migrate_drupal/src/Plugin/migrate/load/LoadEntity.php
@@ -98,9 +98,7 @@ public function loadMultiple(EntityStorageInterface $storage, array $sub_ids = N
                 $this->processTextField($field_name, $data, $migration);
                 break;
               default:
-                $process = $migration->getProcess();
-                $process[$field_name] = $field_name;
-                $migration->setProcess($process);
+                $migration->setProcessOfProperty($field_name, $field_name);
             }
           }
         }
@@ -134,12 +132,11 @@ protected function processTextField($field_name, $field_data, MigrationInterface
     $value_key = $field_data['db_storage'] ? $field_name : "$field_name/value";
     $format_key = $field_data['db_storage'] ? $field_name . '_format' : "$field_name/format" ;
 
-    $process = $migration->getProcess();
+    $migration->setProcessOfProperty("$field_name/value", $value_key);
 
-    $process["$field_name/value"] = $value_key;
     // See d6_user, signature_format for an example of the YAML that
     // represents this process array.
-    $process["$field_name/format"] = [
+    $process = [
       [
         'plugin' => 'static_map',
         'bypass' => TRUE,
@@ -153,8 +150,7 @@ protected function processTextField($field_name, $field_data, MigrationInterface
         'source' => $format_key,
       ],
     ];
-
-    $migration->setProcess($process);
+    $migration->setProcessOfProperty("$field_name/format", $process);
   }
 
   /**
@@ -168,8 +164,7 @@ protected function processTextField($field_name, $field_data, MigrationInterface
    *   The migration entity.
    */
   protected function processFileField($field_name, $field_data, MigrationInterface $migration) {
-    $process = $migration->getProcess();
-    $process[$field_name] = [
+    $process = [
       'plugin' => 'd6_cck_file',
       'source' => [
         $field_name,
@@ -177,7 +172,7 @@ protected function processFileField($field_name, $field_data, MigrationInterface
         $field_name . '_data',
       ],
     ];
-    $migration->setProcess($process);
+    $migration->setProcessOfProperty($field_name, $process);
   }
 
   /**
@@ -193,8 +188,7 @@ protected function processFileField($field_name, $field_data, MigrationInterface
   protected function processLinkField($field_name, $field_data, MigrationInterface $migration) {
     // Specifically process the link field until core is fixed.
     // @see https://www.drupal.org/node/2235457
-    $process = $migration->getProcess();
-    $process[$field_name] = [
+    $process = [
       'plugin' => 'd6_cck_link',
       'source' => [
         $field_name,
@@ -202,7 +196,7 @@ protected function processLinkField($field_name, $field_data, MigrationInterface
         $field_name . '_attributes',
       ],
     ];
-    $migration->setProcess($process);
+    $migration->setProcessOfProperty($field_name, $process);
   }
 
 }
diff --git a/core/modules/system/src/Tests/Entity/EntityTranslationTest.php b/core/modules/system/src/Tests/Entity/EntityTranslationTest.php
index 65bb740..2e8a3b3 100644
--- a/core/modules/system/src/Tests/Entity/EntityTranslationTest.php
+++ b/core/modules/system/src/Tests/Entity/EntityTranslationTest.php
@@ -7,7 +7,6 @@
 
 namespace Drupal\system\Tests\Entity;
 
-use Drupal\Component\Utility\String;
 use Drupal\Core\Language\LanguageInterface;
 use Drupal\entity_test\Entity\EntityTestMulRev;
 use Drupal\language\Entity\ConfigurableLanguage;
@@ -666,28 +665,4 @@ protected function doTestLanguageChange($entity_type) {
     }
   }
 
-  /**
-   * Tests how entity adapters work with translations.
-   */
-  function testEntityAdapter() {
-    $entity_type = 'entity_test';
-    $default_langcode = 'en';
-    $values[$default_langcode] = array('name' => $this->randomString());
-    $controller = $this->entityManager->getStorage($entity_type);
-    /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
-    $entity = $controller->create($values[$default_langcode]);
-
-    foreach ($this->langcodes as $langcode) {
-      $values[$langcode] = array('name' => $this->randomString());
-      $entity->addTranslation($langcode, $values[$langcode]);
-    }
-
-    $langcodes = array_merge(array($default_langcode), $this->langcodes);
-    foreach ($langcodes as $langcode) {
-      $adapter = $entity->getTranslation($langcode)->getTypedData();
-      $name = $adapter->get('name')->value;
-      $this->assertEqual($name, $values[$langcode]['name'], String::format('Name correctly retrieved from "@langcode" adapter', array('@langcode' => $langcode)));
-    }
-  }
-
 }
diff --git a/core/modules/system/tests/modules/session_test/session_test.services.yml b/core/modules/system/tests/modules/session_test/session_test.services.yml
index 281b09d..8ef2e20 100644
--- a/core/modules/system/tests/modules/session_test/session_test.services.yml
+++ b/core/modules/system/tests/modules/session_test/session_test.services.yml
@@ -1,6 +1,5 @@
 services:
   session_test.subscriber:
     class: Drupal\session_test\EventSubscriber\SessionTestSubscriber
-    arguments: ['@session_manager']
     tags:
       - { name: event_subscriber }
diff --git a/core/modules/system/tests/modules/session_test/src/EventSubscriber/SessionTestSubscriber.php b/core/modules/system/tests/modules/session_test/src/EventSubscriber/SessionTestSubscriber.php
index 9029093..a17cd5a 100644
--- a/core/modules/system/tests/modules/session_test/src/EventSubscriber/SessionTestSubscriber.php
+++ b/core/modules/system/tests/modules/session_test/src/EventSubscriber/SessionTestSubscriber.php
@@ -7,7 +7,6 @@
 
 namespace Drupal\session_test\EventSubscriber;
 
-use Drupal\Core\Session\SessionManagerInterface;
 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
 use Symfony\Component\HttpFoundation\RedirectResponse;
 use Symfony\Component\HttpKernel\KernelEvents;
@@ -20,13 +19,6 @@
 class SessionTestSubscriber implements EventSubscriberInterface {
 
   /**
-   * The session manager.
-   *
-   * @var \Drupal\Core\Session\SessionManagerInterface
-   */
-  protected $sessionManager;
-
-  /**
    * Stores whether $_SESSION is empty at the beginning of the request.
    *
    * @var bool
@@ -34,20 +26,14 @@ class SessionTestSubscriber implements EventSubscriberInterface {
   protected $emptySession;
 
   /**
-   * Constructs a new session test subscriber.
-   */
-  public function __construct(SessionManagerInterface $session_manager) {
-    $this->sessionManager = $session_manager;
-  }
-
-  /**
    * Set header for session testing.
    *
    * @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event
    *   The Event to process.
    */
   public function onKernelRequestSessionTest(GetResponseEvent $event) {
-    $this->emptySession = (int) !$this->sessionManager->start();
+    $session = $event->getRequest()->getSession();
+    $this->emptySession = (int) !($session && $session->start());
   }
 
   /**
diff --git a/core/modules/user/src/Entity/User.php b/core/modules/user/src/Entity/User.php
index 8be2e5e..a2c3a47 100644
--- a/core/modules/user/src/Entity/User.php
+++ b/core/modules/user/src/Entity/User.php
@@ -128,7 +128,7 @@ public function postSave(EntityStorageInterface $storage, $update = TRUE) {
       if ($this->pass->value != $this->original->pass->value) {
         $session_manager->delete($this->id());
         if ($this->id() == \Drupal::currentUser()->id()) {
-          $session_manager->regenerate();
+          \Drupal::service('session')->migrate();
         }
       }
 
diff --git a/core/modules/user/user.module b/core/modules/user/user.module
index 86c063d..e09ff03 100644
--- a/core/modules/user/user.module
+++ b/core/modules/user/user.module
@@ -609,7 +609,7 @@ function user_login_finalize(UserInterface $account) {
   // This is called before hook_user_login() in case one of those functions
   // fails or incorrectly does a redirect which would leave the old session
   // in place.
-  \Drupal::service('session_manager')->regenerate();
+  \Drupal::service('session')->migrate();
 
   \Drupal::moduleHandler()->invokeAll('user_login', array($account));
 }
@@ -840,7 +840,7 @@ function _user_cancel($edit, $account, $method) {
 function _user_cancel_session_regenerate() {
   // Regenerate the users session instead of calling session_destroy() as we
   // want to preserve any messages that might have been set.
-  \Drupal::service('session_manager')->regenerate();
+  \Drupal::service('session')->migrate();
 }
 
 /**
@@ -1484,6 +1484,10 @@ function user_logout() {
   \Drupal::moduleHandler()->invokeAll('user_logout', array($user));
 
   // Destroy the current session, and reset $user to the anonymous user.
+  // Note: In Symfony the session is intended to be destroyed with
+  // Session::invalidate(). Regrettably this method is currently broken and may
+  // lead to the creation of spurious session records in the database.
+  // @see https://github.com/symfony/symfony/issues/12375
   session_destroy();
 }
 
diff --git a/core/modules/user/user.services.yml b/core/modules/user/user.services.yml
index 3b6e451..8a4f4f0 100644
--- a/core/modules/user/user.services.yml
+++ b/core/modules/user/user.services.yml
@@ -17,7 +17,6 @@ services:
       - { name: access_check, applies_to: _user_is_logged_in }
   authentication.cookie:
     class: Drupal\Core\Authentication\Provider\Cookie
-    arguments: ['@session_manager']
     tags:
       - { name: authentication_provider, priority: 0 }
   cache_context.user:
