Print this page
4005 libctf can't deal with extended sections

Split Close
Expand all
Collapse all
          --- old/usr/src/lib/libctf/common/ctf_lib.c
          +++ new/usr/src/lib/libctf/common/ctf_lib.c
↓ open down ↓ 185 lines elided ↑ open up ↑
 186  186  /*
 187  187   * Open the specified file descriptor and return a pointer to a CTF container.
 188  188   * The file can be either an ELF file or raw CTF file.  The caller is
 189  189   * responsible for closing the file descriptor when it is no longer needed.
 190  190   */
 191  191  ctf_file_t *
 192  192  ctf_fdopen(int fd, int *errp)
 193  193  {
 194  194          ctf_sect_t ctfsect, symsect, strsect;
 195  195          ctf_file_t *fp = NULL;
      196 +        size_t shstrndx, shnum;
 196  197  
 197  198          struct stat64 st;
 198  199          ssize_t nbytes;
 199  200  
 200  201          union {
 201  202                  ctf_preamble_t ctf;
 202  203                  Elf32_Ehdr e32;
 203  204                  GElf_Ehdr e64;
 204  205          } hdr;
 205  206  
↓ open down ↓ 42 lines elided ↑ open up ↑
 248  249           * do our own largefile ELF processing, and convert everything to
 249  250           * GElf structures so that clients can operate on any data model.
 250  251           */
 251  252          if (nbytes >= sizeof (Elf32_Ehdr) &&
 252  253              bcmp(&hdr.e32.e_ident[EI_MAG0], ELFMAG, SELFMAG) == 0) {
 253  254  #ifdef  _BIG_ENDIAN
 254  255                  uchar_t order = ELFDATA2MSB;
 255  256  #else
 256  257                  uchar_t order = ELFDATA2LSB;
 257  258  #endif
 258      -                GElf_Half i, n;
 259  259                  GElf_Shdr *sp;
 260  260  
 261  261                  void *strs_map;
 262      -                size_t strs_mapsz;
      262 +                size_t strs_mapsz, i;
 263  263                  const char *strs;
 264  264  
 265  265                  if (hdr.e32.e_ident[EI_DATA] != order)
 266  266                          return (ctf_set_open_errno(errp, ECTF_ENDIAN));
 267  267                  if (hdr.e32.e_version != EV_CURRENT)
 268  268                          return (ctf_set_open_errno(errp, ECTF_ELFVERS));
 269  269  
 270  270                  if (hdr.e32.e_ident[EI_CLASS] == ELFCLASS64) {
 271  271                          if (nbytes < sizeof (GElf_Ehdr))
 272  272                                  return (ctf_set_open_errno(errp, ECTF_FMT));
 273  273                  } else {
 274  274                          Elf32_Ehdr e32 = hdr.e32;
 275  275                          ehdr_to_gelf(&e32, &hdr.e64);
 276  276                  }
 277  277  
 278      -                if (hdr.e64.e_shstrndx >= hdr.e64.e_shnum)
      278 +                shnum = hdr.e64.e_shnum;
      279 +                shstrndx = hdr.e64.e_shstrndx;
      280 +
      281 +                /* Extended ELF sections */
      282 +                if ((shstrndx == SHN_XINDEX) || (shnum == 0)) {
      283 +                        if (hdr.e32.e_ident[EI_CLASS] == ELFCLASS32) {
      284 +                                Elf32_Shdr x32;
      285 +
      286 +                                if (pread64(fd, &x32, sizeof (x32),
      287 +                                    hdr.e64.e_shoff) != sizeof (x32))
      288 +                                        return (ctf_set_open_errno(errp,
      289 +                                            errno));
      290 +
      291 +                                shnum = x32.sh_size;
      292 +                                shstrndx = x32.sh_link;
      293 +                        } else {
      294 +                                Elf64_Shdr x64;
      295 +
      296 +                                if (pread64(fd, &x64, sizeof (x64),
      297 +                                    hdr.e64.e_shoff) != sizeof (x64))
      298 +                                        return (ctf_set_open_errno(errp,
      299 +                                            errno));
      300 +
      301 +                                shnum = x64.sh_size;
      302 +                                shstrndx = x64.sh_link;
      303 +                        }
      304 +                }
      305 +
      306 +                if (shstrndx >= shnum)
 279  307                          return (ctf_set_open_errno(errp, ECTF_CORRUPT));
 280  308  
 281      -                n = hdr.e64.e_shnum;
 282      -                nbytes = sizeof (GElf_Shdr) * n;
      309 +                nbytes = sizeof (GElf_Shdr) * shnum;
 283  310  
 284  311                  if ((sp = malloc(nbytes)) == NULL)
 285  312                          return (ctf_set_open_errno(errp, errno));
 286  313  
 287  314                  /*
 288  315                   * Read in and convert to GElf the array of Shdr structures
 289  316                   * from e_shoff so we can locate sections of interest.
 290  317                   */
 291  318                  if (hdr.e32.e_ident[EI_CLASS] == ELFCLASS32) {
 292  319                          Elf32_Shdr *sp32;
 293  320  
 294      -                        nbytes = sizeof (Elf32_Shdr) * n;
      321 +                        nbytes = sizeof (Elf32_Shdr) * shnum;
 295  322  
 296  323                          if ((sp32 = malloc(nbytes)) == NULL || pread64(fd,
 297  324                              sp32, nbytes, hdr.e64.e_shoff) != nbytes) {
 298  325                                  free(sp);
 299  326                                  return (ctf_set_open_errno(errp, errno));
 300  327                          }
 301  328  
 302      -                        for (i = 0; i < n; i++)
      329 +                        for (i = 0; i < shnum; i++)
 303  330                                  shdr_to_gelf(&sp32[i], &sp[i]);
 304  331  
 305  332                          free(sp32);
 306  333  
 307  334                  } else if (pread64(fd, sp, nbytes, hdr.e64.e_shoff) != nbytes) {
 308  335                          free(sp);
 309  336                          return (ctf_set_open_errno(errp, errno));
 310  337                  }
 311  338  
 312  339                  /*
 313  340                   * Now mmap the section header strings section so that we can
 314  341                   * perform string comparison on the section names.
 315  342                   */
 316      -                strs_mapsz = sp[hdr.e64.e_shstrndx].sh_size +
 317      -                    (sp[hdr.e64.e_shstrndx].sh_offset & ~_PAGEMASK);
      343 +                strs_mapsz = sp[shstrndx].sh_size +
      344 +                    (sp[shstrndx].sh_offset & ~_PAGEMASK);
 318  345  
 319  346                  strs_map = mmap64(NULL, strs_mapsz, PROT_READ, MAP_PRIVATE,
 320      -                    fd, sp[hdr.e64.e_shstrndx].sh_offset & _PAGEMASK);
      347 +                    fd, sp[shstrndx].sh_offset & _PAGEMASK);
 321  348  
 322  349                  strs = (const char *)strs_map +
 323      -                    (sp[hdr.e64.e_shstrndx].sh_offset & ~_PAGEMASK);
      350 +                    (sp[shstrndx].sh_offset & ~_PAGEMASK);
 324  351  
 325  352                  if (strs_map == MAP_FAILED) {
 326  353                          free(sp);
 327  354                          return (ctf_set_open_errno(errp, ECTF_MMAP));
 328  355                  }
 329  356  
 330  357                  /*
 331  358                   * Iterate over the section header array looking for the CTF
 332  359                   * section and symbol table.  The strtab is linked to symtab.
 333  360                   */
 334      -                for (i = 0; i < n; i++) {
      361 +                for (i = 0; i < shnum; i++) {
 335  362                          const GElf_Shdr *shp = &sp[i];
 336  363                          const GElf_Shdr *lhp = &sp[shp->sh_link];
 337  364  
 338      -                        if (shp->sh_link >= hdr.e64.e_shnum)
      365 +                        if (shp->sh_link >= shnum)
 339  366                                  continue; /* corrupt sh_link field */
 340  367  
 341      -                        if (shp->sh_name >= sp[hdr.e64.e_shstrndx].sh_size ||
 342      -                            lhp->sh_name >= sp[hdr.e64.e_shstrndx].sh_size)
      368 +                        if (shp->sh_name >= sp[shstrndx].sh_size ||
      369 +                            lhp->sh_name >= sp[shstrndx].sh_size)
 343  370                                  continue; /* corrupt sh_name field */
 344  371  
 345  372                          if (shp->sh_type == SHT_PROGBITS &&
 346  373                              strcmp(strs + shp->sh_name, _CTF_SECTION) == 0) {
 347  374                                  ctfsect.cts_name = strs + shp->sh_name;
 348  375                                  ctfsect.cts_type = shp->sh_type;
 349  376                                  ctfsect.cts_flags = shp->sh_flags;
 350  377                                  ctfsect.cts_size = shp->sh_size;
 351  378                                  ctfsect.cts_entsize = shp->sh_entsize;
 352  379                                  ctfsect.cts_offset = (off64_t)shp->sh_offset;
↓ open down ↓ 125 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX