diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module
index 43b962e..be76e09 100644
--- a/core/modules/comment/comment.module
+++ b/core/modules/comment/comment.module
@@ -203,10 +203,7 @@ function comment_menu() {
   );
   $items['comment/%comment'] = array(
     'title' => 'Comment permalink',
-    'page callback' => 'comment_permalink',
-    'page arguments' => array(1),
-    'access callback' => 'entity_page_access',
-    'access arguments' => array(1, 'view'),
+    'route_name' => 'comment_permalink',
   );
   $items['comment/%comment/view'] = array(
     'title' => 'View comment',
@@ -388,39 +385,6 @@ function comment_permission() {
 }
 
 /**
- * Redirects comment links to the correct page depending on comment settings.
- *
- * Since comments are paged there is no way to guarantee which page a comment
- * appears on. Comment paging and threading settings may be changed at any time.
- * With threaded comments, an individual comment may move between pages as
- * comments can be added either before or after it in the overall discussion.
- * Therefore we use a central routing function for comment links, which
- * calculates the page number based on current comment settings and returns
- * the full comment view with the pager set dynamically.
- *
- * @param \Drupal\comment\Plugin\Core\Entity\Comment $comment
- *   A comment entity.
- *
- * @return
- *   The comment listing set to the page on which the comment appears.
- */
-function comment_permalink(Comment $comment) {
-  if ($node = $comment->nid->entity) {
-    // Find the current display page for this comment.
-    $page = comment_get_display_page($comment->id(), $node->type);
-
-    // @todo: Cleaner sub request handling.
-    $request = Drupal::request();
-    $subrequest = Request::create('/node/' . $node->nid, 'GET', $request->query->all(), $request->cookies->all(), array(), $request->server->all());
-    $subrequest->query->set('page', $page);
-    // @todo: Convert the pager to use the request object.
-    $request->query->set('page', $page);
-    return Drupal::service('http_kernel')->handle($subrequest, HttpKernelInterface::SUB_REQUEST);
-  }
-  throw new NotFoundHttpException();
-}
-
-/**
  * Finds the most recent comments that are available to the current user.
  *
  * @param integer $number
diff --git a/core/modules/comment/comment.routing.yml b/core/modules/comment/comment.routing.yml
index eaaeba4..b62c118 100644
--- a/core/modules/comment/comment.routing.yml
+++ b/core/modules/comment/comment.routing.yml
@@ -12,3 +12,10 @@ comment_approve:
     entity_type: 'comment'
   requirements:
     _entity_access: 'comment.approve'
+
+comment_permalink:
+  pattern: '/comment/{comment}'
+  defaults:
+    _controller: '\Drupal\comment\Controller\CommentController::commentPermalink'
+  requirements:
+    _entity_access: 'comment.view'
diff --git a/core/modules/comment/lib/Drupal/comment/Controller/CommentController.php b/core/modules/comment/lib/Drupal/comment/Controller/CommentController.php
index 10e61ea..fe340cf 100644
--- a/core/modules/comment/lib/Drupal/comment/Controller/CommentController.php
+++ b/core/modules/comment/lib/Drupal/comment/Controller/CommentController.php
@@ -15,6 +15,8 @@
 use Symfony\Component\HttpFoundation\RedirectResponse;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
+use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
+use Symfony\Component\HttpKernel\HttpKernelInterface;
 
 /**
  * Controller for the comment entity.
@@ -31,19 +33,32 @@ class CommentController implements ControllerInterface {
   protected $urlGenerator;
 
   /**
+   * The HTTP kernel.
+   *
+   * @var \Symfony\Component\HttpKernel\HttpKernelInterface
+   */
+  protected $httpKernel;
+
+  /**
    * Constructs a CommentController object.
    *
    * @param \Drupal\Core\Routing\PathBasedGeneratorInterface $url_generator
    *   The url generator service.
+   * @param \Symfony\Component\HttpKernel\HttpKernelInterface $httpKernel
+   *   HTTP kernel to handle requests.
    */
-  public function __construct(PathBasedGeneratorInterface $url_generator) {
+  public function __construct(PathBasedGeneratorInterface $url_generator, HttpKernelInterface $httpKernel) {
     $this->urlGenerator = $url_generator;
+    $this->httpKernel = $httpKernel;
   }
   /**
    * {@inheritdoc}
    */
   public static function create(ContainerInterface $container) {
-    return new static($container->get('url_generator'));
+    return new static(
+      $container->get('url_generator'),
+      $container->get('http_kernel')
+    );
   }
 
   /**
@@ -77,4 +92,44 @@ public function commentApprove(Request $request, CommentInterface $comment) {
     return new RedirectResponse($url);
   }
 
+  /**
+   * Redirects comment links to the correct page depending on comment settings.
+   *
+   * Since comments are paged there is no way to guarantee which page a comment
+   * appears on. Comment paging and threading settings may be changed at any
+   * time. With threaded comments, an individual comment may move between pages
+   * as comments can be added either before or after it in the overall
+   * discussion. Therefore we use a central routing function for comment links,
+   * which calculates the page number based on current comment settings and
+   * returns the full comment view with the pager set dynamically.
+   *
+   * @param \Symfony\Component\HttpFoundation\Request $request
+   *   The request of the page.
+   * @param \Drupal\comment\CommentInterface $comment
+   *   A comment entity.
+   *
+   * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
+   * @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException
+   *
+   * @return \Symfony\Component\HttpFoundation\Response
+   *   The comment listing set to the page on which the comment appears.
+   */
+  public function commentPermalink(Request $request, CommentInterface $comment) {
+    if ($node = $comment->nid->entity) {
+      // Check access permissions for the node entity.
+      if (!$node->access('view')) {
+        throw new AccessDeniedHttpException();
+      }
+      // Find the current display page for this comment.
+      $page = comment_get_display_page($comment->id(), $node->type);
+      // @todo: Cleaner sub request handling.
+      $redirect_request = Request::create('/node/' . $node->nid, 'GET', $request->query->all(), $request->cookies->all(), array(), $request->server->all());
+      $redirect_request->query->set('page', $page);
+      // @todo: Convert the pager to use the request object.
+      $request->query->set('page', $page);
+      return $this->httpKernel->handle($redirect_request, HttpKernelInterface::SUB_REQUEST);
+    }
+    throw new NotFoundHttpException();
+  }
+
 }
