gdb/corelow.c: fix use-after-free in build_file_mappings
authorLancelot SIX <lancelot.six@amd.com>
Wed, 31 May 2023 10:35:32 +0000 (11:35 +0100)
committerLancelot SIX <lancelot.six@amd.com>
Thu, 8 Jun 2023 13:18:09 +0000 (14:18 +0100)
In core_target::build_file_mappings, GDB tries to open files referenced
in the core dump.

The process goes like this:

    struct bfd *bfd = bfd_map[filename];
    if (bfd == nullptr)
      {
        bfd = bfd_map[filename]
          = bfd_openr (expanded_fname.get (), "binary");
        if (bfd == nullptr || !bfd_check_format (bfd, bfd_object))
          {
            if (bfd != nullptr)
              bfd_close (bfd);
            return;
          }
      }
    asection *sec = bfd_make_section_anyway (bfd, "load");
    ...

The problem is that if bfd_check_format fails, we close the bfd but keep
a reference to it in the bfd_map.

If the same filename appears another time in the NT_FILE note, we enter
this code again.  The second time, bfd_map[filename] is not nullptr and
we try to call bfd_make_section_anyway on an already closed BFD, which
is a use-after-free error.

This patch makes sure that the bfd is only saved in the bfd_map if it
got opened successfully.

This error got exposed by a recent change in BFD (014a602b86f "Don't
optimise bfd_seek to same position").  Since this change, opening a
coredump which contains mapping to some special files such as a DRI
render node (/dev/dri/renderD$NUM) exposes the issue.  This happens for
example for processes using AMDGPU devices to offload compute tasks.

Reviewed-By: John Baldwin <jhb@FreeBSD.org>
Approved-By: Andrew Burgess <aburgess@redhat.com>
gdb/corelow.c

index db489b4280e86193950af4c93bb5b930176e23d3..54def4198bc0363e4df9f511792b25b76cb500f7 100644 (file)
@@ -258,8 +258,7 @@ core_target::build_file_mappings ()
                return;
              }
 
-           bfd = bfd_map[filename] = bfd_openr (expanded_fname.get (),
-                                                "binary");
+           bfd = bfd_openr (expanded_fname.get (), "binary");
 
            if (bfd == nullptr || !bfd_check_format (bfd, bfd_object))
              {
@@ -284,6 +283,7 @@ core_target::build_file_mappings ()
               This can be checked before/after a core file detach via
               "maint info bfds".  */
            gdb_bfd_record_inclusion (core_bfd, bfd);
+           bfd_map[filename] = bfd;
          }
 
        /* Make new BFD section.  All sections have the same name,