Print this page
5679 be_sort_list(): Possible null pointer dereference

Split Close
Expand all
Collapse all
          --- old/usr/src/lib/libbe/common/be_list.c
          +++ new/usr/src/lib/libbe/common/be_list.c
↓ open down ↓ 18 lines elided ↑ open up ↑
  19   19   * CDDL HEADER END
  20   20   */
  21   21  
  22   22  /*
  23   23   * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
  24   24   */
  25   25  
  26   26  /*
  27   27   * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
  28   28   * Copyright 2015 Toomas Soome <tsoome@me.com>
       29 + * Copyright 2015 Gary Mills
  29   30   */
  30   31  
  31   32  #include <assert.h>
  32   33  #include <libintl.h>
  33   34  #include <libnvpair.h>
  34   35  #include <libzfs.h>
  35   36  #include <stdio.h>
  36   37  #include <stdlib.h>
  37   38  #include <string.h>
  38   39  #include <strings.h>
↓ open down ↓ 21 lines elided ↑ open up ↑
  60   61   */
  61   62  static int be_add_children_callback(zfs_handle_t *zhp, void *data);
  62   63  static int be_get_list_callback(zpool_handle_t *, void *);
  63   64  static int be_get_node_data(zfs_handle_t *, be_node_list_t *, char *,
  64   65      const char *, char *, char *);
  65   66  static int be_get_zone_node_data(be_node_list_t *, char *);
  66   67  static int be_get_ds_data(zfs_handle_t *, char *, be_dataset_list_t *,
  67   68      be_node_list_t *);
  68   69  static int be_get_ss_data(zfs_handle_t *, char *, be_snapshot_list_t *,
  69   70      be_node_list_t *);
  70      -static void be_sort_list(be_node_list_t **,
       71 +static int be_sort_list(be_node_list_t **,
  71   72      int (*)(const void *, const void *));
  72   73  static int be_qsort_compare_BEs_name(const void *, const void *);
  73   74  static int be_qsort_compare_BEs_name_rev(const void *, const void *);
  74   75  static int be_qsort_compare_BEs_date(const void *, const void *);
  75   76  static int be_qsort_compare_BEs_date_rev(const void *, const void *);
  76   77  static int be_qsort_compare_BEs_space(const void *, const void *);
  77   78  static int be_qsort_compare_BEs_space_rev(const void *, const void *);
  78   79  static int be_qsort_compare_snapshots(const void *x, const void *y);
  79   80  static int be_qsort_compare_datasets(const void *x, const void *y);
  80   81  static void *be_list_alloc(int *, size_t);
↓ open down ↓ 55 lines elided ↑ open up ↑
 136  137  
 137  138          return (ret);
 138  139  }
 139  140  
 140  141  /*
 141  142   * Function:    be_sort
 142  143   * Description: Sort BE node list
 143  144   * Parameters:
 144  145   *              pointer to address of list head
 145  146   *              sort order type
 146      - * Returns:
 147      - *              nothing
      147 + * Return:
      148 + *              BE_SUCCESS - Success
      149 + *              be_errno_t - Failure
 148  150   * Side effect:
 149  151   *              node list sorted by name
 150  152   * Scope:
 151  153   *              Public
 152  154   */
 153      -void
      155 +int
 154  156  be_sort(be_node_list_t **be_nodes, int order)
 155  157  {
 156  158          int (*compar)(const void *, const void *) = be_qsort_compare_BEs_date;
 157  159  
 158  160          if (be_nodes == NULL)
 159      -                return;
      161 +                return (BE_ERR_INVAL);
 160  162  
 161  163          switch (order) {
 162  164          case BE_SORT_UNSPECIFIED:
 163  165          case BE_SORT_DATE:
 164  166                  compar = be_qsort_compare_BEs_date;
 165  167                  break;
 166  168          case BE_SORT_DATE_REV:
 167  169                  compar = be_qsort_compare_BEs_date_rev;
 168  170                  break;
 169  171          case BE_SORT_NAME:
↓ open down ↓ 4 lines elided ↑ open up ↑
 174  176                  break;
 175  177          case BE_SORT_SPACE:
 176  178                  compar = be_qsort_compare_BEs_space;
 177  179                  break;
 178  180          case BE_SORT_SPACE_REV:
 179  181                  compar = be_qsort_compare_BEs_space_rev;
 180  182                  break;
 181  183          default:
 182  184                  be_print_err(gettext("be_sort: invalid sort order %d\n"),
 183  185                      order);
 184      -                return;
      186 +                return (BE_ERR_INVAL);
 185  187          }
 186  188  
 187      -        be_sort_list(be_nodes, compar);
      189 +        return (be_sort_list(be_nodes, compar));
 188  190  }
 189  191  
 190  192  /* ******************************************************************** */
 191  193  /*                      Semi-Private Functions                          */
 192  194  /* ******************************************************************** */
 193  195  
 194  196  /*
 195  197   * Function:    _be_list
 196  198   * Description: This does the actual work described in be_list.
 197  199   * Parameters:
↓ open down ↓ 9 lines elided ↑ open up ↑
 207  209   *              be_errno_t - Failure
 208  210   * Scope:
 209  211   *              Semi-private (library wide use only)
 210  212   */
 211  213  int
 212  214  _be_list(char *be_name, be_node_list_t **be_nodes)
 213  215  {
 214  216          list_callback_data_t cb = { 0 };
 215  217          be_transaction_data_t bt = { 0 };
 216  218          int ret = BE_SUCCESS;
      219 +        int sret;
 217  220          zpool_handle_t *zphp;
 218  221          char *rpool = NULL;
 219  222          struct be_defaults be_defaults;
 220  223  
 221  224          if (be_nodes == NULL)
 222  225                  return (BE_ERR_INVAL);
 223  226  
 224  227          be_get_defaults(&be_defaults);
 225  228  
 226  229          if (be_find_current_be(&bt) != BE_SUCCESS) {
↓ open down ↓ 43 lines elided ↑ open up ↑
 270  273                              "exist\n"), be_name);
 271  274                  else
 272  275                          be_print_err(gettext("be_list: No BE's found\n"));
 273  276                  ret = BE_ERR_BE_NOENT;
 274  277          }
 275  278  
 276  279          *be_nodes = cb.be_nodes_head;
 277  280  
 278  281          free(cb.be_name);
 279  282  
 280      -        be_sort(be_nodes, BE_SORT_DATE);
      283 +        sret = be_sort(be_nodes, BE_SORT_DATE);
 281  284  
 282      -        return (ret);
      285 +        return ((ret == BE_SUCCESS) ? sret : ret);
 283  286  }
 284  287  
 285  288  /*
 286  289   * Function:    be_free_list
 287  290   * Description: Frees up all the data allocated for the list of BEs,
 288  291   *              datasets and snapshots returned by be_list.
 289  292   * Parameters:
 290  293   *              be_node - be_nodes_t structure returned from call to be_list.
 291  294   * Returns:
 292  295   *              none
↓ open down ↓ 384 lines elided ↑ open up ↑
 677  680          ZFS_CLOSE(zhp);
 678  681          return (ret);
 679  682  }
 680  683  
 681  684  /*
 682  685   * Function:    be_sort_list
 683  686   * Description: Sort BE node list
 684  687   * Parameters:
 685  688   *              pointer to address of list head
 686  689   *              compare function
 687      - * Returns:
 688      - *              nothing
      690 + * Return:
      691 + *              BE_SUCCESS - Success
      692 + *              be_errno_t - Failure
 689  693   * Side effect:
 690  694   *              node list sorted by name
 691  695   * Scope:
 692  696   *              Private
 693  697   */
 694      -static void
      698 +static int
 695  699  be_sort_list(be_node_list_t **pstart, int (*compar)(const void *, const void *))
 696  700  {
      701 +        int ret = BE_SUCCESS;
 697  702          size_t ibe, nbe;
 698  703          be_node_list_t *p = NULL;
 699  704          be_node_list_t **ptrlist = NULL;
      705 +        be_node_list_t **ptrtmp;
 700  706  
 701      -        if (pstart == NULL)
 702      -                return;
      707 +        if (pstart == NULL) /* Nothing to sort */
      708 +                return (BE_SUCCESS);
 703  709          /* build array of linked list BE struct pointers */
 704  710          for (p = *pstart, nbe = 0; p != NULL; nbe++, p = p->be_next_node) {
 705      -                ptrlist = realloc(ptrlist,
      711 +                ptrtmp = realloc(ptrlist,
 706  712                      sizeof (be_node_list_t *) * (nbe + 2));
      713 +                if (ptrtmp == NULL) { /* out of memory */
      714 +                        be_print_err(gettext("be_sort_list: memory "
      715 +                            "allocation failed\n"));
      716 +                        ret = BE_ERR_NOMEM;
      717 +                        goto free;
      718 +                }
      719 +                ptrlist = ptrtmp;
 707  720                  ptrlist[nbe] = p;
 708  721          }
 709      -        if (nbe == 0)
 710      -                return;
      722 +        if (nbe == 0) /* Nothing to sort */
      723 +                return (BE_SUCCESS);
 711  724          /* in-place list quicksort using qsort(3C) */
 712  725          if (nbe > 1)    /* no sort if less than 2 BEs */
 713  726                  qsort(ptrlist, nbe, sizeof (be_node_list_t *), compar);
 714  727  
 715  728          ptrlist[nbe] = NULL; /* add linked list terminator */
 716  729          *pstart = ptrlist[0]; /* set new linked list header */
 717  730          /* for each BE in list */
 718  731          for (ibe = 0; ibe < nbe; ibe++) {
 719  732                  size_t k, ns;   /* subordinate index, count */
 720  733  
 721  734                  /* rewrite list pointer chain, including terminator */
 722  735                  ptrlist[ibe]->be_next_node = ptrlist[ibe + 1];
 723  736                  /* sort subordinate snapshots */
 724  737                  if (ptrlist[ibe]->be_node_num_snapshots > 1) {
 725  738                          const size_t nmax = ptrlist[ibe]->be_node_num_snapshots;
 726  739                          be_snapshot_list_t ** const slist =
 727  740                              malloc(sizeof (be_snapshot_list_t *) * (nmax + 1));
 728  741                          be_snapshot_list_t *p;
 729  742  
 730      -                        if (slist == NULL)
      743 +                        if (slist == NULL) {
      744 +                                ret = BE_ERR_NOMEM;
 731  745                                  continue;
      746 +                        }
 732  747                          /* build array of linked list snapshot struct ptrs */
 733  748                          for (ns = 0, p = ptrlist[ibe]->be_node_snapshots;
 734  749                              ns < nmax && p != NULL;
 735  750                              ns++, p = p->be_next_snapshot) {
 736  751                                  slist[ns] = p;
 737  752                          }
 738  753                          if (ns < 2)
 739  754                                  goto end_snapshot;
 740  755                          slist[ns] = NULL; /* add terminator */
 741  756                          /* in-place list quicksort using qsort(3C) */
↓ open down ↓ 6 lines elided ↑ open up ↑
 748  763  end_snapshot:
 749  764                          free(slist);
 750  765                  }
 751  766                  /* sort subordinate datasets */
 752  767                  if (ptrlist[ibe]->be_node_num_datasets > 1) {
 753  768                          const size_t nmax = ptrlist[ibe]->be_node_num_datasets;
 754  769                          be_dataset_list_t ** const slist =
 755  770                              malloc(sizeof (be_dataset_list_t *) * (nmax + 1));
 756  771                          be_dataset_list_t *p;
 757  772  
 758      -                        if (slist == NULL)
      773 +                        if (slist == NULL) {
      774 +                                ret = BE_ERR_NOMEM;
 759  775                                  continue;
      776 +                        }
 760  777                          /* build array of linked list dataset struct ptrs */
 761  778                          for (ns = 0, p = ptrlist[ibe]->be_node_datasets;
 762  779                              ns < nmax && p != NULL;
 763  780                              ns++, p = p->be_next_dataset) {
 764  781                                  slist[ns] = p;
 765  782                          }
 766  783                          if (ns < 2) /* subordinate datasets < 2 - no sort */
 767  784                                  goto end_dataset;
 768  785                          slist[ns] = NULL; /* add terminator */
 769  786                          /* in-place list quicksort using qsort(3C) */
↓ open down ↓ 2 lines elided ↑ open up ↑
 772  789                          /* rewrite list pointer chain, including terminator */
 773  790                          ptrlist[ibe]->be_node_datasets = slist[0];
 774  791                          for (k = 0; k < ns; k++)
 775  792                                  slist[k]->be_next_dataset = slist[k + 1];
 776  793  end_dataset:
 777  794                          free(slist);
 778  795                  }
 779  796          }
 780  797  free:
 781  798          free(ptrlist);
      799 +        return (ret);
 782  800  }
 783  801  
 784  802  /*
 785  803   * Function:    be_qsort_compare_BEs_date
 786  804   * Description: compare BE creation times for qsort(3C)
 787  805   *              will sort BE list from oldest to most recent
 788  806   * Parameters:
 789  807   *              x,y - BEs with names to compare
 790  808   * Returns:
 791  809   *              positive if x>y, negative if y>x, 0 if equal
↓ open down ↓ 572 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX